Spaces:
Paused
Paused
# signature_verification/signature_detector.py | |
import cv2 | |
import numpy as np | |
class SignatureDetector: | |
""" | |
Detects and crops a signature from a prescription image using refined OpenCV contour analysis. | |
This method is fast, offline, and does not require a pre-trained model. | |
""" | |
def crop(self, img: np.ndarray) -> np.ndarray | None: | |
if img is None: return None | |
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
blurred = cv2.GaussianBlur(gray, (5, 5), 0) | |
_, thresh = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) | |
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
if not contours: return None | |
height, width = img.shape[:2] | |
significant_contours = [] | |
for cnt in contours: | |
x, y, w, h = cv2.boundingRect(cnt) | |
# Filter for contours that are reasonably large and in the bottom 70% of the page | |
if w > 50 and h > 15 and y > height * 0.3: | |
if w < width * 0.8 and h < height * 0.4: | |
significant_contours.append(cnt) | |
if not significant_contours: return None | |
largest_contour = max(significant_contours, key=cv2.contourArea) | |
x, y, w, h = cv2.boundingRect(largest_contour) | |
padding = 15 | |
x1 = max(0, x - padding) | |
y1 = max(0, y - padding) | |
x2 = min(width, x + w + padding) | |
y2 = min(height, y + h + padding) | |
return img[y1:y2, x1:x2] | |