sundeep-news-scan/scratch_test_lines.py

81 lines
3.2 KiB
Python

import cv2
import numpy as np
import sys
from pathlib import Path
def test_lines(img_path, out_path):
img = cv2.imread(img_path)
if img is None:
print("Could not read image")
return
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 1. Use standard binary thresholding instead of adaptive to reduce noise from text
# Newspapers usually have very black lines on white background
_, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
# We want lines that are at least 300px long (a typical column width)
line_length = 300
# 2. Detect horizontal lines (MUST be thin: e.g., height <= 5px)
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (line_length, 1))
horizontal_lines_raw = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
# 3. Detect vertical lines (MUST be thin: e.g., width <= 5px)
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, line_length))
vertical_lines_raw = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
# 4. Filter contours to ensure they are actually THIN lines, not thick blocks/images
h_contours_raw, _ = cv2.findContours(horizontal_lines_raw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
v_contours_raw, _ = cv2.findContours(vertical_lines_raw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
h_contours = []
for cnt in h_contours_raw:
x, y, w, h = cv2.boundingRect(cnt)
if h <= 15: # Line must not be thicker than 15px
h_contours.append(cnt)
v_contours = []
for cnt in v_contours_raw:
x, y, w, h = cv2.boundingRect(cnt)
if w <= 15: # Line must not be thicker than 15px
v_contours.append(cnt)
print(f"Horizontal separators found: {len(h_contours)} (filtered from {len(h_contours_raw)})")
print(f"Vertical separators found: {len(v_contours)} (filtered from {len(v_contours_raw)})")
# 5. Create clean masks from only the filtered thin lines
clean_h_mask = np.zeros_like(thresh)
cv2.drawContours(clean_h_mask, h_contours, -1, 255, thickness=cv2.FILLED)
clean_v_mask = np.zeros_like(thresh)
cv2.drawContours(clean_v_mask, v_contours, -1, 255, thickness=cv2.FILLED)
grid = cv2.add(clean_h_mask, clean_v_mask)
rect_contours, _ = cv2.findContours(grid, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
box_count = 0
debug_img = img.copy()
for cnt in rect_contours:
epsilon = 0.02 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
if len(approx) == 4:
x, y, w, h = cv2.boundingRect(approx)
if w > 300 and h > 200:
box_count += 1
cv2.rectangle(debug_img, (x, y), (x+w, y+h), (255, 0, 255), 8)
print(f"Rectangular boxes found: {box_count}")
cv2.drawContours(debug_img, h_contours, -1, (0, 0, 255), 3) # Red for horizontal
cv2.drawContours(debug_img, v_contours, -1, (255, 0, 0), 3) # Blue for vertical
cv2.imwrite(out_path, debug_img)
print(f"Saved debug image to {out_path}")
if __name__ == "__main__":
test_lines(sys.argv[1], sys.argv[2])