Skip to content

Commit

Permalink
Add zxing zbar example
Browse files Browse the repository at this point in the history
  • Loading branch information
yushulx committed Aug 13, 2024
1 parent e46aa7f commit c6d3d37
Show file tree
Hide file tree
Showing 18 changed files with 338 additions and 0 deletions.
39 changes: 39 additions & 0 deletions examples/official/9.x/zxing_zbar/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# ZXing vs. ZBar vs. Dynamsoft Barcode Reader in Python
This repository provides a comparison of barcode recognition performance between three popular barcode scanning libraries: **ZXing**, **ZBar**, and [Dynamsoft Barcode Reader](https://pypi.org/project/dbr/).

This comment has been minimized.

Copy link
@axxel

axxel Sep 8, 2024

As the maintainer of the zxing-cpp project which you are apparently referring to with ZXing here, I'd like to point out that this name is technically misleading. While the zxing-cpp project started out as a C++ port of the java ZXing project, it has digressed a lot over the years. Some parts, like the EAN13 decoder that is benchmaked here are a complete rewrite. So to be more accurate, I'd like to suggest to either use the term ZXing-C++ or zxing-cpp here. Thanks.

This comment has been minimized.

Copy link
@yushulx

yushulx Sep 8, 2024

Author Owner

@axxel Thanks for your suggestion. I've updated the wording.

This comment has been minimized.

Copy link
@axxel

axxel Sep 9, 2024

Thanks for your effort. Interestingly, you chose neither of my two suggestions but it is still an improvement... ;).


## Dataset Download
Download the full dataset from the following link: https://drive.google.com/uc?id=1uThXXH8HiHAw6KlpdgcimBSbrvi0Mksf&export=download

## Installation

To get started, install the required dependencies:

```bash
pip install -r requirements.txt
```


## Usage
1. Obtain a [Dynamsoft Barcode Reader trial license](ttps://www.dynamsoft.com/customer/license/trialLicense) and update the code with the license key in `app.py`.

```python
BarcodeReader.init_license('LICENSE-KEY')
```

2. Run the Python script:

```bash
python app.py

Usage:
python app.py -i <image_file>
python app.py -d <folder_directory>
```

## Benchmark Results
Below is a visual comparison of the barcode recognition rates among ZXing, ZBar, and Dynamsoft Barcode Reader based on the dataset.

![barcode sdk benchmark](https://www.dynamsoft.com/codepool/img/2020/02/benchmark-barcode-sdk.png)

## Blog
[How to Use Python ZXing and Python ZBar on Windows 10](https://www.dynamsoft.com/codepool/python-zxing-zbar-barcode.html)
198 changes: 198 additions & 0 deletions examples/official/9.x/zxing_zbar/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import argparse
import pyzbar.pyzbar as zbar
from PIL import Image
import zxingcpp
from dbr import *
import time
import os
import data
import cv2


def zxing_decode(filename):
start = time.time()
img = cv2.imread(filename)
zxing_results = zxingcpp.read_barcodes(img)
elapsed_time = time.time() - start
if zxing_results != None:
for result in zxing_results:
print('ZXing: {}. Elapsed time: {}ms'.format(
result.text, int(elapsed_time * 1000)))
return zxing_results
else:
print('ZXing failed to decode {}'.format(filename))

return None


def zbar_decode(zbar_reader, filename):
start = time.time()
zbar_results = zbar.decode(Image.open(filename))
elapsed_time = time.time() - start
if len(zbar_results) > 0:
for zbar_result in zbar_results:
print('ZBar: {}. Elapsed time: {}ms'.format(
zbar_result.data.decode("utf-8"), int(elapsed_time * 1000)))

return zbar_results
else:
print('ZBar failed to decode {}'.format(filename))

return None


def dbr_decode(dbr_reader, filename):
try:
start = time.time()
dbr_results = dbr_reader.decode_file(filename)
elapsed_time = time.time() - start

if dbr_results != None:
for text_result in dbr_results:
# print(textResult["BarcodeFormatString"])
print('Dynamsoft Barcode Reader: {}. Elapsed time: {}ms'.format(
text_result.barcode_text, int(elapsed_time * 1000)))

return dbr_results
else:
print("DBR failed to decode {}".format(filename))
except Exception as err:
print("DBR failed to decode {}".format(filename))

return None


def dataset(directory=None, zbar_reader=None, dbr_reader=None):
if directory != None:
print(directory)
files = os.listdir(directory)
files = [f for f in files if f.endswith('.jpg') or f.endswith('.png')]
total_count = len(files)
if total_count == 0:
print('No image files')
return

# Create a .xlsx file
datafile = 'benchmark.xlsx'
wb = data.get_workbook(datafile)
index = 2

print('Total count of barcode image files: {}'.format(total_count))
zbar_count = 0
dbr_count = 0
zxing_count = 0

for filename in files:
file_path = os.path.join(directory, filename)
expected_result = filename.split('_')[0]

r1 = ''
r2 = ''
r3 = ''

# ZBar
if zbar_reader != None:
zbar_results = zbar_decode(zbar_reader, file_path)
if zbar_results != None:
for zbar_result in zbar_results:
zbar_text = zbar_result.data.decode("utf-8")
r1 = zbar_text
if r1 == expected_result:
zbar_count += 1
break
else:
print('Fail to decode {}'.format(filename))

# DBR
if dbr_reader != None:
textResults = dbr_decode(dbr_reader, file_path)
if textResults != None:
for textResult in textResults:
r2 = textResult.barcode_text
if r2 == expected_result:
dbr_count += 1
break
else:
print("DBR failed to decode {}".format(filename))

# ZXing
print('ZXing decoding {}'.format(filename))
zxing_results = zxing_decode(file_path)
if zxing_results != None:
for result in zxing_results:
r3 = result.text
if r3 == expected_result:
zxing_count += 1
else:
print('ZXing failed to decode {}'.format(filename))

# Add results to .xlsx file
data.update_row(wb, index, filename, expected_result, r1, r2, r3)
index += 1

# Test
# if index == 9:
# break

r1 = 0
r2 = 0
r3 = 0
if zbar_reader != None:
zbar_rate = zbar_count * 100 / total_count
r1 = '{0:.2f}%'.format(zbar_rate)
print('ZBar recognition rate: {0:.2f}%'.format(zbar_rate))

if dbr_reader != None:
dbr_rate = dbr_count * 100 / total_count
r2 = '{0:.2f}%'.format(dbr_rate)
print('DBR recognition rate: {0:.2f}%'.format(dbr_rate))

zxing_rate = zxing_count * 100 / total_count
r3 = '{0:.2f}%'.format(zxing_rate)
print('ZXing recognition rate: {0:.2f}%'.format(zxing_rate))

data.set_recognition_rate(wb, index, r1, r2, r3)
# Save data to .xlsx file
data.save_workbook(wb, datafile)


def main():
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", type=str,
help="path to input image")
ap.add_argument("-d", "--directory", type=str,
help="directory of image folder")
args = vars(ap.parse_args())

image = args["image"]
directory = args["directory"]
if image == None and directory == None:
print('''
Usage:
python app.py -i <image_file>
python app.py -d <folder_directory>
''')
return

# Initialize barcode reader
BarcodeReader.init_license(
'DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==')
dbr_reader = BarcodeReader()

if image != None:
# ZXing
zxing_decode(image)

# ZBar
zbar_decode(zbar, image)

# Dynamsoft Barcode Reader
dbr_decode(dbr_reader, image)

if directory != None:
dataset(directory,
zbar_reader=zbar, dbr_reader=dbr_reader)


if __name__ == "__main__":
main()
Binary file added examples/official/9.x/zxing_zbar/benchmark.xlsx
Binary file not shown.
97 changes: 97 additions & 0 deletions examples/official/9.x/zxing_zbar/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from openpyxl import utils
from openpyxl import Workbook
from openpyxl import load_workbook
from openpyxl.styles import Color, PatternFill

import os

# Define cell color
red = PatternFill(start_color='FFFF0000',
end_color='FFFF0000',
fill_type='solid')

green = PatternFill(start_color='FF00FF00',
end_color='FF00FF00',
fill_type='solid')

yellow = PatternFill(start_color='00FFFF00',
end_color='00FFFF00',
fill_type='solid')

passed = 'Passed'

def get_workbook(wb_name):
if os.path.isfile(wb_name):
wb = load_workbook(wb_name)
else:
wb = Workbook()
ws = wb.active
ws.title = 'Recognition Rate'
ws['A1'] = 'File Name'
# Set column width
ws.column_dimensions[utils.get_column_letter(1)].width = 25
ws['B1'] = 'Expected Results'
ws.column_dimensions[utils.get_column_letter(2)].width = 20
ws['C1'] = 'ZBar'
ws.column_dimensions[utils.get_column_letter(3)].width = 20
ws['D1'] = 'DBR'
ws.column_dimensions[utils.get_column_letter(4)].width = 20
ws['E1'] = 'ZXing'
ws.column_dimensions[utils.get_column_letter(5)].width = 20
return wb

def save_workbook(wb, wb_name):
if wb != None:
wb.save(wb_name)

def append_row(wb, filename=None, expected_results=None, zbar_results=None, dbr_results=None, ZXing_results=None):
ws = wb.active
ws.append([filename, expected_results, zbar_results, dbr_results, ZXing_results])

def update_row(wb, row_index, filename=None, expected_results=None, zbar_results=None, dbr_results=None, ZXing_results=None):
ws = wb.active
row = ws[row_index]
row[0].value = filename
row[1].value = expected_results
if zbar_results != None:
row[2].value = zbar_results
if zbar_results == expected_results:
row[2].fill = green
else:
row[2].fill = red

if dbr_results != None:
row[3].value = dbr_results
if dbr_results == expected_results:
row[3].fill = green
else:
row[3].fill = red

if ZXing_results != None:
row[4].value = ZXing_results
if ZXing_results == expected_results:
row[4].fill = green
else:
row[4].fill = red

def set_recognition_rate(wb, row_index, r1=None, r2=None, r3=None):
ws = wb.active
row = ws[row_index]
row[2].value = r1
row[3].value = r2
row[4].value = r3


# Test
# name = 'data.xlsx'
# wb = get_workbook(name)
# ws = wb.active
# index = 2
# update_row(wb, index, r'D:\python-zxing-zbar-dbr\dataset\20499525_2.jpg', '20499525', '20499525', '20499525', '20499521')
# index += 1
# set_recognition_rate(wb, index, '59.46%', '75.68%', '13.51%')
# save_workbook(wb, name)




Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions examples/official/9.x/zxing_zbar/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dbr
pyzbar
zxing-cpp
openpyxl

0 comments on commit c6d3d37

Please sign in to comment.