A Guide to Running ARM32 and ARM64 Python Barcode Readers in Docker Containers
Among the Python barcode SDKs available, only a few support ARM32 and ARM64 architectures. The Dynamsoft Barcode Reader stands out as the premier commercial SDK offering robust 1D and 2D barcode recognition for ARM32 and ARM64 devices. This article guides you through creating ARM32 and ARM64 emulated environments on Windows, enabling seamless barcode scanning implementation with the Dynamsoft Python Barcode SDK.
This article is Part 11 in a 11-Part Series.
- Part 1 - Detecting and Decoding QR Codes in Python with YOLO and Dynamsoft Barcode Reader
- Part 2 - How to a GUI Barcode Reader with Qt PySide6 on Raspberry Pi
- Part 3 - Advanced GUI Python Barcode and QR Code Reader for Windows, Linux, macOS and Rasberry Pi OS
- Part 4 - Advanced QR Code Recognition: Handling Inverted Colors, Perspective Distortion, and Grayscale Images
- Part 5 - Scanning QR Code from Desktop Screen with Qt and Python Barcode SDK
- Part 6 - Building an Online Barcode and QR Code Scanning App with Python Django
- Part 7 - Real-Time Barcode and QR Code Scanning with Webcam, OpenCV, and Python
- Part 8 - How to Build Flet Chat App with Barcode and Gemini APIs
- Part 9 - Comparing Barcode Scanning in Python: ZXing vs. ZBar vs. Dynamsoft Barcode Reader
- Part 10 - Python Ctypes: Invoking C/C++ Shared Library and Native Threading
- Part 11 - A Guide to Running ARM32 and ARM64 Python Barcode Readers in Docker Containers
Getting Started with Dynamsoft Python Barcode SDK
To get started, you can easily install the Dynamsoft Python Barcode SDK via pip:
pip install dbr
The SDK is compatible with Python 3.6 and above.
Supported Platforms
- Windows (x64)
- Linux (x64, ARM32, and ARM64)
- macOS (x64 and ARM64)
License Key Activation
After installation, you will need to obtain a valid license to activate the SDK:
from dbr import *
BarcodeReader.init_license(license_key)
Quick Start Guide
Here’s a simple example to get you up and running quickly:
from dbr import *
license_key = "Input your own license"
image = r"Please input your own image path"
BarcodeReader.init_license(license_key)
reader = BarcodeReader()
try:
text_results = reader.decode_file(image)
if text_results != None:
for text_result in text_results:
print("Barcode Format : ")
print(text_result.barcode_format_string)
print("Barcode Text : ")
print(text_result.barcode_text)
print("Localization Points : ")
print(text_result.localization_result.localization_points)
print("Exception : ")
print(text_result.exception)
print("-------------")
except BarcodeReaderError as bre:
print(bre)
Additional Resources
- Sample Code: Explore more examples on GitHub at Dynamsoft Barcode Reader Python Samples
- Online API Documentation: Visit the official documentation
- Visual Studio Code Extension: Enhance your development experience with the Dynamsoft Barcode Reader extension for Visual Studio Code.
Why ARM32 and ARM64 Emulated Environments?
Creating a Python barcode scanning application for ARM32 or ARM64 devices, such as Raspberry Pi or Jetson Nano, is made easier with emulated environments. These environments allow you to develop and test your code without the immediate need for physical ARM hardware, providing a flexible and convenient development workflow.
How to Create Docker ARM32 and ARM64 Images with Dynamsoft Barcode SDK on Windows
To emulate different CPU architectures such as ARM on a Windows machine, you can leverage QEMU, a popular open-source emulator. Additionally, multiarch/qemu-user-static is a Docker image that integrates with QEMU, enabling emulation of different CPU architectures within Docker containers.
Follow these steps to create Docker ARM32 and ARM64 images with Dynamsoft Barcode SDK on Windows:
- Install Docker Desktop for Windows: Start by installing Docker Desktop on your Windows machine.
-
Set Up QEMU for Cross-Platform Emulation: Install qemu-user-static:
docker run --rm --privileged multiarch/qemu-user-static:register --reset
-
Create Dockerfiles for ARM32 and ARM64: Write Dockerfiles that use ARM32 or ARM64 base images and install necessary tools like CMake, Dynamsoft Barcode Reader, OpenCV, and Pillow.
DockerfileArm32
FROM arm32v7/python RUN apt-get update && apt-get install -y cmake libgl1-mesa-glx RUN pip install dbr opencv-python pillow
DockerfileArm64
FROM arm64v8/python RUN apt-get update && apt-get install -y cmake libgl1-mesa-glx RUN pip install dbr opencv-python pillow
Note: The
opencv-python
package might take a long time to build on ARM32 as there is no pre-built wheel available. Consider usingpillow
as an alternative for image processing. -
Build Docker Images for ARM Architectures: Build the Docker images for ARM32 and ARM64:
docker build --platform linux/arm64 -f DockerfileArm64 -t <IMAGE-NAME> . docker build --platform linux/arm/v7 -f DockerfileArm32 -t <IMAGE-NAME> .
With these steps, you have successfully created Docker ARM32 and ARM64 images containing the Dynamsoft Python Barcode SDK. You can now proceed to write and run a barcode reader script within these containers.
Running Python Barcode Recognition in ARM32 and ARM64 Docker Containers
Single-board computers like Raspberry Pi and Jetson Nano often lack high-end hardware, which may impact barcode decoding speed for large images. A typical use case involves capturing low-resolution images (e.g., 640x480) from a USB camera and decoding QR codes in real-time.
Here’s how to simulate this process:
Capture Images from a USB Camera
Use the following Python script to capture frames from a USB camera and save them:
import cv2 as cv
from dbr import *
capture = cv.VideoCapture(0)
if not capture.isOpened():
print("Cannot open camera")
exit()
BarcodeReader.init_license("LICENSE-KEY")
reader = BarcodeReader()
index = 0
while True:
frame = capture.read()[1]
cv.imshow("frame", frame)
if cv.waitKey(1) == ord('q'):
break
results = reader.decode_buffer(frame)
if results != None and len(results) > 0:
cv.imwrite('images/' + str(index) + '.png', frame)
index += 1
if index == 30:
break
Decode the Captured Images
Next, use the following script to read the saved images using PIL
and decode them with Dynamsoft Barcode Reader:
#!/usr/bin/env python3
import os
from dbr import *
import dbr
import time
from PIL import Image
def main():
print('version: ' + dbr.__version__)
BarcodeReader.init_license("LICENSE-KEY")
reader = BarcodeReader()
reader.init_runtime_settings_with_file('faster.json', conflict_mode=EnumConflictMode.CM_OVERWRITE)
# read file list
folder = 'images'
target_dir = os.path.join(os.getcwd(), folder)
if os.path.exists(target_dir):
filelist = os.listdir('images')
index = 0
while index < 5:
file = filelist[index]
filapath = os.path.join(target_dir, file)
index += 1
with Image.open(filapath) as im:
try:
start_time = time.time()
results = reader.decode_buffer_manually(im.tobytes(), im.width, im.height, im.width * 3, EnumImagePixelFormat.IPF_RGB_888)
elapsed_time = time.time() - start_time
print(file + ", elapsed time: " + str(round(elapsed_time * 1000)) + "ms, " + ' results: ' + str(len(results)))
if results != None:
for result in results:
print(result.barcode_format_string + ': ' + result.barcode_text)
else:
print(' results: 0')
except Exception as err:
print(err)
if __name__ == '__main__':
main()
Running the Script in Docker
Mount the current folder to the Docker container and run the script:
docker run --platform linux/arm64 -it --rm -v ${pwd}:/usr/src/myapp -w /usr/src/myapp <IMAGE-NAME> python pillow_test.py
docker run --platform linux/arm/v7 -it --rm -v ${pwd}:/usr/src/myapp -w /usr/src/myapp <IMAGE-NAME> python pillow_test.py
Optimizing CPU Resources for Docker Containers
One critical factor to consider when running barcode decoding tasks in Docker containers is the impact of CPU resources on performance.
By default, Docker containers have unrestricted access to the host machine’s CPU cycles, which means they can use as many CPU resources as needed.
However, if you want to control and test the performance of your application under specific conditions, Docker allows you to limit the number of CPU cores available to a container using the –cpuset-cpus option. This can be useful for simulating scenarios where your application runs on hardware with limited processing power.
For instance, you can restrict the container to use only two CPU cores and observe how this affects the decoding speed:
docker run --cpuset-cpus="0,1" --platform linux/arm64 -it --rm -v ${pwd}:/usr/src/myapp -w /usr/src/myapp yushulx/dbr-arm64:1.0 python pillow_test.py
To verify the number of CPU cores available to the container, you can use the nproc
command:
docker run --cpuset-cpus="0,1" --platform linux/arm64 -it --rm -v ${pwd}:/usr/src/myapp -w /usr/src/myapp yushulx/dbr-arm64:1.0 nproc
2
In this example, the command should return 2
, confirming that the container is limited to two CPU cores.
Emulating Raspberry Pi with DockerPi
For a more realistic emulation, use dockerpi to simulate different Raspberry Pi models:
docker run -it lukechilds/dockerpi pi2
pi@raspberrypi:~$ lscpu
Architecture: armv7l
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
Vendor ID: ARM
Model: 5
Model name: Cortex-A7
Stepping: r0p5
CPU max MHz: 700.0000
CPU min MHz: 700.0000
BogoMIPS: 125.00
Flags: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm
docker run -it lukechilds/dockerpi pi3
pi@raspberrypi:~$ lscpu
Architecture: aarch64
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 1
Core(s) per socket: 4
Socket(s): 1
Vendor ID: ARM
Model: 4
Model name: Cortex-A53
Stepping: r0p4
CPU max MHz: 700.0000
CPU min MHz: 700.0000
BogoMIPS: 125.00
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
Source Code
https://github.com/yushulx/python-barcode-qrcode-sdk/tree/main/examples/official/9.x/arm32_arm64