feat(phase1): implement OpenCV image processing pipeline

- Create ImageProcessor service with EXIF orientation detection
- Implement smart cropping via OpenCV contour detection (10% padding)
- Add text orientation detection using Hough line transform
- Resize and compress images to 1200px with 85% JPEG quality
- Generate 200px square thumbnails with center crop
- Fallback to Pillow if OpenCV fails
- Comprehensive test suite: 28 tests all passing
- File size validation (reject >10MB)
- Graceful error handling for corrupted/invalid images
- Update requirements.txt with opencv-python, piexif, python-magic
This commit is contained in:
2026-04-20 22:17:11 +03:00
parent 01321bf607
commit 3aafacab12
1068 changed files with 720366 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
__all__: list[str] = []
import cv2
import cv2.typing
import os
import typing as _typing
# Classes
class BarcodeDetector(cv2.GraphicalCodeDetector):
# Functions
@_typing.overload
def __init__(self) -> None: ...
@_typing.overload
def __init__(self, prototxt_path: str | os.PathLike[str], model_path: str | os.PathLike[str]) -> None: ...
@_typing.overload
def decodeWithType(self, img: cv2.typing.MatLike, points: cv2.typing.MatLike) -> tuple[bool, _typing.Sequence[str], _typing.Sequence[str]]: ...
@_typing.overload
def decodeWithType(self, img: cv2.UMat, points: cv2.UMat) -> tuple[bool, _typing.Sequence[str], _typing.Sequence[str]]: ...
@_typing.overload
def detectAndDecodeWithType(self, img: cv2.typing.MatLike, points: cv2.typing.MatLike | None = ...) -> tuple[bool, _typing.Sequence[str], _typing.Sequence[str], cv2.typing.MatLike]: ...
@_typing.overload
def detectAndDecodeWithType(self, img: cv2.UMat, points: cv2.UMat | None = ...) -> tuple[bool, _typing.Sequence[str], _typing.Sequence[str], cv2.UMat]: ...
def getDownsamplingThreshold(self) -> float: ...
def setDownsamplingThreshold(self, thresh: float) -> BarcodeDetector: ...
def getDetectorScales(self) -> _typing.Sequence[float]: ...
def setDetectorScales(self, sizes: _typing.Sequence[float]) -> BarcodeDetector: ...
def getGradientThreshold(self) -> float: ...
def setGradientThreshold(self, thresh: float) -> BarcodeDetector: ...