File size: 5,046 Bytes
b42373a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | import cv2
import os
import re
import time
from collections import defaultdict
BARCODE_DIR = "images/barcode"
PART_NUMBER_RE = re.compile(r'^0301BAB\d+N$')
def get_image_files():
files = sorted([f for f in os.listdir(BARCODE_DIR)
if f.lower().endswith(('.jpg', '.jpeg', '.png'))])
return files
def is_chassis(text):
text = text.strip()
return bool(text) and not PART_NUMBER_RE.match(text)
def decode_pyzbar(img, gray, thresh):
from pyzbar.pyzbar import decode
all_values = set()
for frame in [img, thresh]:
for d in decode(frame):
text = d.data.decode("utf-8").strip()
all_values.add(text)
return all_values
def decode_zxingcpp(img, gray, thresh):
import zxingcpp
all_values = set()
for frame in [gray, thresh]:
try:
results = zxingcpp.read_barcodes(frame)
for r in results:
text = r.text.strip()
if text:
all_values.add(text)
except Exception as e:
pass
return all_values
def decode_cv2barcode(img, gray, thresh):
all_values = set()
try:
detector = cv2.barcode.BarcodeDetector()
for frame in [gray, thresh]:
ok, decoded_info, decoded_type, points = detector.detectAndDecode(frame)
if ok and decoded_info is not None:
for text in decoded_info:
if text and text.strip():
all_values.add(text.strip())
except AttributeError:
pass
except Exception as e:
pass
return all_values
def main():
files = get_image_files()
print(f"Testing {len(files)} barcode images from {BARCODE_DIR}/\n")
decoders = {
"pyzbar": decode_pyzbar,
"zxing-cpp": decode_zxingcpp,
"cv2.barcode": decode_cv2barcode,
}
stats = {name: {"chassis": 0, "part_only": 0, "none": 0, "chassis_list": []}
for name in decoders}
timings = {name: 0.0 for name in decoders}
detail_rows = []
for fname in files:
path = os.path.join(BARCODE_DIR, fname)
img = cv2.imread(path)
if img is None:
continue
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
key = os.path.splitext(fname)[0]
row = {"file": fname}
for name, decoder_fn in decoders.items():
t0 = time.perf_counter()
all_values = decoder_fn(img, gray, thresh)
elapsed = time.perf_counter() - t0
timings[name] += elapsed
chassis_vals = {v for v in all_values if is_chassis(v)}
part_vals = {v for v in all_values if PART_NUMBER_RE.match(v)}
if chassis_vals:
stats[name]["chassis"] += 1
stats[name]["chassis_list"].append((key, chassis_vals))
row[name] = ", ".join(sorted(chassis_vals))
elif part_vals:
stats[name]["part_only"] += 1
row[name] = "(part# only)"
else:
stats[name]["none"] += 1
row[name] = "—"
detail_rows.append(row)
print("=" * 100)
print(f"{'File':<14} {'pyzbar':<20} {'zxing-cpp':<20} {'cv2.barcode':<20}")
print("-" * 100)
for row in detail_rows:
pyz = row.get("pyzbar", "—")
zxc = row.get("zxing-cpp", "—")
cv2b = row.get("cv2.barcode", "—")
print(f"{row['file']:<14} {pyz:<20} {zxc:<20} {cv2b:<20}")
total = len(files)
print("\n" + "=" * 100)
print("SUMMARY")
print("=" * 100)
print(f"{'Metric':<30} {'pyzbar':>12} {'zxing-cpp':>12} {'cv2.barcode':>12}")
print("-" * 70)
print(f"{'Chassis decoded':.<30} {stats['pyzbar']['chassis']:>12} {stats['zxing-cpp']['chassis']:>12} {stats['cv2.barcode']['chassis']:>12}")
print(f"{'Part# only (filtered out)':.<30} {stats['pyzbar']['part_only']:>12} {stats['zxing-cpp']['part_only']:>12} {stats['cv2.barcode']['part_only']:>12}")
print(f"{'Nothing decoded':.<30} {stats['pyzbar']['none']:>12} {stats['zxing-cpp']['none']:>12} {stats['cv2.barcode']['none']:>12}")
print(f"{'Total time (s)':.<30} {timings['pyzbar']:>12.2f} {timings['zxing-cpp']:>12.2f} {timings['cv2.barcode']:>12.2f}")
print("-" * 70)
print(f"{'CHASSIS DECODE RATE':.<30} {stats['pyzbar']['chassis']/total:>11.0%} {stats['zxing-cpp']['chassis']/total:>11.0%} {stats['cv2.barcode']['chassis']/total:>11.0%}")
print("=" * 100)
best_name = max(decoders.keys(), key=lambda n: stats[n]["chassis"])
print(f"\n★ Best decoder: {best_name} ({stats[best_name]['chassis']}/{total} chassis barcodes)")
for name in decoders:
if stats[name]["chassis_list"]:
print(f"\n {name} decoded chassis numbers:")
for key, vals in stats[name]["chassis_list"]:
print(f" {key}: {', '.join(sorted(vals))}")
if __name__ == "__main__":
main()
|