Compare commits

..

No commits in common. "d5437130828136ee38984fdd78489968ff145989" and "fe515d61ba4428c81cc33a981c56f9a6abc3824f" have entirely different histories.

7 changed files with 23 additions and 53 deletions

1
.gitignore vendored
View file

@ -1,3 +1,2 @@
videos/*
data/*
logs/*

View file

@ -4,3 +4,10 @@
* -- `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.
![ANPR](ANPR.jpg)
## 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.

View file

@ -3,7 +3,7 @@
#* File Name : anpr_yolo_v8.py
#* Purpose :
#* Creation Date : 21-04-2025
#* Last Modified : Thu 01 May 2025 11:45:10 PM CEST
#* Last Modified : Thu 01 May 2025 05:48:26 PM UTC
#* Created By : Yaay Nands
#_._._._._._._._._._._._._._._._._._._._._.#
import glob
@ -43,12 +43,10 @@ SQL = {
'INSERT_NUMBERS':
'INSERT INTO numberplates (model, filename, ts, ) VALUES (? , ?, ?)',
'UPDATE_NUMBERS':
'''UPDATE numberplates set anal_complete=?, numberplates=?, np_extract_status ="success"
WHERE model=? AND filename=? AND ts=?''',
'UPDATE numberplates set anal_complete=?, numberplates=? \
WHERE model=? AND filename=? AND ts=?',
'SELECT_UNPROCESSED':
'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=?'
'SELECT model, filename, ts FROM numberplates WHERE anal_complete=0;',
}
MODEL_NAME="YOLOv8"
@ -236,23 +234,18 @@ 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'])
#logger.debug("processing record: %s"%json.dumps(record))
plates = anprm.infer(filename)
cursor = await db.execute(SQL["UPDATE_NUMBERS"],
(True, json.dumps(plates), record['model'],
record['filename'], record['ts'])
)
(True, 'NOMARS', record['model'],
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.

View file

@ -6,26 +6,16 @@ import torch
import ultralytics
from ultralytics import YOLO
from PIL import Image
import logging
import time
logger = logging.getLogger('lib')
#ultralytics.checks()
ultralytics.checks()
from xml.etree import ElementTree as ET
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')
else:
device = torch.device('cpu')
BASE_PATH = '..'
def convert_bbox_to_yolo(
size: tuple[float, float], box: tuple[float, float, float, float]
) -> tuple[float, float, float, float]:
@ -115,34 +105,18 @@ 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)
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
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()
return number_plates
#download_kaggle_data()

View file

@ -2,12 +2,10 @@ DB_RECORDINGS = "db/numberplates.sqlite3"
VIDEO_OUT_FULL = "videos/full/"
VIDEO_OUT_ANAL = "videos/analysis"
BASE_PATH = '/home/nands/workspace/c4s/anpr'
MODEL_NAME = "yolo_v8_custom"
MODEL_NAME = "models/train25/best.pt"
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

View file

@ -4,8 +4,7 @@ CREATE TABLE numberplates(
filename TEXT,
ts DATETIME DEFAULT (datetime('now', 'localtime')),
anal_complete BOOLEAN NOT NULL DEFAULT FALSE,
np_extract_status TEXT DEFAULT 'pending',
numberplates TEXT
numberplates TEXT,
);
CREATE INDEX filename_idx ON numberplates (filename);