Files
PartsInquiry/backend/txm/app/server/main.py
2025-09-27 22:57:59 +08:00

104 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()