Initial commit: 包装审核 POC、Docker 与前后端

Made-with: Cursor
This commit is contained in:
2026-04-15 17:18:49 +08:00
commit bbb4dd43b3
74 changed files with 297415 additions and 0 deletions

View File

@@ -0,0 +1,103 @@
"""Detect and decode barcodes / QR codes from an image file using zxing-cpp."""
from __future__ import annotations
import logging
from dataclasses import dataclass, field
from pathlib import Path
logger = logging.getLogger(__name__)
# Human-readable names for zxing BarcodeFormat values
_FORMAT_NAMES: dict[str, str] = {
"QRCode": "二维码 (QR Code)",
"DataMatrix": "DataMatrix",
"Aztec": "Aztec",
"PDF417": "PDF417",
"MicroQRCode": "微型二维码",
"RMQRCode": "R型QR码",
"EAN8": "EAN-8",
"EAN13": "EAN-13",
"UPCE": "UPC-E",
"UPCA": "UPC-A",
"Code39": "Code 39",
"Code93": "Code 93",
"Code128": "Code 128",
"ITF": "ITF交叉二五码",
"Codabar": "Codabar",
"DataBar": "DataBar",
"DataBarExpanded": "DataBar Expanded",
"MaxiCode": "MaxiCode",
"DXFilmEdge": "DXFilmEdge",
"LinearCodes": "一维码",
"MatrixCodes": "矩阵码",
}
@dataclass
class BarcodeResult:
format: str # zxing format string, e.g. "EAN13"
format_label: str # Chinese-friendly label
text: str # decoded text / number
# bounding box in image pixels (top-left origin)
x0: int
y0: int
x1: int
y1: int
valid: bool # zxing isValid
def detect_barcodes(image_path: Path) -> list[BarcodeResult]:
"""Scan *image_path* for all barcodes and QR codes.
Returns a list of :class:`BarcodeResult`, one entry per detected code.
Returns an empty list when nothing is found or on error.
"""
try:
import zxingcpp
except ImportError:
logger.warning("zxing-cpp not installed; barcode detection skipped")
return []
try:
from PIL import Image
img = Image.open(image_path).convert("RGB")
except Exception as exc:
logger.warning("barcode_detector: cannot open image %s: %s", image_path, exc)
return []
try:
results = zxingcpp.read_barcodes(img)
except Exception as exc:
logger.warning("barcode_detector: zxing scan failed: %s", exc)
return []
output: list[BarcodeResult] = []
for r in results:
fmt_str = str(r.format).replace("BarcodeFormat.", "")
label = _FORMAT_NAMES.get(fmt_str, fmt_str)
# zxing-cpp position: r.position is a quadrilateral with four points
try:
pts = r.position
xs = [pts.top_left.x, pts.top_right.x, pts.bottom_right.x, pts.bottom_left.x]
ys = [pts.top_left.y, pts.top_right.y, pts.bottom_right.y, pts.bottom_left.y]
x0, y0, x1, y1 = int(min(xs)), int(min(ys)), int(max(xs)), int(max(ys))
except Exception:
x0 = y0 = x1 = y1 = 0
output.append(BarcodeResult(
format=fmt_str,
format_label=label,
text=r.text,
x0=x0, y0=y0, x1=x1, y1=y1,
valid=r.valid,
))
logger.info(
"barcode_detector: found %s text=%r bbox=(%d,%d,%d,%d)",
fmt_str, r.text, x0, y0, x1, y1,
)
if not output:
logger.info("barcode_detector: no barcode/QR found in %s", image_path.name)
return output