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] | |