DataMatrix Decoder - How to Decode 2D Barcodes from Images
0. Introduction
This How-To will teach you how to use the DataMatrix decoder script to automatically detect and read 2D barcodes (DataMatrix codes) from specific regions in an image.
The script works by:
- Loading a large image (4K resolution)
- Extracting pre-defined rectangular regions (boxes) from the image
- Using the zxing-cpp library to scan and decode DataMatrix codes in each box
- Displaying the results with visual outlines and decoded text
Important: This guide assumes you know:
- Basic Python syntax
- How image coordinates work in OpenCV (row, column system)
- What a 2D barcode (DataMatrix code) is
If you don’t know these things, that’s okay! Section 2 will explain the basics.
Do you already understand these concepts and want to jump straight to usage? Skip to section 5.
1. Requirements
For this How-To you will need:
- A computer with Windows / macOS / Linux
- Python (version 3.8 or higher recommended)
- The following Python libraries:
- OpenCV (cv2):
pip install opencv-python - zxing-cpp:
pip install zxing-cpp - NumPy (numpy):
pip install numpy
- OpenCV (cv2):
- Downloaded the zip file containing the image and python program:
Important to note: This zip file contains a FHD image (succesrate of 40%). The original image of 4k is to large to upload to this website but that one has a succesrate of 100%.
2. Key Concepts
2.1 What is a DataMatrix Code?
A DataMatrix code is a 2D barcode (similar to a QR code) that can store data in a small square. Key characteristics:
- Square or rectangular shape
- Made up of small black and white squares (like a checkerboard pattern)
- Can encode numbers, letters, and special characters
- Smaller and more space-efficient than traditional 1D barcodes
- Commonly used in manufacturing and logistics
Example of a DataMatrix code:
2.2 Image Coordinates in OpenCV
For more information about extracting ROI’s from frames read: “How to zoom in on an image or frame using opencv”
OpenCV stores images as 3D arrays: image[row, column, color_channel]
For extracting a rectangular region (a “box” or ROI - Region of Interest):
image[top:bottom, left:right]
Where:
top= row number (starting from top of image)bottom= row number (ending point)left= column number (starting from left of image)right= column number (ending point)
Important: Top-left corner is (0, 0), and coordinates increase downward and rightward.
2.3 What are ROI Boxes?
ROI stands for “Region of Interest”. In this script, a box is a rectangular area defined by four coordinates:
(top, bottom, left, right)
Example: (110, 196, 780, 866) means:
- From row 110 to row 196 (height = 86 pixels)
- From column 780 to column 866 (width = 86 pixels)
The script contains 50 pre-defined boxes that cover different areas of the 4K image.
2.4 Parallel Processing vs Sequential Processing
The decoder can work in two modes:
Sequential Mode (one at a time):
- Decodes each box one after another
- Simpler, uses less CPU
- Slower overall (good for testing)
Parallel Mode (multiple at once):
- Uses multiple processor threads to decode several boxes simultaneously
- Faster overall
- Uses more CPU resources
- The number of workers (threads) can be adjusted (2-16 recommended, more if you have a good computer)
3. How the Script Works
3.1 Complete Workflow
The script performs these steps in order:
- Load Image: Reads the 4K image file
- Load Boxes: Defines the rectangular regions (ROI boxes) to process
- Crop Boxes: Extracts each box from the original image
- Show Crops (optional): Displays all 50 crops in a grid to check if the ROI coordinates are correct
- Decode: Uses zxing-cpp library to scan and decode DataMatrix codes in each crop
- Show Results (optional): Draws the decoded data and visual outlines on the original image
- Print Statistics (optional): Shows success rate and performance metrics
3.2 The DataMatrixDecoder Class
The main class that handles all decoding:
DataMatrixDecoder
├── __init__() - Initialize the decoder with threading options
├── decode_datamatrices() - Scan all boxes and find DataMatrix codes
├── get_results() - Retrieve the decoded text and position data
└── __del__() - Cleanup (close thread pool)
Key parameters:
enable_parallel: Use multiple threads (True/False)num_workers: How many threads to use (2-16 recommended, more if you have a good computer)
3.3 Timing and Performance
The script includes built-in timing measurements:
- zxing-cpp decode time: How long the library took to scan and decode (measured in milliseconds)
- Total execution time: How long the entire process took
The performance benchmark tests different worker counts to find the optimal setting for your hardware.
4. Output Explanation
4.1 Decoded Text Colors
When viewing the result image:
- White rectangles: Successfully decoded DataMatrix codes
- Red rectangles: Failed to decode (no valid DataMatrix found in that box)
4.2 Result Information
For each successfully decoded box, you see:
- Box number (e.g., “Box 15”)
- Decoded text (the data from the barcode)
- Green outline showing exact position of the detected barcode
- X/Y coordinates and size of the barcode
4.3 Success Rate
If enabled, the script prints:
Success rate
============
Total boxes processed: 50
Success: 48 (96.0%)
Failed: 2 (4.0%)
5. Example Usage
5.1 Basic Setup
Make sure your folder contains:
decode_datamatrix.py (the main script)
raw_image_4k.png (your 4K image with DataMatrix codes)
5.2 Normal Operation
To run the script in normal mode (decode and visualize results):
# At the bottom of the script, change MODE to 1:
MODE = 1 # Normal operation
# Then adjust these settings:
decode_and_visualize_datamatrices(
window_size="FHD", # Display size: "4K", "FHD", or "QHD"
enable_parallel=True, # Use multiple threads (faster)
num_workers=5, # Number of worker threads
show_all_crops=False, # True: Shows 50 crop previews before decoding
show_final_result=True, # True: Shows result image with decoded data
print_decoder_results=False, # True: Prints timing for each box
print_detailed_info_results=False, # True: Prints decoded text per box
print_successrate=False, # True: Prints success rate statistics
)
5.3 Performance Benchmark Mode
To find the optimal number of workers for your hardware:
# At the bottom of the script, change MODE to 2:
MODE = 2 # Benchmark mode
# Then adjust these settings:
run_performance_benchmark(
start_workers=2, # Start testing with 2 workers
max_workers=16, # Test up to 16 workers
iterations_per_worker=5, # Run 5 iterations per worker count
debugging=False # True: Show crops and results during testing
)
The benchmark will show which worker count gives the best decode performance.
6. Understanding the Output
6.1 Console Output Example
When print_decoder_results=True and print_successrate=True:
Decoding datamatrices with zxing-cpp took 17.0291 milliseconds
Retrieving results from zxing-cpp decoder took 0.0191 milliseconds
Box 1: SUCCESS - Decoded: ABC123456 - Processed in 0.91 ms.
Box 2: FAIL - No code found - Processed in 0.83 ms.
Box 3: SUCCESS - Decoded: XYZ789012 - Processed in 0.81 ms.
...
Success rate
============
Total boxes processed: 50
Success: 48 (96.0%)
Failed: 2 (4.0%)
6.2 Visual Output Explanation
The result image shows:
- Green outline: Exact position of detected DataMatrix code
- White box: Rectangle around the ROI where a code was found
- Red box: Rectangle where no code was found
- Text labels: Box number and decoded text
7. Quick Reference - Settings Explained
| Setting | Values | Purpose |
|---|---|---|
window_size |
“4K”, “FHD”, “QHD” | Display size for result image |
enable_parallel |
True, False | Use multiple threads |
num_workers |
2-16 | Number of parallel threads |
show_all_crops |
True, False | Show 50 crop previews |
show_final_result |
True, False | Show result image with decoded data |
print_decoder_results |
True, False | Print timing info per box |
print_detailed_info_results |
True, False | Print decoded text per box |
print_successrate |
True, False | Print success statistics at the end |
