.venv deleted

ocr ready to test
This commit is contained in:
2025-11-29 12:29:08 +03:00
parent 449556c4e4
commit 91923b8616
2094 changed files with 562 additions and 370942 deletions

View File

@@ -3,22 +3,28 @@ from typing import List
from fastapi import FastAPI, File, UploadFile, HTTPException
from pydantic import BaseModel
import cv2
import numpy as np
# Настройка логгера
logging.basicConfig(level=logging.INFO)
# Импортируем модули
from imgproc import preprocess_image
from parser import parse_receipt_text, ParsedItem
from ocr import ocr_engine
# Импортируем новый модуль
from qr_manager import detect_and_decode_qr, fetch_data_from_api
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
app = FastAPI(title="RMSER OCR Service")
# DTO ответа (должно совпадать с Go-структурой RecognizedItem)
class RecognizedItem(BaseModel):
raw_name: str
amount: float
price: float
sum: float
app = FastAPI(title="RMSER OCR Service (Hybrid: QR + OCR)")
class RecognitionResult(BaseModel):
items: List[RecognizedItem]
source: str # 'qr_api' или 'ocr'
items: List[ParsedItem]
raw_text: str = ""
@app.get("/health")
def health_check():
@@ -27,47 +33,70 @@ def health_check():
@app.post("/recognize", response_model=RecognitionResult)
async def recognize_receipt(image: UploadFile = File(...)):
"""
Принимает изображение, 'распознает' его (пока заглушка)
и возвращает список позиций.
1. Попытка найти QR-код.
2. Если QR найден -> запрос к API -> возврат идеальных данных.
3. Если QR не найден -> Preprocessing -> OCR -> Regex Parsing.
"""
logger.info(f"Received file: {image.filename}, content_type: {image.content_type}")
if not image.content_type.startswith("image/"):
raise HTTPException(status_code=400, detail="File must be an image")
# Читаем байты (имитация обработки)
content = await image.read()
logger.info(f"Read {len(content)} bytes")
try:
# Читаем байты
content = await image.read()
# Конвертируем в numpy для работы (нужен и для QR, и для OCR)
nparr = np.frombuffer(content, np.uint8)
# Оригинальное изображение (цветное/серое)
original_cv_image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
# --- ЗАГЛУШКА (MOCK) ---
# Здесь в будущем будет вызов нейросети/Tesseract.
# Пока возвращаем хардкод, чтобы проверить интеграцию с Go.
mock_items = [
RecognizedItem(
raw_name="Молоко Петмол 3.2", # Это мы потом свяжем с реальным молоком
amount=5.0,
price=100.0,
sum=500.0
),
RecognizedItem(
raw_name="Хлеб Бородинский", # Этого, возможно, нет в базе (проверим обработку неизвестных)
amount=2.0,
price=45.50,
sum=91.0
),
RecognizedItem(
raw_name="НЕИЗВЕСТНЫЙ ТОВАР 123",
amount=1.0,
price=1000.0,
sum=1000.0
if original_cv_image is None:
raise HTTPException(status_code=400, detail="Invalid image data")
# --- ЭТАП 1: QR Code Strategy ---
logger.info("Attempting QR code detection...")
qr_raw = detect_and_decode_qr(original_cv_image)
if qr_raw:
logger.info("QR found! Fetching data from API...")
api_items = fetch_data_from_api(qr_raw)
if api_items:
logger.info(f"Successfully retrieved {len(api_items)} items via API.")
return RecognitionResult(
source="qr_api",
items=api_items,
raw_text=f"QR Content: {qr_raw}"
)
else:
logger.warning("QR found but API failed to return items. Falling back to OCR.")
else:
logger.info("QR code not found. Falling back to OCR.")
# --- ЭТАП 2: OCR Strategy (Fallback) ---
# 1. Image Processing (получаем бинарное изображение)
# Передаем исходные байты, так как функция внутри декодирует их заново
# (можно оптимизировать, но оставим совместимость с текущим кодом)
processed_img = preprocess_image(content)
# 2. OCR
full_text = ocr_engine.recognize(processed_img)
# 3. Parsing
ocr_items = parse_receipt_text(full_text)
return RecognitionResult(
source="ocr",
items=ocr_items,
raw_text=full_text
)
]
# -----------------------
return RecognitionResult(items=mock_items)
except Exception as e:
logger.error(f"Error processing request: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
# Запуск: python main.py
uvicorn.run(app, host="0.0.0.0", port=5000)