APIMONSTER commited on
Commit
3c9a517
·
verified ·
1 Parent(s): aec9462

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -31
app.py CHANGED
@@ -49,50 +49,68 @@ def normalize_ocr(recs):
49
  return first[1][0], float(first[1][1])
50
  return "", 0.0
51
 
 
52
  def format_plate(s: str) -> str:
53
- """‘DD AAA DDDD’ veya Unknown"""
54
  s = re.sub(r'[^A-Z0-9]', '', s.upper())
55
  m = re.match(r'^(\d{2})([A-Z]{1,3})(\d{2,4})$', s)
56
- return f"{m.group(1)} {m.group(2)} {m.group(3)}" if m else "Unknown"
57
-
58
- # ─── 5) Single-image inference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  def run_image(img, conf=0.25):
60
- # YOLO wants BGR
61
  bgr = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
62
  res = yolo(bgr, conf=conf)[0]
63
  out = bgr.copy()
64
 
65
  for box in res.boxes.xyxy.cpu().numpy().astype(int):
66
- x1,y1,x2,y2 = box
67
- crop = out[y1:y2, x1:x2]
68
- if crop.size == 0:
69
- continue
70
-
71
- # resize to OCR input
72
- plate_img = cv2.resize(crop, (128,32))
73
- # safe OCR
74
  try:
75
- recs = ocr.ocr(plate_img, det=False, cls=True)
76
- except Exception:
77
  recs = []
78
  txt, score = normalize_ocr(recs)
79
  plate = format_plate(txt)
80
  label = f"{plate} ({score:.2f})"
81
 
82
- # draw
83
- cv2.rectangle(out, (x1,y1),(x2,y2), (0,255,0), 2)
84
- cv2.putText(out, label, (x1, y1-8),
85
- cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2)
86
 
87
  return cv2.cvtColor(out, cv2.COLOR_BGR2RGB), f"{len(res.boxes)} plate(s) detected"
88
 
89
- # ─── 6) Video inference
90
  def run_video(video_file, conf=0.25):
91
  cap = cv2.VideoCapture(video_file)
92
  fps = cap.get(cv2.CAP_PROP_FPS) or 30
93
- w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
94
- h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
95
-
96
  out_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name
97
  writer = cv2.VideoWriter(out_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (w,h))
98
  records, idx = [], 0
@@ -101,24 +119,27 @@ def run_video(video_file, conf=0.25):
101
  ret, frame = cap.read()
102
  if not ret: break
103
  idx += 1; t = idx/fps
104
-
105
  res = yolo(frame, conf=conf)[0]
 
106
  for box in res.boxes.xyxy.cpu().numpy().astype(int):
107
- x1,y1,x2,y2 = box
108
- crop = frame[y1:y2, x1:x2]
109
- if crop.size == 0: continue
110
 
111
- plate_img = cv2.resize(crop, (128,32))
112
  try:
113
- recs = ocr.ocr(plate_img, det=False, cls=True)
114
  except:
115
  recs = []
116
  txt, score = normalize_ocr(recs)
117
  plate = format_plate(txt)
 
 
 
 
118
 
119
- if plate != "Unknown":
120
- records.append({"time_s":round(t,2),"plate":plate,"conf":round(score,3)})
121
 
 
122
  cv2.rectangle(frame, (x1,y1),(x2,y2), (0,255,0), 2)
123
  cv2.putText(frame, plate, (x1, y1-8),
124
  cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2)
@@ -130,6 +151,7 @@ def run_video(video_file, conf=0.25):
130
  json.dump(records, f, indent=2)
131
  return out_path, "Done"
132
 
 
133
  # ─── 7) Gradio UI
134
  with gr.Blocks() as demo:
135
  gr.Markdown("## 🚗 License Plate Detection + Recognition")
 
49
  return first[1][0], float(first[1][1])
50
  return "", 0.0
51
 
52
+ # Plaka format kontrolü (Türk plakası değilse orijinal yazı korunur)
53
  def format_plate(s: str) -> str:
 
54
  s = re.sub(r'[^A-Z0-9]', '', s.upper())
55
  m = re.match(r'^(\d{2})([A-Z]{1,3})(\d{2,4})$', s)
56
+ return f"{m.group(1)} {m.group(2)} {m.group(3)}" if m else f"RAW: {s}" if s else "Unknown"
57
+
58
+ # Perspektif düzeltme (tek sıra plaka kenarı düz olmayan durumlar için)
59
+ def correct_perspective(image, box):
60
+ x1, y1, x2, y2 = box
61
+ h, w = image.shape[:2]
62
+ margin = 5 # biraz dışarıdan al
63
+
64
+ x1 = max(0, x1 - margin)
65
+ y1 = max(0, y1 - margin)
66
+ x2 = min(w, x2 + margin)
67
+ y2 = min(h, y2 + margin)
68
+
69
+ crop = image[y1:y2, x1:x2]
70
+ if crop.size == 0: return None
71
+
72
+ # OCR input boyutuna perspektif düzeltme
73
+ src_pts = np.float32([
74
+ [0, 0], [crop.shape[1], 0],
75
+ [crop.shape[1], crop.shape[0]], [0, crop.shape[0]]
76
+ ])
77
+ dst_pts = np.float32([
78
+ [0, 0], [128, 0],
79
+ [128, 32], [0, 32]
80
+ ])
81
+ M = cv2.getPerspectiveTransform(src_pts, dst_pts)
82
+ warped = cv2.warpPerspective(crop, M, (128, 32))
83
+ return warped
84
+
85
+ # Güncellenmiş image fonksiyonu
86
  def run_image(img, conf=0.25):
 
87
  bgr = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
88
  res = yolo(bgr, conf=conf)[0]
89
  out = bgr.copy()
90
 
91
  for box in res.boxes.xyxy.cpu().numpy().astype(int):
92
+ warped = correct_perspective(out, box)
93
+ if warped is None: continue
94
+
 
 
 
 
 
95
  try:
96
+ recs = ocr.ocr(warped, det=False, cls=True)
97
+ except:
98
  recs = []
99
  txt, score = normalize_ocr(recs)
100
  plate = format_plate(txt)
101
  label = f"{plate} ({score:.2f})"
102
 
103
+ x1, y1, x2, y2 = box
104
+ cv2.rectangle(out, (x1, y1), (x2, y2), (0,255,0), 2)
105
+ cv2.putText(out, label, (x1, y1-8), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2)
 
106
 
107
  return cv2.cvtColor(out, cv2.COLOR_BGR2RGB), f"{len(res.boxes)} plate(s) detected"
108
 
109
+ # Güncellenmiş video fonksiyonu
110
  def run_video(video_file, conf=0.25):
111
  cap = cv2.VideoCapture(video_file)
112
  fps = cap.get(cv2.CAP_PROP_FPS) or 30
113
+ w, h = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
 
 
114
  out_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name
115
  writer = cv2.VideoWriter(out_path, cv2.VideoWriter_fourcc(*"mp4v"), fps, (w,h))
116
  records, idx = [], 0
 
119
  ret, frame = cap.read()
120
  if not ret: break
121
  idx += 1; t = idx/fps
 
122
  res = yolo(frame, conf=conf)[0]
123
+
124
  for box in res.boxes.xyxy.cpu().numpy().astype(int):
125
+ warped = correct_perspective(frame, box)
126
+ if warped is None: continue
 
127
 
 
128
  try:
129
+ recs = ocr.ocr(warped, det=False, cls=True)
130
  except:
131
  recs = []
132
  txt, score = normalize_ocr(recs)
133
  plate = format_plate(txt)
134
+ if plate.startswith("RAW:"):
135
+ raw_txt = plate[5:]
136
+ else:
137
+ raw_txt = plate
138
 
139
+ if raw_txt != "Unknown":
140
+ records.append({"time_s":round(t,2),"plate":raw_txt,"conf":round(score,3)})
141
 
142
+ x1, y1, x2, y2 = box
143
  cv2.rectangle(frame, (x1,y1),(x2,y2), (0,255,0), 2)
144
  cv2.putText(frame, plate, (x1, y1-8),
145
  cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2)
 
151
  json.dump(records, f, indent=2)
152
  return out_path, "Done"
153
 
154
+
155
  # ─── 7) Gradio UI
156
  with gr.Blocks() as demo:
157
  gr.Markdown("## 🚗 License Plate Detection + Recognition")