Skip to content

Commit 66f2077

Browse files
committed
Updated
1 parent 1459cdc commit 66f2077

2 files changed

Lines changed: 105 additions & 12 deletions

File tree

examples/official/annotation_tool/probe_dbr_templates.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ def decode_image(image_path, template_name, template_path=None):
105105
return [], f"init_settings_from_file failed [{err}]: {msg}"
106106

107107
try:
108-
result = router.capture(str(image_path), template_name)
108+
cv_img = cv2.imread(str(image_path), cv2.IMREAD_COLOR)
109+
if cv_img is None:
110+
return [], f"Failed to load image with OpenCV: {image_path}"
111+
result = router.capture(cv_img, template_name)
109112
except Exception as exc:
110113
return [], str(exc)
111114

examples/official/annotation_tool/validate_dbr_template.py

Lines changed: 101 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pathlib import Path
44

55
import cv2
6+
import numpy as np
67

78
from dynamsoft_barcode_reader_bundle import CaptureVisionRouter, EnumPresetTemplate
89

@@ -29,6 +30,15 @@ def parse_args():
2930
action="store_true",
3031
help="Print the decode result as JSON.",
3132
)
33+
parser.add_argument(
34+
"--fallback-profile",
35+
choices=["none", "context-retry"],
36+
default="none",
37+
help=(
38+
"Retry a small prioritized set of app-level image variants when the first decode fails. "
39+
"'context-retry' favors context expansion and simple resampling/binarization retries."
40+
),
41+
)
3242
return parser.parse_args()
3343

3444

@@ -48,18 +58,59 @@ def resolve_template_name(template_file, cli_template_name):
4858
return templates[0]["Name"]
4959

5060

51-
def decode(image_path, template_file=None, template_name=None):
52-
ensure_dbr_license()
53-
router = CaptureVisionRouter()
54-
if template_file:
55-
err, msg = router.init_settings_from_file(str(template_file))
56-
if err != 0:
57-
print(f"[DBR] Template load failed ({err}): {msg}")
61+
def preprocess_image(cv_img, pad):
62+
return cv2.copyMakeBorder(
63+
cv_img,
64+
pad,
65+
pad,
66+
pad,
67+
pad,
68+
cv2.BORDER_CONSTANT,
69+
value=(255, 255, 255),
70+
)
5871

59-
cv_img = cv2.imread(str(image_path))
60-
if cv_img is None:
61-
raise RuntimeError(f"Failed to load image with OpenCV: {image_path}")
6272

73+
def build_fallback_attempts(cv_img, fallback_profile="none"):
74+
attempts = [("original", cv_img)]
75+
if fallback_profile == "none":
76+
return attempts
77+
78+
def add_attempt(name, image):
79+
for existing_name, _ in attempts:
80+
if existing_name == name:
81+
return
82+
attempts.append((name, image))
83+
84+
for extra_pad in (16, 24, 40):
85+
add_attempt(f"padded_{extra_pad}", preprocess_image(cv_img, extra_pad))
86+
87+
base = preprocess_image(cv_img, 16)
88+
nearest_2x = cv2.resize(base, None, fx=2, fy=2, interpolation=cv2.INTER_NEAREST)
89+
add_attempt("nearest_2x", nearest_2x)
90+
91+
nearest_4x = cv2.resize(base, None, fx=4, fy=4, interpolation=cv2.INTER_NEAREST)
92+
add_attempt("nearest_4x", nearest_4x)
93+
94+
gray4 = cv2.cvtColor(nearest_4x, cv2.COLOR_BGR2GRAY)
95+
otsu = cv2.threshold(gray4, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
96+
add_attempt("nearest_4x_otsu", otsu)
97+
add_attempt("nearest_4x_otsu_inverted", cv2.bitwise_not(otsu))
98+
99+
adaptive = cv2.adaptiveThreshold(
100+
gray4,
101+
255,
102+
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
103+
cv2.THRESH_BINARY,
104+
31,
105+
2,
106+
)
107+
add_attempt("nearest_4x_adaptive", adaptive)
108+
add_attempt("nearest_4x_adaptive_inverted", cv2.bitwise_not(adaptive))
109+
110+
return attempts
111+
112+
113+
def decode_with_router(router, cv_img, template_name):
63114
result = router.capture(cv_img, template_name)
64115

65116
items = []
@@ -81,6 +132,36 @@ def decode(image_path, template_file=None, template_name=None):
81132
return items
82133

83134

135+
def decode(image_path, template_file=None, template_name=None, fallback_profile="none"):
136+
ensure_dbr_license()
137+
router = CaptureVisionRouter()
138+
if template_file:
139+
err, msg = router.init_settings_from_file(str(template_file))
140+
if err != 0:
141+
print(f"[DBR] Template load failed ({err}): {msg}")
142+
143+
cv_img = cv2.imread(str(image_path))
144+
if cv_img is None:
145+
raise RuntimeError(f"Failed to load image with OpenCV: {image_path}")
146+
147+
attempts = build_fallback_attempts(cv_img, fallback_profile)
148+
best_items = []
149+
best_attempt = attempts[0][0]
150+
151+
for attempt_name, attempt_image in attempts:
152+
if isinstance(attempt_image, np.ndarray) and attempt_image.ndim == 2:
153+
attempt_image = cv2.cvtColor(attempt_image, cv2.COLOR_GRAY2BGR)
154+
155+
items = decode_with_router(router, attempt_image, template_name)
156+
if items:
157+
return items, attempt_name
158+
159+
if not best_items:
160+
best_attempt = attempt_name
161+
162+
return best_items, best_attempt
163+
164+
84165
def main():
85166
args = parse_args()
86167
image_path = Path(args.image).resolve()
@@ -94,7 +175,12 @@ def main():
94175
raise SystemExit(f"Template not found: {template_file}")
95176

96177
template_name = resolve_template_name(template_file, args.template_name)
97-
items = decode(image_path, template_file, template_name)
178+
items, attempt_name = decode(
179+
image_path,
180+
template_file,
181+
template_name,
182+
args.fallback_profile,
183+
)
98184

99185
if args.json:
100186
print(
@@ -103,6 +189,8 @@ def main():
103189
"image": str(image_path),
104190
"template_file": str(template_file) if template_file else None,
105191
"template_name": template_name,
192+
"fallback_profile": args.fallback_profile,
193+
"attempt": attempt_name,
106194
"items": items,
107195
},
108196
indent=2,
@@ -113,6 +201,8 @@ def main():
113201
print(f"image: {image_path}")
114202
print(f"template_file: {template_file if template_file else 'builtin'}")
115203
print(f"template_name: {template_name}")
204+
print(f"fallback_profile: {args.fallback_profile}")
205+
print(f"attempt: {attempt_name}")
116206
if not items:
117207
print("NO_RESULT")
118208
return

0 commit comments

Comments
 (0)