adding a new numberplate extraction stauts, and image saving for the yolo model output
This commit is contained in:
parent
d7474a11ab
commit
d543713082
6 changed files with 47 additions and 17 deletions
|
|
@ -4,10 +4,3 @@
|
|||
* -- `mkdir db`
|
||||
Number Plate recognition, also called License Plate realization or recognition using image processing methods is a potential research area in smart cities and the Internet of Things. An exponential increase in the number of vehicles necessitates the use of automated systems to maintain vehicle information for various purposes.
|
||||
|
||||

|
||||
|
||||
## Implementation:
|
||||
In the proposed algorithm an efficient method for recognition of Indian vehicle number plates has been devised. We are able to deal with noisy, low illuminated, cross angled, non-standard font number plates. This work employs several image processing techniques such as, morphological transformation, Gaussian smoothing, Gaussian thresholding and Sobel edge detection method in the pre-processing stage, afterwhich number plate segmentation, contours are applied by border following and contours are filtered based on character dimensions and spatial localization. Finally we apply Optical Character Recognition (OCR) to recognize the extracted characters. The detected texts are stored in the database, further which they are sorted and made available for searching.
|
||||
|
||||
This project will work efficiently in recognizing owner's vehicle in small Institutions/Housing societies/Apartments. We can further modify the code to use it in other areas where ANPR is necessary.
|
||||
|
||||
|
|
|
|||
18
anpr_main.py
18
anpr_main.py
|
|
@ -3,7 +3,7 @@
|
|||
#* File Name : anpr_yolo_v8.py
|
||||
#* Purpose :
|
||||
#* Creation Date : 21-04-2025
|
||||
#* Last Modified : Thu 01 May 2025 08:27:26 PM CEST
|
||||
#* Last Modified : Thu 01 May 2025 11:45:10 PM CEST
|
||||
#* Created By : Yaay Nands
|
||||
#_._._._._._._._._._._._._._._._._._._._._.#
|
||||
import glob
|
||||
|
|
@ -43,10 +43,12 @@ SQL = {
|
|||
'INSERT_NUMBERS':
|
||||
'INSERT INTO numberplates (model, filename, ts, ) VALUES (? , ?, ?)',
|
||||
'UPDATE_NUMBERS':
|
||||
'UPDATE numberplates set anal_complete=?, numberplates=? \
|
||||
WHERE model=? AND filename=? AND ts=?',
|
||||
'''UPDATE numberplates set anal_complete=?, numberplates=?, np_extract_status ="success"
|
||||
WHERE model=? AND filename=? AND ts=?''',
|
||||
'SELECT_UNPROCESSED':
|
||||
'SELECT model, filename, ts FROM numberplates WHERE anal_complete=0;',
|
||||
'SELECT model, filename, ts FROM numberplates WHERE anal_complete=0 and np_extract_status="pending";',
|
||||
'UPDATE_FAILS':
|
||||
'UPDATE numberplates set np_extract_status = ? WHERE model=? AND filename=? AND ts=?'
|
||||
}
|
||||
|
||||
MODEL_NAME="YOLOv8"
|
||||
|
|
@ -234,17 +236,23 @@ async def capture_number_plate(db, signal_received):
|
|||
cursor = await db.execute(SQL["SELECT_UNPROCESSED"])
|
||||
res = await cursor.fetchall()
|
||||
logger.debug("found unprocessed records: %i ", len(res))
|
||||
curr_record = dict()
|
||||
for record in res:
|
||||
curr_record = record
|
||||
logger.debug("processing video file %s"%record['filename'])
|
||||
plates = anprm.infer(record['filename'])
|
||||
cursor = await db.execute(SQL["UPDATE_NUMBERS"],
|
||||
(True, json.dumps(plates), record['model'],
|
||||
record['filename'], record['ts']))
|
||||
record['filename'], record['ts'])
|
||||
)
|
||||
res = await cursor.fetchone()
|
||||
except asyncio.CancelledError:
|
||||
logger.debug("Closing loop capture_number_plate")
|
||||
#break
|
||||
except Exception as e:
|
||||
cursor = await db.execute(SQL["UPDATE_FAILS"], ('failed', curr_record['model'],
|
||||
curr_record['filename'],
|
||||
curr_record['ts']))
|
||||
logger.critical(f"traceback:{traceback.format_tb(e.__traceback__)} ")
|
||||
logger.critical(f"Error in capture_number_plate logic:")
|
||||
err_type = type(e).__name__
|
||||
|
|
|
|||
Binary file not shown.
35
lib/anpr.py
35
lib/anpr.py
|
|
@ -6,9 +6,20 @@ import torch
|
|||
import ultralytics
|
||||
from ultralytics import YOLO
|
||||
from PIL import Image
|
||||
import logging
|
||||
import time
|
||||
logger = logging.getLogger('lib')
|
||||
#ultralytics.checks()
|
||||
from xml.etree import ElementTree as ET
|
||||
from .consts import BASE_PATH
|
||||
from .consts import BASE_PATH, FRAME_RATE
|
||||
from pytesseract import TesseractError
|
||||
|
||||
daily_log_ts = time.strftime("%Y-%m-%d")
|
||||
#logging.basicConfig(
|
||||
# filename= f"{BASE_PATH}/logs/main-yolo-tesseract-{daily_log_ts}.log",
|
||||
# level=logging.DEBUG,
|
||||
# format='%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s'
|
||||
# )
|
||||
|
||||
if torch.cuda.is_available():
|
||||
device = torch.device('cuda')
|
||||
|
|
@ -104,18 +115,34 @@ def train_model():
|
|||
def infer(filename):
|
||||
model2 = YOLO(f"{BASE_PATH}/models/train25/best.pt")
|
||||
test_result = model2.predict(source=filename)
|
||||
logger.debug(len(test_result))
|
||||
#onnx_model = YOLO("../models/train25/best.onnx")
|
||||
#model_2 = YOLO('/kaggle/input/weights/best(2).pt')
|
||||
#testfiles = glob.glob('../data/TEST/*')
|
||||
#import pdb; pdb.set_trace()
|
||||
#test_result = model2.predict(source=testfiles[4])
|
||||
vidname = os.path.basename(filename).split('.')[0]
|
||||
if not os.path.exists(f"{BASE_PATH}/images/{vidname}"):
|
||||
os.mkdir(f"{BASE_PATH}/images/{vidname}")
|
||||
number_plates = dict()
|
||||
number_plates['frames_found'] = list()
|
||||
for i, res in enumerate(test_result):
|
||||
res_img = res.plot()
|
||||
plate_im = Image.fromarray(res_img)
|
||||
np_text = pytesseract.image_to_string(plate_im, lang='eng')
|
||||
plate = str("".join(re.split("[^a-zA-Z0-9]*", np_text)))
|
||||
number_plates[i] = plate.upper()
|
||||
logger.debug(f"Saving result number {i} for file {vidname}")
|
||||
if i % FRAME_RATE == 0:
|
||||
number_plates['frames_found'].append(i)
|
||||
plate_im.save(f"{BASE_PATH}/images/{vidname}/frame-{i}.jpg")
|
||||
#try:
|
||||
# np_text = pytesseract.image_to_string(plate_im, lang='eng')
|
||||
# plate = str("".join(re.split("[^a-zA-Z0-9]*", np_text)))
|
||||
# number_plates[i] = plate.upper()
|
||||
#except TesseractError as TE:
|
||||
# logger.error("Failed to extract numberplate from the detected image")
|
||||
# continue
|
||||
#except Exception as e:
|
||||
# logger.error("Failed to extract numberplate from the detected image")
|
||||
# continue
|
||||
return number_plates
|
||||
|
||||
#download_kaggle_data()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ MODEL_NAME = "yolo_v8_custom"
|
|||
RTSP_URL = "rtsp://admin:C4sinfra12@192.168.1.10:554/rtsp"
|
||||
SCREEN_RESOLUTION = (1280, 720) # Resolution of the RTSP stream
|
||||
BITRATE = 1000000 # Bitrate for video recording
|
||||
FRAME_RATE = 25 # Video frame rate
|
||||
CONTOUR_MOTION_THRESHOLD = 800 # Sensitivity for motion detection
|
||||
MAX_CLIP_TIME = 20 # Maximum recording time in seconds
|
||||
MIN_TIME = 10 # Minimum recording time in seconds
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ CREATE TABLE numberplates(
|
|||
filename TEXT,
|
||||
ts DATETIME DEFAULT (datetime('now', 'localtime')),
|
||||
anal_complete BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
numberplates TEXT,
|
||||
np_extract_status TEXT DEFAULT 'pending',
|
||||
numberplates TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX filename_idx ON numberplates (filename);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue