2
This commit is contained in:
2
backend/txm/app/server/__init__.py
Normal file
2
backend/txm/app/server/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
BIN
backend/txm/app/server/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
backend/txm/app/server/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
backend/txm/app/server/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
backend/txm/app/server/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
BIN
backend/txm/app/server/__pycache__/main.cpython-311.pyc
Normal file
BIN
backend/txm/app/server/__pycache__/main.cpython-311.pyc
Normal file
Binary file not shown.
BIN
backend/txm/app/server/__pycache__/main.cpython-39.pyc
Normal file
BIN
backend/txm/app/server/__pycache__/main.cpython-39.pyc
Normal file
Binary file not shown.
103
backend/txm/app/server/main.py
Normal file
103
backend/txm/app/server/main.py
Normal 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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user