PaperPod/tests/test_refine.py
ilia a43ab20df6 Add crop refinement, finger removal, and local LLM naming
- vision/refine.py: tighten crops to the paper band (removes mat
  margins and hands beside receipts) and inpaint border-connected
  skin regions so fingers disappear from output
- llm/vision.py: identify documents with a local Ollama vision model
  (qwen2.5vl); extracts vendor/date/total/form code and flags quality
  issues (fingers, blur, glare); falls back to Tesseract when down
- pipeline: drop blank pages, dedupe consecutive captures of the same
  document, record refine/LLM fields in report and export summary
2026-07-08 18:23:50 -04:00

74 lines
2.4 KiB
Python

import cv2
import numpy as np
from paperpod.vision.refine import _density_band, refine_crop, skin_mask
def _crop_with_margin() -> np.ndarray:
"""White paper occupying the left 60% of a dark-mat crop."""
img = np.full((600, 500, 3), (60, 60, 60), dtype=np.uint8)
img[20:580, 20:300] = 245
return img
def _skin_patch(img: np.ndarray, y0: int, y1: int, x0: int, x1: int) -> None:
# BGR value squarely inside the YCrCb skin range.
img[y0:y1, x0:x1] = (120, 160, 210)
def test_tightens_to_paper_band():
result = refine_crop(_crop_with_margin(), remove_fingers=False)
assert result.tightened
h, w = result.image.shape[:2]
assert w < 350 # dark right margin removed
assert result.image.mean() > 150 # mostly paper now
def test_no_tighten_when_paper_fills_crop():
img = np.full((600, 500, 3), 245, dtype=np.uint8)
result = refine_crop(img, remove_fingers=False)
assert result.image.shape == img.shape
def test_skin_mask_detects_skin_tone():
img = _crop_with_margin()
_skin_patch(img, 0, 150, 350, 500)
mask = skin_mask(img)
assert (mask[50, 400] > 0) and (mask[300, 100] == 0)
def test_fingers_inpainted_when_touching_border():
img = _crop_with_margin()
_skin_patch(img, 0, 120, 100, 220) # finger reaching in from the top edge
result = refine_crop(img, tighten=False, remove_fingers=True)
assert result.fingers_removed
# Skin tone should be gone from the finger region.
assert skin_mask(result.image).sum() < skin_mask(img).sum() * 0.2
def test_interior_skin_tone_not_inpainted():
"""A skin-colored logo in the middle of the page must not be smeared."""
img = np.full((600, 500, 3), 245, dtype=np.uint8)
_skin_patch(img, 250, 300, 200, 260)
result = refine_crop(img, tighten=False, remove_fingers=True)
assert not result.fingers_removed
def test_density_band_ignores_far_edge_strip():
# Paper columns 0-59, gap, thin bright strip at the far edge.
density = np.zeros(100)
density[0:60] = 0.9
density[97:100] = 0.9
band = _density_band(density, threshold=0.25, gap_fraction=0.1)
assert band is not None
x0, x1 = band
assert x0 == 0 and x1 < 80
def test_density_band_bridges_dark_print_on_paper():
# Paper band with a dark printed banner (low density) in the middle.
density = np.full(100, 0.9)
density[40:48] = 0.05
band = _density_band(density, threshold=0.25, gap_fraction=0.15)
assert band == (0, 99)