askakalsky commited on
Commit
b8d39bc
·
verified ·
1 Parent(s): 6d4968a

Upload src/detect.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. src/detect.py +65 -0
src/detect.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ROI detection: full passport image -> bounding box of the dotted series/number strip.
3
+ Uses a YOLO model fine-tuned on Ukrainian passport images (class: "Dotted").
4
+ """
5
+
6
+ from pathlib import Path
7
+ import cv2
8
+ import numpy as np
9
+
10
+
11
+ def load_detector(model_path: str | Path):
12
+ from ultralytics import YOLO
13
+ return YOLO(str(model_path))
14
+
15
+
16
+ def detect_roi(image: np.ndarray, model, conf: float = 0.30) -> tuple[int, int, int, int] | None:
17
+ """
18
+ Detect the dotted passport series/number strip in a full passport image.
19
+
20
+ Args:
21
+ image: BGR image (numpy array) or grayscale — will be converted as needed.
22
+ model: loaded YOLO model (from load_detector).
23
+ conf: minimum confidence threshold.
24
+
25
+ Returns:
26
+ (x1, y1, x2, y2) pixel coordinates of the best detection,
27
+ or None if nothing found.
28
+ """
29
+ results = model(image, conf=conf, verbose=False)
30
+ boxes = results[0].boxes
31
+
32
+ if boxes is None or len(boxes) == 0:
33
+ return None
34
+
35
+ # Pick highest-confidence box
36
+ best = boxes[boxes.conf.argmax()]
37
+ x1, y1, x2, y2 = map(int, best.xyxy[0].tolist())
38
+ return x1, y1, x2, y2
39
+
40
+
41
+ def crop_roi(image: np.ndarray, box: tuple[int, int, int, int],
42
+ padding: float = 0.05) -> np.ndarray:
43
+ """
44
+ Crop the ROI from the image with optional relative padding.
45
+
46
+ Args:
47
+ image: BGR or grayscale image.
48
+ box: (x1, y1, x2, y2)
49
+ padding: fraction of box size to add as margin on each side.
50
+
51
+ Returns:
52
+ Cropped numpy array (same channels as input).
53
+ """
54
+ h, w = image.shape[:2]
55
+ x1, y1, x2, y2 = box
56
+
57
+ pw = int((x2 - x1) * padding)
58
+ ph = int((y2 - y1) * padding)
59
+
60
+ x1 = max(0, x1 - pw)
61
+ y1 = max(0, y1 - ph)
62
+ x2 = min(w, x2 + pw)
63
+ y2 = min(h, y2 + ph)
64
+
65
+ return image[y1:y2, x1:x2]