Sarvamangalak commited on
Commit
6c1f0e5
·
verified ·
1 Parent(s): 1fcb43a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +143 -31
app.py CHANGED
@@ -255,26 +255,82 @@ def preprocess_plate_for_ocr(plate_img):
255
  # ============================================================
256
  # OCR FUNCTION
257
  # ============================================================
 
 
 
258
 
259
  def read_license_plate(plate_img):
260
 
261
  if reader is None:
262
-
263
  return "OCR_UNAVAILABLE"
264
 
265
  try:
 
 
 
 
 
266
 
267
- processed = preprocess_plate_for_ocr(
268
- plate_img
 
 
269
  )
270
 
271
- if processed is None:
272
- return "UNKNOWN"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  results = reader.readtext(
275
- processed,
276
  detail=1,
277
- paragraph=False
 
278
  )
279
 
280
  if not results:
@@ -284,55 +340,111 @@ def read_license_plate(plate_img):
284
 
285
  for result in results:
286
 
287
- if len(result) >= 3:
 
288
 
289
- text = str(
290
- result[1]
291
- ).strip()
292
 
293
- confidence = float(
294
- result[2]
295
- )
 
296
 
297
- if confidence >= 0.20:
 
 
 
 
 
 
 
 
 
 
298
 
299
- candidates.append(
300
- (text, confidence)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
301
  )
302
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  if not candidates:
304
  return "UNKNOWN"
305
 
306
- # Select highest-confidence result
307
  candidates.sort(
308
  key=lambda x: x[1],
309
  reverse=True
310
  )
311
 
312
- text = candidates[0][0]
313
 
314
- # Remove unwanted characters
315
- cleaned = "".join(
316
- char
317
- for char in text
318
- if char.isalnum()
 
 
319
  )
320
 
321
- if cleaned == "":
322
- return "UNKNOWN"
323
-
324
- return cleaned.upper()
325
 
326
  except Exception as e:
327
 
328
  print(
329
- "OCR error:",
330
  e
331
  )
332
 
333
  return "UNKNOWN"
334
-
335
-
336
  # ============================================================
337
  # DUPLICATE VEHICLE CHECK
338
  # ============================================================
 
255
  # ============================================================
256
  # OCR FUNCTION
257
  # ============================================================
258
+ # ============================================================
259
+ # IMPROVED LICENSE PLATE OCR
260
+ # ============================================================
261
 
262
  def read_license_plate(plate_img):
263
 
264
  if reader is None:
 
265
  return "OCR_UNAVAILABLE"
266
 
267
  try:
268
+ # Convert PIL image to OpenCV image
269
+ img = np.array(plate_img)
270
+
271
+ if img.size == 0:
272
+ return "UNKNOWN"
273
 
274
+ # RGB -> Grayscale
275
+ gray = cv2.cvtColor(
276
+ img,
277
+ cv2.COLOR_RGB2GRAY
278
  )
279
 
280
+ # --------------------------------------------------------
281
+ # Enlarge plate image
282
+ # --------------------------------------------------------
283
+ gray = cv2.resize(
284
+ gray,
285
+ None,
286
+ fx=4,
287
+ fy=4,
288
+ interpolation=cv2.INTER_CUBIC
289
+ )
290
+
291
+ # --------------------------------------------------------
292
+ # Noise reduction
293
+ # --------------------------------------------------------
294
+ gray = cv2.bilateralFilter(
295
+ gray,
296
+ 9,
297
+ 75,
298
+ 75
299
+ )
300
+
301
+ # --------------------------------------------------------
302
+ # Improve contrast
303
+ # --------------------------------------------------------
304
+ clahe = cv2.createCLAHE(
305
+ clipLimit=2.0,
306
+ tileGridSize=(8, 8)
307
+ )
308
 
309
+ gray = clahe.apply(gray)
310
+
311
+ # --------------------------------------------------------
312
+ # Sharpen image
313
+ # --------------------------------------------------------
314
+ kernel = np.array([
315
+ [0, -1, 0],
316
+ [-1, 5, -1],
317
+ [0, -1, 0]
318
+ ])
319
+
320
+ sharpened = cv2.filter2D(
321
+ gray,
322
+ -1,
323
+ kernel
324
+ )
325
+
326
+ # --------------------------------------------------------
327
+ # OCR
328
+ # --------------------------------------------------------
329
  results = reader.readtext(
330
+ sharpened,
331
  detail=1,
332
+ paragraph=False,
333
+ allowlist="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
334
  )
335
 
336
  if not results:
 
340
 
341
  for result in results:
342
 
343
+ if len(result) < 3:
344
+ continue
345
 
346
+ text = str(result[1]).upper().strip()
 
 
347
 
348
+ confidence = float(result[2])
349
+
350
+ if confidence < 0.20:
351
+ continue
352
 
353
+ # ----------------------------------------------------
354
+ # Remove spaces and special characters
355
+ # ----------------------------------------------------
356
+ cleaned = "".join(
357
+ char
358
+ for char in text
359
+ if char.isalnum()
360
+ )
361
+
362
+ if cleaned == "":
363
+ continue
364
 
365
+ # ----------------------------------------------------
366
+ # Common OCR corrections
367
+ # ----------------------------------------------------
368
+ replacements = {
369
+ "O": "0",
370
+ "I": "1",
371
+ "L": "1",
372
+ "Z": "2",
373
+ "S": "5",
374
+ "B": "8"
375
+ }
376
+
377
+ # Apply corrections only when the character is
378
+ # surrounded by digits, where OCR commonly confuses
379
+ # letters and numbers.
380
+ corrected = ""
381
+
382
+ for i, char in enumerate(cleaned):
383
+
384
+ if char in replacements:
385
+
386
+ prev_char = (
387
+ cleaned[i - 1]
388
+ if i > 0
389
+ else ""
390
  )
391
 
392
+ next_char = (
393
+ cleaned[i + 1]
394
+ if i < len(cleaned) - 1
395
+ else ""
396
+ )
397
+
398
+ if (
399
+ prev_char.isdigit()
400
+ or next_char.isdigit()
401
+ ):
402
+ char = replacements[char]
403
+
404
+ corrected += char
405
+
406
+ # ----------------------------------------------------
407
+ # Keep realistic Indian plate length
408
+ # ----------------------------------------------------
409
+ if 4 <= len(corrected) <= 12:
410
+
411
+ candidates.append(
412
+ (
413
+ corrected,
414
+ confidence
415
+ )
416
+ )
417
+
418
  if not candidates:
419
  return "UNKNOWN"
420
 
421
+ # Highest-confidence OCR result
422
  candidates.sort(
423
  key=lambda x: x[1],
424
  reverse=True
425
  )
426
 
427
+ plate_number = candidates[0][0]
428
 
429
+ # --------------------------------------------------------
430
+ # Final cleanup
431
+ # --------------------------------------------------------
432
+ plate_number = "".join(
433
+ c
434
+ for c in plate_number
435
+ if c.isalnum()
436
  )
437
 
438
+ return plate_number.upper()
 
 
 
439
 
440
  except Exception as e:
441
 
442
  print(
443
+ "Improved OCR error:",
444
  e
445
  )
446
 
447
  return "UNKNOWN"
 
 
448
  # ============================================================
449
  # DUPLICATE VEHICLE CHECK
450
  # ============================================================