This commit is contained in:
2025-09-27 22:57:59 +08:00
parent 8a458ff0a4
commit ed26244cdb
12585 changed files with 1914308 additions and 3474 deletions

View File

@@ -0,0 +1,2 @@

Binary file not shown.

View File

@@ -0,0 +1,103 @@
from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import JSONResponse
import uvicorn
import io
import time
import logging
import numpy as np
import cv2
from ..config_loader import load_config
from ..pipeline import EAN13Recognizer
from ..logging_utils import setup_logging
config = load_config()
setup_logging(config)
logger = logging.getLogger(__name__)
app = FastAPI(title="条形码识别端口 API", version="1.0.0")
recognizer = EAN13Recognizer()
@app.post("/recognize/ean13")
async def recognize_ean13(file: UploadFile = File(...)):
# 上传大小简易校验
t0 = time.time()
content = await file.read()
max_bytes = int(config["app"]["server"]["max_upload_mb"]) * 1024 * 1024
if len(content) > max_bytes:
logger.warning("/recognize/ean13 上传超限: size=%d, limit=%d", len(content), max_bytes)
raise HTTPException(status_code=413, detail="文件过大")
# 读取为图像
data = np.frombuffer(content, dtype=np.uint8)
img = cv2.imdecode(data, cv2.IMREAD_COLOR)
if img is None:
logger.error("/recognize/ean13 解码为图像失败, filename=%s, size=%d", getattr(file, 'filename', ''), len(content))
raise HTTPException(status_code=400, detail="无法解析为图像")
logger.debug("/recognize/ean13 收到图像: shape=%s, dtype=%s", getattr(img, 'shape', None), getattr(img, 'dtype', None))
merged = recognizer.recognize_any_from_image(img)
code = merged.get("ean13") or ""
resp = {
"code": code,
"type": "EAN13" if code else "",
"others": merged.get("others", []),
"message": "ok" if code or merged.get("others") else "未识别",
}
logger.info("/recognize/ean13 识别完成: code=%s, others=%d, cost_ms=%.1f", code, len(merged.get("others", []) or []), (time.time()-t0)*1000)
return JSONResponse(resp)
@app.post("/api/barcode/scan")
async def api_barcode_scan(file: UploadFile = File(...)):
t0 = time.time()
content = await file.read()
max_bytes = int(config["app"]["server"]["max_upload_mb"]) * 1024 * 1024
if len(content) > max_bytes:
logger.warning("/api/barcode/scan 上传超限: size=%d, limit=%d", len(content), max_bytes)
raise HTTPException(status_code=413, detail="文件过大")
data = np.frombuffer(content, dtype=np.uint8)
img = cv2.imdecode(data, cv2.IMREAD_COLOR)
if img is None:
logger.error("/api/barcode/scan 解码为图像失败, filename=%s, size=%d", getattr(file, 'filename', ''), len(content))
raise HTTPException(status_code=400, detail="无法解析为图像")
logger.debug("/api/barcode/scan 收到图像: shape=%s, dtype=%s", getattr(img, 'shape', None), getattr(img, 'dtype', None))
merged = recognizer.recognize_any_from_image(img)
ean13 = merged.get("ean13") or ""
others = merged.get("others", []) or []
# 优先返回 EAN-13否则回退到任意码制的第一个结果
if ean13:
resp = {
"success": True,
"barcodeType": "EAN13",
"barcode": ean13,
"others": others,
}
logger.info("/api/barcode/scan 命中 EAN13: code=%s, others=%d, cost_ms=%.1f", ean13, len(others), (time.time()-t0)*1000)
return JSONResponse(resp)
if isinstance(others, list) and others:
first = others[0] if isinstance(others[0], dict) else None
if first and first.get("code"):
resp = {
"success": True,
"barcodeType": first.get("type", ""),
"barcode": first.get("code", ""),
"others": others,
}
logger.info("/api/barcode/scan 命中非 EAN: type=%s, code=%s, cost_ms=%.1f", first.get("type", ""), first.get("code", ""), (time.time()-t0)*1000)
return JSONResponse(resp)
logger.warning("/api/barcode/scan 未识别, others=%d, cost_ms=%.1f", len(others), (time.time()-t0)*1000)
return JSONResponse({"success": False, "message": "无法识别,请重新上传"}, status_code=400)
def main():
host = config["app"]["server"]["host"]
port = int(config["app"]["server"]["port"])
logger.info("启动 FastAPI 服务器: %s:%d", host, port)
uvicorn.run("app.server.main:app", host=host, port=port, reload=False)
if __name__ == "__main__":
main()