Skip to content

Commit 40b6293

Browse files
committed
Added a benchmark project
1 parent 8aca4bb commit 40b6293

13 files changed

Lines changed: 13681 additions & 0 deletions
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Python Barcode Reader Benchmark
2+
3+
This project measures barcode decoding accuracy and speed for the ZXing Python package and Dynamsoft Barcode Reader Python on the public [BarBeR dataset](https://ditto.ing.unimore.it/barber/). Both readers are evaluated with the same image set, ground truth manifest, matching rules, and raw JSONL result protocol.
4+
5+
## Dependencies
6+
7+
- Python 3.9 or later
8+
- OpenCV Python
9+
- `zxing-cpp` Python package
10+
- `dynamsoft-capture-vision-bundle`
11+
- A valid [Dynamsoft Barcode Reader license](https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform)
12+
13+
Install dependencies:
14+
15+
```powershell
16+
python -m venv .venv
17+
.\.venv\Scripts\Activate.ps1
18+
pip install -r requirements.txt
19+
```
20+
21+
## Prepare the BarBeR Dataset
22+
23+
The expected dataset layout is:
24+
25+
```text
26+
BarBeR - Dataset/
27+
Annotations/VIA/
28+
dataset/images/
29+
```
30+
31+
Generate the benchmark manifest from the same image collection:
32+
33+
```powershell
34+
python benchmark.py audit `
35+
--images "D:/images/public-barcode-dataset/BarBeR - Dataset/dataset/images" `
36+
--annotations "D:/images/public-barcode-dataset/BarBeR - Dataset/Annotations/VIA" `
37+
--output manifests
38+
```
39+
40+
The audit validates image availability, payload structure, overlapping annotations, and exact duplicate image bytes. It writes `manifests/benchmark_manifest.jsonl`, `manifests/smoke_manifest.jsonl`, and `manifests/barber_source_files.json`.
41+
42+
## Run a Smoke Test
43+
44+
Store the Dynamsoft license in a local text file or set `DYNAMSOFT_LICENSE_KEY`.
45+
46+
```powershell
47+
python benchmark.py smoke `
48+
--images "D:/images/public-barcode-dataset/BarBeR - Dataset/dataset/images" `
49+
--manifest manifests/smoke_manifest.jsonl `
50+
--output results/smoke `
51+
--license-key-file "license-key.txt" `
52+
--repetitions 1
53+
```
54+
55+
## Run the Full Benchmark
56+
57+
```powershell
58+
python benchmark.py run `
59+
--images "D:/images/public-barcode-dataset/BarBeR - Dataset/dataset/images" `
60+
--manifest manifests/benchmark_manifest.jsonl `
61+
--output results/full `
62+
--license-key-file "license-key.txt" `
63+
--dbr-template ReadBarcodes_Default `
64+
--repetitions 1
65+
```
66+
67+
The command is resumable. It skips existing `(sample_id, decoder, repetition)` records in `results.jsonl`, then writes `summary.json` and `results.json`.
68+
69+
## Validate Results
70+
71+
```powershell
72+
python tools/validate_results.py `
73+
--results results/full/results.jsonl `
74+
--summary results/full/summary.json `
75+
--expected-images 7894 `
76+
--expected-ground-truth 8615 `
77+
--expected-repetitions 1
78+
```
79+
80+
## Benchmark Results
81+
82+
The current full run uses one repetition on 7,894 unique BarBeR images with zxing-cpp 3.1.1 and the Dynamsoft Capture Vision 3.6.1000 bundle. Recall is calculated as correct ground truth matches divided by 8,615 eligible ground truth instances. Precision is calculated as correct predictions divided by evaluated predictions, where evaluated predictions are `correct + wrong_text + wrong_format + extra_result`.
83+
84+
| Decoder | Correct | Recall | Precision | Image all-read rate | Mean decode time | Median decode time | P95 decode time |
85+
|---|---:|---:|---:|---:|---:|---:|---:|
86+
| Dynamsoft Barcode Reader 3.6.1000 | **7,476 / 8,615** | **86.78%** | 91.49% | **86.91%** | **63.84 ms** | 44.87 ms | **173.80 ms** |
87+
| ZXing-C++ 3.1.1 | 5,809 / 8,615 | 67.43% | 92.35% | 67.24% | 70.22 ms | 42.49 ms | 233.48 ms |
88+
89+
DBR read 1,667 more ground truth barcodes in this run and improved recall by 19.35 percentage points. ZXing-C++ had 0.86 percentage points higher precision. DBR's mean decoder call was 63.84 ms versus 70.22 ms for ZXing-C++, about 9.1% lower in this run.
90+
91+
### Python vs C++ on the Same BarBeR Images
92+
93+
The [C++ benchmark](https://www.dynamsoft.com/codepool/benchmark-barcode-reading-cpp-zxing-dynamsoft-barcode-reader.html) ran the identical 7,894-image manifest with ZXing-C++ 3.1.0 and Dynamsoft Barcode Reader 11.4.20.7177. This Python run uses ZXing-C++ 3.1.1 and the Dynamsoft Capture Vision 3.6.1000 bundle, whose bundled engine is Dynamsoft Barcode Reader 11.6.10.8373.
94+
95+
| Decoder | Run | Correct | Recall | Mean decode time |
96+
|---|---|---:|---:|---:|
97+
| Dynamsoft Barcode Reader | C++ 11.4.20.7177 | 7,444 / 8,615 | 86.41% | 70.08 ms |
98+
| Dynamsoft Barcode Reader | Python 11.6.10.8373 | 7,476 / 8,615 | 86.78% | 63.84 ms |
99+
| ZXing-C++ | C++ 3.1.0 | 5,855 / 8,615 | 67.96% | 74.09 ms |
100+
| ZXing-C++ | Python 3.1.1 | 5,809 / 8,615 | 67.43% | 70.22 ms |
101+
102+
On the same BarBeR images, the newer DBR engine in the Python bundle improved recall by 0.37 percentage points and cut mean decode time by about 8.9% compared with the C++ release used in the earlier article. ZXing-C++ 3.1.1 in Python read fewer barcodes than ZXing-C++ 3.1.0 in C++ on this dataset, while the Python binding and newer revision delivered a faster mean decode time in this run.
103+
104+
## Generate the HTML Report
105+
106+
Record the Python runtime environment:
107+
108+
```powershell
109+
python benchmark.py write-environment `
110+
--output configs/benchmark_environment.json `
111+
--repetitions 1 `
112+
--dbr-template ReadBarcodes_Default
113+
```
114+
115+
Generate the report:
116+
117+
```powershell
118+
python tools/generate_html_report.py `
119+
--inventory manifests/barber_source_files.json `
120+
--environment configs/benchmark_environment.json `
121+
--results results/full/results.jsonl `
122+
--results-json results/full/results.json `
123+
--summary results/full/summary.json `
124+
--output report/index.html
125+
```
126+
127+
## Matching Rules
128+
129+
- Ground truth and predictions are matched one to one as multisets.
130+
- The key is canonical barcode format plus exact normalized payload.
131+
- UPC-A and the equivalent zero-prefixed EAN-13 value are treated as equal.
132+
- DBR `CODE39EXTENDED` output is treated as `CODE_39` when the payload matches.
133+
- Barcode location is not part of the score.
134+
- Unsupported formats remain visible in coverage-adjusted metrics.
135+
- Decoder and input pipeline errors are explicit outcomes, not no-read results.
136+
137+

0 commit comments

Comments
 (0)