89 lines
4.7 KiB
Python
89 lines
4.7 KiB
Python
import unittest
|
|
|
|
import cv2
|
|
import numpy as np
|
|
import pymupdf
|
|
|
|
from copienator.auto_page_split import _analyse_page_full as analyse_page
|
|
from copienator.fast_page_split import analyse_page_fast, analyse_pdf_page_fast, quick_page_content
|
|
|
|
|
|
class FastPageSplitTests(unittest.TestCase):
|
|
def test_direct_pdf_strip_respects_rotation_and_crop_offsets(self):
|
|
image = np.full((1400, 2000, 3), 255, np.uint8)
|
|
for y in range(150, 650, 70):
|
|
for x in (150, 1300):
|
|
cv2.putText(image, 'answer x y z', (x, y),
|
|
cv2.FONT_HERSHEY_SIMPLEX, 1, (20, 20, 20), 2)
|
|
cv2.putText(image, 'x + y = z', (870, 1000),
|
|
cv2.FONT_HERSHEY_SIMPLEX, 1, (20, 20, 20), 2)
|
|
for rotation in (0, 90, 180, 270):
|
|
with self.subTest(rotation=rotation), pymupdf.open() as doc:
|
|
source = np.ascontiguousarray(np.rot90(image, rotation//90))
|
|
h,w = source.shape[:2]
|
|
page = doc.new_page(width=w*72/150+20,height=h*72/150+30)
|
|
box = pymupdf.Rect(10,15,w*72/150+10,h*72/150+15)
|
|
pix = pymupdf.Pixmap(pymupdf.csRGB,w,h,source.tobytes(),False)
|
|
page.insert_image(box,pixmap=pix)
|
|
page.set_cropbox(box)
|
|
page.set_rotation(rotation)
|
|
rendered = page.get_pixmap(dpi=150,alpha=False)
|
|
full = np.frombuffer(rendered.samples,np.uint8).reshape(rendered.height,rendered.width,3)
|
|
reference = analyse_page(full,150,'a3')
|
|
fast,overview = analyse_pdf_page_fast(page,150,'a3')
|
|
self.assertIsNone(fast['analysis']['fallback'])
|
|
self.assertEqual(fast['size_px'],reference['size_px'])
|
|
self.assertLess(overview.size,full.size)
|
|
self.assertEqual([o['keep'] for o in fast['outputs']],[True,True])
|
|
for a,b in zip(fast['outputs'],reference['outputs']):
|
|
self.assertLessEqual(max(abs(x-y) for x,y in zip(a['rect_px'],b['rect_px'])),2)
|
|
|
|
def test_plain_blank_and_sparse_pencil_use_full_detector(self):
|
|
for pencil in (False, True):
|
|
with self.subTest(pencil=pencil):
|
|
image = np.full((1200, 850, 3), 255, np.uint8)
|
|
if pencil:
|
|
cv2.putText(image, 'pencil', (100, 600),
|
|
cv2.FONT_HERSHEY_SIMPLEX, 1, (195, 195, 195), 2)
|
|
mask, early = quick_page_content(image, 150)
|
|
self.assertFalse(early)
|
|
expected = analyse_page(image, 150, 'a4')
|
|
actual = analyse_page_fast(image, 150, 'a4')
|
|
self.assertEqual(actual['outputs'][0]['keep'], expected['outputs'][0]['keep'])
|
|
self.assertEqual(actual['outputs'][0]['rect_px'], [0, 0, 850, 1200])
|
|
self.assertEqual(bool(mask.any()), pencil)
|
|
|
|
def test_compact_roi_maps_bounds_back_to_full_spread(self):
|
|
image = np.full((1400, 2000, 3), 255, np.uint8)
|
|
for y in range(150, 650, 70):
|
|
for x in (150, 1300):
|
|
cv2.putText(image, 'answer x y z', (x, y),
|
|
cv2.FONT_HERSHEY_SIMPLEX, 1, (20, 20, 20), 2)
|
|
cv2.putText(image, 'x + y = z', (870, 1000),
|
|
cv2.FONT_HERSHEY_SIMPLEX, 1, (20, 20, 20), 2)
|
|
for mirrored in (False, True):
|
|
with self.subTest(mirrored=mirrored):
|
|
rgb = image[:, ::-1].copy() if mirrored else image
|
|
reference = analyse_page(rgb, 150, 'a3')
|
|
fast = analyse_page_fast(rgb, 150, 'a3')
|
|
self.assertIsNone(fast['analysis']['fallback'])
|
|
self.assertEqual(fast['size_px'], [2000, 1400])
|
|
self.assertEqual(fast['extensions_mm'], reference['extensions_mm'])
|
|
self.assertEqual([o['rect_px'] for o in fast['outputs']],
|
|
[o['rect_px'] for o in reference['outputs']])
|
|
self.assertTrue(all(o['keep'] for o in fast['outputs']))
|
|
|
|
def test_ambiguous_or_wide_writing_falls_back_without_truncation(self):
|
|
image = np.full((700, 1000, 3), 255, np.uint8)
|
|
image[200:230, 300:650] = 20
|
|
reference = analyse_page(image, 100, 'a3')
|
|
fast = analyse_page_fast(image, 100, 'a3')
|
|
self.assertEqual(fast['analysis']['fallback'], 'full-spread')
|
|
self.assertEqual(fast['outputs'], reference['outputs'])
|
|
self.assertEqual(fast['crossings'], reference['crossings'])
|
|
|
|
def test_unknown_geometry_keeps_reference_behaviour(self):
|
|
image = np.full((400, 500, 3), 255, np.uint8)
|
|
self.assertEqual(analyse_page_fast(image, 100, 'unknown'),
|
|
analyse_page(image, 100, 'unknown'))
|