modest improvement to cropping (safer)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import math
|
||||
import shutil
|
||||
import tempfile
|
||||
from collections import defaultdict
|
||||
@@ -23,6 +24,7 @@ from copienator import (
|
||||
from copienator.filesystem import staged_directory
|
||||
|
||||
SQUARE = 1000 // 38
|
||||
ANSWER_TOP_PADDING_POINTS = 4 * 72 / 25.4
|
||||
Coordinate = tuple[str, int, int, int, int, int]
|
||||
ParsedCoordinate = tuple[str, str, int, int, int, int, int]
|
||||
|
||||
@@ -171,7 +173,15 @@ def _render_split_outputs(
|
||||
|
||||
for page_number in range(start_page, end_page + 1):
|
||||
page = document[page_number]
|
||||
y0 = (y_start / 1000) * page.rect.height if page_number == start_page else 0
|
||||
y0 = (
|
||||
math.floor(max(
|
||||
0,
|
||||
(y_start / 1000) * page.rect.height
|
||||
- ANSWER_TOP_PADDING_POINTS,
|
||||
))
|
||||
if page_number == start_page
|
||||
else 0
|
||||
)
|
||||
y1 = (end_y / 1000) * page.rect.height if page_number == end_page else page.rect.height
|
||||
clip = pymupdf.Rect(
|
||||
fraction_x0 * page.rect.width, y0,
|
||||
|
||||
@@ -110,7 +110,8 @@ def main() -> None:
|
||||
flush=True)
|
||||
(args.output/'report.json').write_text(json.dumps(rows, indent=2)+'\n')
|
||||
with (args.output/'report.csv').open('w') as stream:
|
||||
writer = csv.DictWriter(stream, fieldnames=list(rows[0]))
|
||||
fieldnames = list(dict.fromkeys(key for row in rows for key in row))
|
||||
writer = csv.DictWriter(stream, fieldnames=fieldnames)
|
||||
writer.writeheader()
|
||||
writer.writerows(rows)
|
||||
cards = []
|
||||
|
||||
@@ -65,13 +65,26 @@ def _large_blank_ink(gray: np.ndarray, clean: np.ndarray, dpi: float):
|
||||
n, labels, stats, centers = cv2.connectedComponentsWithStats(
|
||||
(residual > 35).astype(np.uint8), 8)
|
||||
keep = np.zeros(n, bool)
|
||||
xx = stats[1:, 0]
|
||||
ww, hh, area = stats[1:, 2], stats[1:, 3], stats[1:, 4]
|
||||
keep[1:] = ((area >= .8*px*px) & (np.minimum(ww, hh) >= .6*px)
|
||||
& (area / (ww*hh) > .3)
|
||||
& (np.maximum(ww, hh) < 4*np.minimum(ww, hh)))
|
||||
density = area / (ww*hh)
|
||||
shortest, longest = np.minimum(ww, hh), np.maximum(ww, hh)
|
||||
compact_ink = ((area >= .8*px*px) & (shortest >= .6*px)
|
||||
& (density > .3) & (longest < 4*shortest))
|
||||
# Ruling suppression can fragment faint pencil handwriting into sparse,
|
||||
# elongated components. Admit those moderately more readily in the central
|
||||
# 80% of the sheet. The outermost 9% deliberately uses a stricter filter:
|
||||
# punched holes, torn binding edges, and page numbers usually occur there.
|
||||
center_x = xx + ww/2
|
||||
central = (center_x > width*.1) & (center_x < width*.9)
|
||||
central_ink = (central & (area >= .55*px*px) & (shortest >= .45*px)
|
||||
& (density > .18) & (longest < 6*shortest))
|
||||
outer = (center_x < width*.09) | (center_x > width*.91)
|
||||
outer_ink = (outer & (area >= 1.2*px*px) & (shortest >= .8*px)
|
||||
& (density >= .4) & (longest < 3*shortest))
|
||||
keep[1:] = np.where(outer, outer_ink, compact_ink | central_ink)
|
||||
# Use side columns as a prior, then require repeated size and alignment. An
|
||||
# isolated note in the same column remains eligible to protect the margin.
|
||||
xx = stats[1:, 0]
|
||||
candidates = np.flatnonzero(
|
||||
((xx < 15*px) | (xx+ww > width-15*px))
|
||||
& (ww > px) & (ww < 9*px) & (hh > px) & (hh < 12*px)) + 1
|
||||
|
||||
Reference in New Issue
Block a user