From 314761bf9ea4fec7f4e1c45bd0937eb62cc90724 Mon Sep 17 00:00:00 2001 From: MaddoScientisto Date: Sun, 15 Feb 2026 14:04:11 +0100 Subject: [PATCH] First commit --- AiGareFrontend.exe | 3 + AiSettingsNew.json | 1 + Intelligenza artificiale foto.zip | 3 + det.py | 315 ++++++++++++++++++++++++++++ det2.py | 319 ++++++++++++++++++++++++++++ det3.py | 334 ++++++++++++++++++++++++++++++ det4.py | 327 +++++++++++++++++++++++++++++ guida.txt | 23 ++ models/detection.cfg | 180 ++++++++++++++++ models/detection.weights | 3 + models/recognition.cfg | 150 ++++++++++++++ models/recognition.weights | 3 + script.bat | 21 ++ settings.json | 1 + sni.dll | 3 + 15 files changed, 1686 insertions(+) create mode 100644 AiGareFrontend.exe create mode 100644 AiSettingsNew.json create mode 100644 Intelligenza artificiale foto.zip create mode 100644 det.py create mode 100644 det2.py create mode 100644 det3.py create mode 100644 det4.py create mode 100644 guida.txt create mode 100644 models/detection.cfg create mode 100644 models/detection.weights create mode 100644 models/recognition.cfg create mode 100644 models/recognition.weights create mode 100644 script.bat create mode 100644 settings.json create mode 100644 sni.dll diff --git a/AiGareFrontend.exe b/AiGareFrontend.exe new file mode 100644 index 0000000..2f5d159 --- /dev/null +++ b/AiGareFrontend.exe @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:38f750d47f2792e8ae574bc487f2cbf3f41e381f87826acc44b3300e142905a2 +size 16828286 diff --git a/AiSettingsNew.json b/AiSettingsNew.json new file mode 100644 index 0000000..85d7172 --- /dev/null +++ b/AiSettingsNew.json @@ -0,0 +1 @@ +{"SourcePath":"E:\\ORIGINAL\\SANLORENZO","DestinationPath":"E:\\RISULTATI_AI\\SANGIOVANNI.csv","CommandPath":"cmd","ExecuteFrom":"\"C:\\Users\\Utente\\Desktop\\AI Foto ONLUS\"","UseShellExecute":true,"Arguments":"/k python \"C:\\Users\\Utente\\Desktop\\AI Foto ONLUS\\det.py\" -d $source -c $dest","Recursive":true} \ No newline at end of file diff --git a/Intelligenza artificiale foto.zip b/Intelligenza artificiale foto.zip new file mode 100644 index 0000000..c2e161f --- /dev/null +++ b/Intelligenza artificiale foto.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d91e6f86ed65df84007e9a861c49cc4896c7bfdab3eca2bb69b62a0d813d784 +size 44626835 diff --git a/det.py b/det.py new file mode 100644 index 0000000..c0ff2da --- /dev/null +++ b/det.py @@ -0,0 +1,315 @@ +### +# Run as following: +# `python3 det.py -d ./images/prova -c newResult.csv` +# __ -d : the directory where you wanna to scan files +# __ -c : the output file name which you are going to make that contain the result of scanning +### + + +import os +import tempfile +import subprocess +import csv +from imutils.object_detection import non_max_suppression +import numpy as np +import argparse +import time +import cv2 +from PIL import Image +import shutil +import pytesseract + +ap = argparse.ArgumentParser() +ap.add_argument('-d', '--directory', type=str, + help="the name of the directory to scan") +ap.add_argument('-c', '--csv', type=str, + help="the name of the output file which have the result of scanning") +args = vars(ap.parse_args()) + +directory = args['directory'] +outputFile = args['csv'] + + +detecion_net = cv2.dnn.readNet('models/detection.weights', 'models/detection.cfg') +recognition_net = cv2.dnn.readNet('models/recognition.weights', 'models/recognition.cfg') + + +image_width = 0 +image_height = 0 +number_classes = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] + + +def get_output_layers(net): + layer_names = net.getLayerNames() + + output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()] + + return output_layers + + +def check_min_value(a): + if a < 0: + return 0 + else: + return a + + +def check_X_max_value(x): + if x > image_width: + return image_width + else: + return x + + +def check_Y_max_value(y): + if y > image_height: + return image_height + else: + return y + + +def crop_image(img, x, y, w, h): + global crop_img_counter + + x1 = check_min_value(x - int(w * 0.1)) + x2 = check_X_max_value(x + w + int(w * 0.1)) + y1 = check_min_value(y - int(h * 0.1)) + y2 = check_Y_max_value(y + h + int(h * 0.1)) + crop_img = img[y1:y2, x1:x2] + + return crop_img + + +def draw_bounding_box(img, class_id, label, x, y, x_plus_w, y_plus_h): + # label = str(plate_classes[class_id]) + + color = (0, 255, 0) + + cv2.rectangle(img, (x, y), (x_plus_w, y_plus_h), color, 2) + + cv2.putText(img, label, (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.5, color, 3) + + +def recog_number(image): + scale = 0.00392 + + # read pre-trained model and config file + + # create input blob + blob = cv2.dnn.blobFromImage(image, scale, (140, 120), (0, 0, 0), True, crop=False) + + # set input blob for the network + recognition_net.setInput(blob) + + # run inference through the network + # and gather predictions from output layers + outs = recognition_net.forward(get_output_layers(recognition_net)) + + # initialization + class_ids = [] + confidences = [] + boxes = [] + center_X = [] + conf_threshold = 0.5 + nms_threshold = 0.4 + + # for each detetion from each output layer + # get the confidence, class id, bounding box params + # and ignore weak detections (confidence < 0.5) + for out in outs: + for detection in out: + scores = detection[5:] + class_id = np.argmax(scores) + confidence = scores[class_id] + if confidence > 0.5: + center_x = int(detection[0] * image.shape[1]) + center_y = int(detection[1] * image.shape[0]) + w = int(detection[2] * image.shape[1]) + h = int(detection[3] * image.shape[0]) + x = center_x - w / 2 + y = center_y - h / 2 + class_ids.append(class_id) + confidences.append(float(confidence)) + boxes.append([x, y, w, h]) + center_X.append(center_x) + + # apply non-max suppression + indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold) + + # go through the detections remaining + # after nms and draw bounding box + + result = '' + + valid_boxes = [] + valid_classids = [] + valid_centerX = [] + + + for i in indices: + i = i[0] + box = boxes[i] + x = box[0] + valid_boxes.append(box) + valid_classids.append(class_ids[i]) + valid_centerX.append(x) + + for i in range(0, len(valid_centerX)): + for j in range(i + 1, len(valid_centerX)): + if valid_centerX[i] > valid_centerX[j]: + temp = valid_centerX[i] + valid_centerX[i] = valid_centerX[j] + valid_centerX[j] = temp + + tem = valid_classids[i] + valid_classids[i] = valid_classids[j] + valid_classids[j] = tem + + for i in range(0, len(valid_classids)): + + result += number_classes[valid_classids[i]] + + + return result + + +def recog_text(image): + scale = 0.00392 + + # read pre-trained model and config file + + # create input blob + blob = cv2.dnn.blobFromImage(image, scale, (416, 416), (0, 0, 0), True, crop=False) + + # set input blob for the network + detecion_net.setInput(blob) + + # run inference through the network + # and gather predictions from output layers + outs = detecion_net.forward(get_output_layers(detecion_net)) + + # initialization + class_ids = [] + confidences = [] + boxes = [] + center_Y_list = [] + conf_threshold = 0.5 + nms_threshold = 0.4 + + # for each detetion from each output layer + # get the confidence, class id, bounding box params + # and ignore weak detections (confidence < 0.5) + for out in outs: + for detection in out: + scores = detection[5:] + class_id = np.argmax(scores) + confidence = scores[class_id] + if confidence > 0.5: + center_x = int(detection[0] * image.shape[1]) + center_y = int(detection[1] * image.shape[0]) + w = int(detection[2] * image.shape[1]) + h = int(detection[3] * image.shape[0]) + x = center_x - w / 2 + y = center_y - h / 2 + class_ids.append(class_id) + confidences.append(float(confidence)) + boxes.append([x, y, w, h]) + center_Y_list.append(center_y) + + # apply non-max suppression + indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold) + + # go through the detections remaining + # after nms and draw bounding box + + text = "" + + for i in indices: + i = i[0] + box = boxes[i] + x = box[0] + y = box[1] + w = box[2] + h = box[3] + + # if center_Y_list[i] in range(int(image.shape[0] * 0.2), int(image.shape[0] * 0.8)): + + plate_img = crop_image(image, round(x), round(y), round(w), round(h)) + + license_str = recog_number(plate_img) + + draw_bounding_box(image, class_ids[i], license_str, round(x), round(y), round(x + w), round(y + h)) + + print(license_str) + + text += license_str + "," + + return text[:-1] + + +class detector: + def __init__(self): + super().__init__() + self.superdir = "" + self.subdir = directory + self.outputName = outputFile + + # self.finddir() + self.ocr() + + def finddir(self): + currentPath = os.getcwd() + self.superdir = currentPath + "/images" + self.subdir = [self.superdir + "/" + + sd for sd in os.listdir(self.superdir) if not ("." in sd)] + + def ocr(self): + if os.path.isfile(self.outputName): + os.remove(self.outputName) + for fil in os.listdir(self.subdir): + if ".jpg" in fil or ".JPG" in fil: + filepath = self.subdir + "/" + fil + text = self.text_detect(filepath, fil) + # i = self.subdir.index(self.subdir) + # subfolders = [sf for sf in os.listdir(self.superdir) if not ("." in sf)] + csvPath = self.outputName + + file_exists = os.path.isfile(csvPath) + if text == "": + continue + with open(csvPath, mode='a') as csv_file: + fieldnames = ['filename', 'text'] + writer = csv.DictWriter(csv_file, fieldnames=fieldnames) + if not file_exists: + writer.writeheader() + writer.writerow({'filename': fil, 'text': text}) + + def text_detect(self, filepath, file): + global image_width, image_height + + image = cv2.imread(filepath) + + image_width = image.shape[1] + image_height = image.shape[0] + + text = recog_text(image) + print(text) + + #image = cv2.resize(image, (1000, 800)) + #cv2.imshow("Result", image) + #cv2.waitKey(0) + + return text + + +if __name__ == "__main__": + if directory == None or outputFile == None: + print('\tInvalid argument inputed. You should input correct arguments.\n\t--e.g.\t `python3 det.py -d ./images/prova -c prova.csv') + else: + if not os.path.isdir(directory) or not '.csv' in outputFile: + if not os.path.isdir(directory): + print('\tSuch directory doesn\'t exist.') + else: + print('\tInvalid argument inputed. You should input correct arguments.\n\t--e.g.\t `python3 det.py -d ./images/prova -c prova.csv') + else: + detector() diff --git a/det2.py b/det2.py new file mode 100644 index 0000000..a2cb327 --- /dev/null +++ b/det2.py @@ -0,0 +1,319 @@ +### +# Run as following: +# `python3 det.py -d ./images/prova -c newResult.csv` +# __ -d : the directory where you wanna to scan files +# __ -c : the output file name which you are going to make that contain the result of scanning +### + + +import os +import tempfile +import subprocess +import csv +from imutils.object_detection import non_max_suppression +import numpy as np +import argparse +import time +import cv2 +from PIL import Image +import shutil +import pytesseract + +ap = argparse.ArgumentParser() +ap.add_argument('-d', '--directory', type=str, + help="the name of the directory to scan") +ap.add_argument('-c', '--csv', type=str, + help="the name of the output file which have the result of scanning") +ap.add_argument('-tn', '--textnegative', action='store_true', + help="skip files that begin with 'tn_'") +args = vars(ap.parse_args()) + +directory = args['directory'] +outputFile = args['csv'] +textnegative = args['textnegative'] + +detecion_net = cv2.dnn.readNet('models/detection.weights', 'models/detection.cfg') +recognition_net = cv2.dnn.readNet('models/recognition.weights', 'models/recognition.cfg') + + +image_width = 0 +image_height = 0 +number_classes = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] + + +def get_output_layers(net): + layer_names = net.getLayerNames() + + output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()] + + return output_layers + + +def check_min_value(a): + if a < 0: + return 0 + else: + return a + + +def check_X_max_value(x): + if x > image_width: + return image_width + else: + return x + + +def check_Y_max_value(y): + if y > image_height: + return image_height + else: + return y + + +def crop_image(img, x, y, w, h): + global crop_img_counter + + x1 = check_min_value(x - int(w * 0.1)) + x2 = check_X_max_value(x + w + int(w * 0.1)) + y1 = check_min_value(y - int(h * 0.1)) + y2 = check_Y_max_value(y + h + int(h * 0.1)) + crop_img = img[y1:y2, x1:x2] + + return crop_img + + +def draw_bounding_box(img, class_id, label, x, y, x_plus_w, y_plus_h): + # label = str(plate_classes[class_id]) + + color = (0, 255, 0) + + cv2.rectangle(img, (x, y), (x_plus_w, y_plus_h), color, 2) + + cv2.putText(img, label, (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.5, color, 3) + + +def recog_number(image): + scale = 0.00392 + + # read pre-trained model and config file + + # create input blob + blob = cv2.dnn.blobFromImage(image, scale, (140, 120), (0, 0, 0), True, crop=False) + + # set input blob for the network + recognition_net.setInput(blob) + + # run inference through the network + # and gather predictions from output layers + outs = recognition_net.forward(get_output_layers(recognition_net)) + + # initialization + class_ids = [] + confidences = [] + boxes = [] + center_X = [] + conf_threshold = 0.5 + nms_threshold = 0.4 + + # for each detetion from each output layer + # get the confidence, class id, bounding box params + # and ignore weak detections (confidence < 0.5) + for out in outs: + for detection in out: + scores = detection[5:] + class_id = np.argmax(scores) + confidence = scores[class_id] + if confidence > 0.5: + center_x = int(detection[0] * image.shape[1]) + center_y = int(detection[1] * image.shape[0]) + w = int(detection[2] * image.shape[1]) + h = int(detection[3] * image.shape[0]) + x = center_x - w / 2 + y = center_y - h / 2 + class_ids.append(class_id) + confidences.append(float(confidence)) + boxes.append([x, y, w, h]) + center_X.append(center_x) + + # apply non-max suppression + indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold) + + # go through the detections remaining + # after nms and draw bounding box + + result = '' + + valid_boxes = [] + valid_classids = [] + valid_centerX = [] + + + for i in indices: + i = i[0] + box = boxes[i] + x = box[0] + valid_boxes.append(box) + valid_classids.append(class_ids[i]) + valid_centerX.append(x) + + for i in range(0, len(valid_centerX)): + for j in range(i + 1, len(valid_centerX)): + if valid_centerX[i] > valid_centerX[j]: + temp = valid_centerX[i] + valid_centerX[i] = valid_centerX[j] + valid_centerX[j] = temp + + tem = valid_classids[i] + valid_classids[i] = valid_classids[j] + valid_classids[j] = tem + + for i in range(0, len(valid_classids)): + + result += number_classes[valid_classids[i]] + + + return result + + +def recog_text(image): + scale = 0.00392 + + # read pre-trained model and config file + + # create input blob + blob = cv2.dnn.blobFromImage(image, scale, (416, 416), (0, 0, 0), True, crop=False) + + # set input blob for the network + detecion_net.setInput(blob) + + # run inference through the network + # and gather predictions from output layers + outs = detecion_net.forward(get_output_layers(detecion_net)) + + # initialization + class_ids = [] + confidences = [] + boxes = [] + center_Y_list = [] + conf_threshold = 0.5 + nms_threshold = 0.4 + + # for each detetion from each output layer + # get the confidence, class id, bounding box params + # and ignore weak detections (confidence < 0.5) + for out in outs: + for detection in out: + scores = detection[5:] + class_id = np.argmax(scores) + confidence = scores[class_id] + if confidence > 0.5: + center_x = int(detection[0] * image.shape[1]) + center_y = int(detection[1] * image.shape[0]) + w = int(detection[2] * image.shape[1]) + h = int(detection[3] * image.shape[0]) + x = center_x - w / 2 + y = center_y - h / 2 + class_ids.append(class_id) + confidences.append(float(confidence)) + boxes.append([x, y, w, h]) + center_Y_list.append(center_y) + + # apply non-max suppression + indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold) + + # go through the detections remaining + # after nms and draw bounding box + + text = "" + + for i in indices: + i = i[0] + box = boxes[i] + x = box[0] + y = box[1] + w = box[2] + h = box[3] + + # if center_Y_list[i] in range(int(image.shape[0] * 0.2), int(image.shape[0] * 0.8)): + + plate_img = crop_image(image, round(x), round(y), round(w), round(h)) + + license_str = recog_number(plate_img) + + draw_bounding_box(image, class_ids[i], license_str, round(x), round(y), round(x + w), round(y + h)) + + print(license_str) + + text += license_str + "," + + return text[:-1] + + +class detector: + def __init__(self): + super().__init__() + self.superdir = "" + self.subdir = directory + self.outputName = outputFile + + # self.finddir() + self.ocr() + + def finddir(self): + currentPath = os.getcwd() + self.superdir = currentPath + "/images" + self.subdir = [self.superdir + "/" + + sd for sd in os.listdir(self.superdir) if not ("." in sd)] + + def ocr(self): + if os.path.isfile(self.outputName): + os.remove(self.outputName) + for fil in os.listdir(self.subdir): + if textnegative and fil.startswith('tn_'): + continue + if ".jpg" in fil or ".JPG" in fil: + filepath = self.subdir + "/" + fil + text = self.text_detect(filepath, fil) + # i = self.subdir.index(self.subdir) + # subfolders = [sf for sf in os.listdir(self.superdir) if not ("." in sf)] + csvPath = self.outputName + + file_exists = os.path.isfile(csvPath) + if text == "": + continue + with open(csvPath, mode='a') as csv_file: + fieldnames = ['filename', 'text'] + writer = csv.DictWriter(csv_file, fieldnames=fieldnames) + if not file_exists: + writer.writeheader() + writer.writerow({'filename': fil, 'text': text}) + + def text_detect(self, filepath, file): + global image_width, image_height + + image = cv2.imread(filepath) + + image_width = image.shape[1] + image_height = image.shape[0] + + text = recog_text(image) + print(text) + + #image = cv2.resize(image, (1000, 800)) + #cv2.imshow("Result", image) + #cv2.waitKey(0) + + return text + + +if __name__ == "__main__": + if directory == None or outputFile == None: + print('\tInvalid argument inputed. You should input correct arguments.\n\t--e.g.\t `python3 det.py -d ./images/prova -c prova.csv') + else: + if not os.path.isdir(directory) or not '.csv' in outputFile: + if not os.path.isdir(directory): + print('\tSuch directory doesn\'t exist.') + else: + print('\tInvalid argument inputed. You should input correct arguments.\n\t--e.g.\t `python3 det.py -d ./images/prova -c prova.csv') + else: + detector() diff --git a/det3.py b/det3.py new file mode 100644 index 0000000..6a99c89 --- /dev/null +++ b/det3.py @@ -0,0 +1,334 @@ +### +# Run as following: +# `python3 det.py -d ./images/prova -c newResult.csv` +# __ -d : the directory where you wanna to scan files +# __ -c : the output file name which you are going to make that contain the result of scanning +### + + +import os +import tempfile +import subprocess +import csv +from imutils.object_detection import non_max_suppression +import numpy as np +import argparse +import time +import cv2 +from PIL import Image +import shutil +import pytesseract +from multiprocessing import Pool + +ap = argparse.ArgumentParser() +ap.add_argument('-d', '--directory', type=str, + help="the name of the directory to scan") +ap.add_argument('-c', '--csv', type=str, + help="the name of the output file which have the result of scanning") +ap.add_argument('-tn', '--textnegative', action='store_true', + help="skip files that begin with 'tn_'") +ap.add_argument('-r', '--recursive', type=int, + help="recursively called with defined concurrent operations") +args = vars(ap.parse_args()) + +directory = args['directory'] +outputFile = args['csv'] +textnegative = args['textnegative'] +recursive = args['recursive'] + +detecion_net = cv2.dnn.readNet('models/detection.weights', 'models/detection.cfg') +recognition_net = cv2.dnn.readNet('models/recognition.weights', 'models/recognition.cfg') + + +image_width = 0 +image_height = 0 +number_classes = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] + + +def get_output_layers(net): + layer_names = net.getLayerNames() + + output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()] + + return output_layers + + +def check_min_value(a): + if a < 0: + return 0 + else: + return a + + +def check_X_max_value(x): + if x > image_width: + return image_width + else: + return x + + +def check_Y_max_value(y): + if y > image_height: + return image_height + else: + return y + + +def crop_image(img, x, y, w, h): + global crop_img_counter + + x1 = check_min_value(x - int(w * 0.1)) + x2 = check_X_max_value(x + w + int(w * 0.1)) + y1 = check_min_value(y - int(h * 0.1)) + y2 = check_Y_max_value(y + h + int(h * 0.1)) + crop_img = img[y1:y2, x1:x2] + + return crop_img + + +def draw_bounding_box(img, class_id, label, x, y, x_plus_w, y_plus_h): + # label = str(plate_classes[class_id]) + + color = (0, 255, 0) + + cv2.rectangle(img, (x, y), (x_plus_w, y_plus_h), color, 2) + + cv2.putText(img, label, (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.5, color, 3) + + +def recog_number(image): + scale = 0.00392 + + # read pre-trained model and config file + + # create input blob + blob = cv2.dnn.blobFromImage(image, scale, (140, 120), (0, 0, 0), True, crop=False) + + # set input blob for the network + recognition_net.setInput(blob) + + # run inference through the network + # and gather predictions from output layers + outs = recognition_net.forward(get_output_layers(recognition_net)) + + # initialization + class_ids = [] + confidences = [] + boxes = [] + center_X = [] + conf_threshold = 0.5 + nms_threshold = 0.4 + + # for each detetion from each output layer + # get the confidence, class id, bounding box params + # and ignore weak detections (confidence < 0.5) + for out in outs: + for detection in out: + scores = detection[5:] + class_id = np.argmax(scores) + confidence = scores[class_id] + if confidence > 0.5: + center_x = int(detection[0] * image.shape[1]) + center_y = int(detection[1] * image.shape[0]) + w = int(detection[2] * image.shape[1]) + h = int(detection[3] * image.shape[0]) + x = center_x - w / 2 + y = center_y - h / 2 + class_ids.append(class_id) + confidences.append(float(confidence)) + boxes.append([x, y, w, h]) + center_X.append(center_x) + + # apply non-max suppression + indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold) + + # go through the detections remaining + # after nms and draw bounding box + + result = '' + + valid_boxes = [] + valid_classids = [] + valid_centerX = [] + + + for i in indices: + i = i[0] + box = boxes[i] + x = box[0] + valid_boxes.append(box) + valid_classids.append(class_ids[i]) + valid_centerX.append(x) + + for i in range(0, len(valid_centerX)): + for j in range(i + 1, len(valid_centerX)): + if valid_centerX[i] > valid_centerX[j]: + temp = valid_centerX[i] + valid_centerX[i] = valid_centerX[j] + valid_centerX[j] = temp + + tem = valid_classids[i] + valid_classids[i] = valid_classids[j] + valid_classids[j] = tem + + for i in range(0, len(valid_classids)): + + result += number_classes[valid_classids[i]] + + + return result + + +def recog_text(image): + scale = 0.00392 + + # read pre-trained model and config file + + # create input blob + blob = cv2.dnn.blobFromImage(image, scale, (416, 416), (0, 0, 0), True, crop=False) + + # set input blob for the network + detecion_net.setInput(blob) + + # run inference through the network + # and gather predictions from output layers + outs = detecion_net.forward(get_output_layers(detecion_net)) + + # initialization + class_ids = [] + confidences = [] + boxes = [] + center_Y_list = [] + conf_threshold = 0.5 + nms_threshold = 0.4 + + # for each detetion from each output layer + # get the confidence, class id, bounding box params + # and ignore weak detections (confidence < 0.5) + for out in outs: + for detection in out: + scores = detection[5:] + class_id = np.argmax(scores) + confidence = scores[class_id] + if confidence > 0.5: + center_x = int(detection[0] * image.shape[1]) + center_y = int(detection[1] * image.shape[0]) + w = int(detection[2] * image.shape[1]) + h = int(detection[3] * image.shape[0]) + x = center_x - w / 2 + y = center_y - h / 2 + class_ids.append(class_id) + confidences.append(float(confidence)) + boxes.append([x, y, w, h]) + center_Y_list.append(center_y) + + # apply non-max suppression + indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold) + + # go through the detections remaining + # after nms and draw bounding box + + text = "" + + for i in indices: + i = i[0] + box = boxes[i] + x = box[0] + y = box[1] + w = box[2] + h = box[3] + + # if center_Y_list[i] in range(int(image.shape[0] * 0.2), int(image.shape[0] * 0.8)): + + plate_img = crop_image(image, round(x), round(y), round(w), round(h)) + + license_str = recog_number(plate_img) + + draw_bounding_box(image, class_ids[i], license_str, round(x), round(y), round(x + w), round(y + h)) + + print(license_str) + + text += license_str + "," + + return text[:-1] + + +class detector: + def __init__(self, subdir=None, outputName=None): + super().__init__() + self.superdir = "" + self.subdir = subdir if subdir else directory + self.outputName = outputName if outputName else outputFile + self.ocr() + + def finddir(self): + currentPath = os.getcwd() + self.superdir = currentPath + "/images" + self.subdir = [self.superdir + "/" + + sd for sd in os.listdir(self.superdir) if not ("." in sd)] + + def ocr(self): + if os.path.isfile(self.outputName): + os.remove(self.outputName) + content = os.listdir(self.subdir) + files = [fil for fil in content if (".jpg" in fil or ".JPG" in fil) and os.path.isfile(os.path.join(self.subdir,fil))] + if recursive: + with Pool(processes=recursive) as pool: + pool.map(self.process_file, files) + else: + for fil in files: + self.process_file(fil) + + # Check for the -r or --recursive argument + if recursive: + directories = [item for item in content if os.path.isdir(os.path.join(self.subdir, item))] + for directory in directories: + # Create a new instance of detector for each subdirectory + detector(subdir=os.path.join(self.subdir, directory), outputName=self.outputName) + + def process_file(self, fil): + if textnegative and fil.startswith('tn_'): + return + filepath = self.subdir + "/" + fil + text = self.text_detect(filepath, fil) + csvPath = self.outputName + + file_exists = os.path.isfile(csvPath) + if text == "": + return + with open(csvPath, mode='a') as csv_file: + fieldnames = ['filename', 'text'] + writer = csv.DictWriter(csv_file, fieldnames=fieldnames) + if not file_exists: + writer.writeheader() + writer.writerow({'filename': fil, 'text': text}) + + def text_detect(self, filepath, file): + global image_width, image_height + + image = cv2.imread(filepath) + + image_width = image.shape[1] + image_height = image.shape[0] + + text = recog_text(image) + print(text) + + #image = cv2.resize(image, (1000, 800)) + #cv2.imshow("Result", image) + #cv2.waitKey(0) + + return text + + +if __name__ == "__main__": + if directory == None or outputFile == None: + print('\tInvalid argument inputed. You should input correct arguments.\n\t--e.g.\t `python3 det.py -d ./images/prova -c prova.csv') + else: + if not os.path.isdir(directory) or not '.csv' in outputFile: + if not os.path.isdir(directory): + print('\tSuch directory doesn\'t exist.') + else: + print('\tInvalid argument inputed. You should input correct arguments.\n\t--e.g.\t `python3 det.py -d ./images/prova -c prova.csv') + else: + detector() diff --git a/det4.py b/det4.py new file mode 100644 index 0000000..5175c28 --- /dev/null +++ b/det4.py @@ -0,0 +1,327 @@ +### +# Run as following: +# `python3 det.py -d ./images/prova -c newResult.csv` +# __ -d : the directory where you wanna to scan files +# __ -c : the output file name which you are going to make that contain the result of scanning +# __ -tn : Skip files that begin with 'tn_' +### + + +import os +import tempfile +import subprocess +import csv +from imutils.object_detection import non_max_suppression +import numpy as np +import argparse +import time +import cv2 +from PIL import Image +import shutil +import pytesseract + +ap = argparse.ArgumentParser() +ap.add_argument('-d', '--directory', type=str, + help="the name of the directory to scan") +ap.add_argument('-c', '--csv', type=str, + help="the name of the output file which have the result of scanning") +ap.add_argument('-tn', '--textnegative', action='store_true', + help="skip files that begin with 'tn_'") +args = vars(ap.parse_args()) + +directory = args['directory'] +outputFile = args['csv'] +textnegative = args['textnegative'] + +detecion_net = cv2.dnn.readNet('models/detection.weights', 'models/detection.cfg') +recognition_net = cv2.dnn.readNet('models/recognition.weights', 'models/recognition.cfg') + + +image_width = 0 +image_height = 0 +number_classes = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] + + +def get_output_layers(net): + layer_names = net.getLayerNames() + + output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()] + + return output_layers + + +def check_min_value(a): + if a < 0: + return 0 + else: + return a + + +def check_X_max_value(x): + if x > image_width: + return image_width + else: + return x + + +def check_Y_max_value(y): + if y > image_height: + return image_height + else: + return y + + +def crop_image(img, x, y, w, h): + global crop_img_counter + + x1 = check_min_value(x - int(w * 0.1)) + x2 = check_X_max_value(x + w + int(w * 0.1)) + y1 = check_min_value(y - int(h * 0.1)) + y2 = check_Y_max_value(y + h + int(h * 0.1)) + crop_img = img[y1:y2, x1:x2] + + return crop_img + + +def draw_bounding_box(img, class_id, label, x, y, x_plus_w, y_plus_h): + # label = str(plate_classes[class_id]) + + color = (0, 255, 0) + + cv2.rectangle(img, (x, y), (x_plus_w, y_plus_h), color, 2) + + cv2.putText(img, label, (x - 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1.5, color, 3) + + +def recog_number(image): + scale = 0.00392 + + # read pre-trained model and config file + + # create input blob + blob = cv2.dnn.blobFromImage(image, scale, (140, 120), (0, 0, 0), True, crop=False) + + # set input blob for the network + recognition_net.setInput(blob) + + # run inference through the network + # and gather predictions from output layers + outs = recognition_net.forward(get_output_layers(recognition_net)) + + # initialization + class_ids = [] + confidences = [] + boxes = [] + center_X = [] + conf_threshold = 0.5 + nms_threshold = 0.4 + + # for each detetion from each output layer + # get the confidence, class id, bounding box params + # and ignore weak detections (confidence < 0.5) + for out in outs: + for detection in out: + scores = detection[5:] + class_id = np.argmax(scores) + confidence = scores[class_id] + if confidence > 0.5: + center_x = int(detection[0] * image.shape[1]) + center_y = int(detection[1] * image.shape[0]) + w = int(detection[2] * image.shape[1]) + h = int(detection[3] * image.shape[0]) + x = center_x - w / 2 + y = center_y - h / 2 + class_ids.append(class_id) + confidences.append(float(confidence)) + boxes.append([x, y, w, h]) + center_X.append(center_x) + + # apply non-max suppression + indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold) + + # go through the detections remaining + # after nms and draw bounding box + + result = '' + + valid_boxes = [] + valid_classids = [] + valid_centerX = [] + + + for i in indices: + i = i[0] + box = boxes[i] + x = box[0] + valid_boxes.append(box) + valid_classids.append(class_ids[i]) + valid_centerX.append(x) + + for i in range(0, len(valid_centerX)): + for j in range(i + 1, len(valid_centerX)): + if valid_centerX[i] > valid_centerX[j]: + temp = valid_centerX[i] + valid_centerX[i] = valid_centerX[j] + valid_centerX[j] = temp + + tem = valid_classids[i] + valid_classids[i] = valid_classids[j] + valid_classids[j] = tem + + for i in range(0, len(valid_classids)): + + result += number_classes[valid_classids[i]] + + + return result + + +def recog_text(image): + scale = 0.00392 + + # read pre-trained model and config file + + # create input blob + blob = cv2.dnn.blobFromImage(image, scale, (416, 416), (0, 0, 0), True, crop=False) + + # set input blob for the network + detecion_net.setInput(blob) + + # run inference through the network + # and gather predictions from output layers + outs = detecion_net.forward(get_output_layers(detecion_net)) + + # initialization + class_ids = [] + confidences = [] + boxes = [] + center_Y_list = [] + conf_threshold = 0.5 + nms_threshold = 0.4 + + # for each detetion from each output layer + # get the confidence, class id, bounding box params + # and ignore weak detections (confidence < 0.5) + for out in outs: + for detection in out: + scores = detection[5:] + class_id = np.argmax(scores) + confidence = scores[class_id] + if confidence > 0.5: + center_x = int(detection[0] * image.shape[1]) + center_y = int(detection[1] * image.shape[0]) + w = int(detection[2] * image.shape[1]) + h = int(detection[3] * image.shape[0]) + x = center_x - w / 2 + y = center_y - h / 2 + class_ids.append(class_id) + confidences.append(float(confidence)) + boxes.append([x, y, w, h]) + center_Y_list.append(center_y) + + # apply non-max suppression + indices = cv2.dnn.NMSBoxes(boxes, confidences, conf_threshold, nms_threshold) + + # go through the detections remaining + # after nms and draw bounding box + + text = "" + + for i in indices: + i = i[0] + box = boxes[i] + x = box[0] + y = box[1] + w = box[2] + h = box[3] + + # if center_Y_list[i] in range(int(image.shape[0] * 0.2), int(image.shape[0] * 0.8)): + + plate_img = crop_image(image, round(x), round(y), round(w), round(h)) + + license_str = recog_number(plate_img) + + draw_bounding_box(image, class_ids[i], license_str, round(x), round(y), round(x + w), round(y + h)) + + #print(license_str) + if license_str: # Only append if license_str is not empty + text += license_str + "," + + return text[:-1] if text else text + + +class detector: + def __init__(self): + super().__init__() + self.superdir = "" + self.subdir = directory + self.outputName = outputFile + + # self.finddir() + self.ocr() + + def finddir(self): + currentPath = os.getcwd() + self.superdir = currentPath + "/images" + self.subdir = [self.superdir + "/" + + sd for sd in os.listdir(self.superdir) if not ("." in sd)] + + def ocr(self): + if os.path.isfile(self.outputName): + os.remove(self.outputName) + for fil in os.listdir(self.subdir): + if textnegative and fil.startswith('tn_'): + continue + if ".jpg" in fil or ".JPG" in fil or ".jpeg" in fil: + #filepath = self.subdir + "/" + fil + filepath = os.path.join(self.subdir, fil) # Use os.path.join for cross-platform compatibility + try: + text = self.text_detect(filepath, fil) + except Exception as e: + print(f"\033[91mError processing {fil}: {e}\033[0m") # Print error in red + continue # Skip to the next image + # i = self.subdir.index(self.subdir) + # subfolders = [sf for sf in os.listdir(self.superdir) if not ("." in sf)] + csvPath = self.outputName + + file_exists = os.path.isfile(csvPath) + if text == "" or text == ",": + print(f"{fil}: N/A") + continue + print(f"{fil}: \033[92m{text}\033[0m") + with open(csvPath, mode='a') as csv_file: + fieldnames = ['filename', 'text'] + writer = csv.DictWriter(csv_file, fieldnames=fieldnames) + if not file_exists: + writer.writeheader() + writer.writerow({'filename': fil, 'text': text}) + + def text_detect(self, filepath, file): + global image_width, image_height + + image = cv2.imread(filepath) + + image_width = image.shape[1] + image_height = image.shape[0] + + text = recog_text(image) + #print(text) + + #image = cv2.resize(image, (1000, 800)) + #cv2.imshow("Result", image) + #cv2.waitKey(0) + + return text + + +if __name__ == "__main__": + if directory == None or outputFile == None: + print('\tInvalid argument inputed. You should input correct arguments.\n\t--e.g.\t `python3 det.py -d ./images/prova -c prova.csv') + else: + if not os.path.isdir(directory) or not '.csv' in outputFile: + if not os.path.isdir(directory): + print('\tSuch directory doesn\'t exist.') + else: + print('\tInvalid argument inputed. You should input correct arguments.\n\t--e.g.\t `python3 det.py -d ./images/prova -c prova.csv') + else: + detector() diff --git a/guida.txt b/guida.txt new file mode 100644 index 0000000..0fd2248 --- /dev/null +++ b/guida.txt @@ -0,0 +1,23 @@ + +You should install followings first for use this script. + +windows 10: +pip install imutils +pip install numpy +pip install opencv-python +pip install pillow +pip install pytesseract + + +altro: + pip install csv + pip install numpy + pip install python-opencv + pip install os + pip install argparse + + +Then run code as following: + + python det.py -d ./images/onlus -c onlus.csv + diff --git a/models/detection.cfg b/models/detection.cfg new file mode 100644 index 0000000..8f388d1 --- /dev/null +++ b/models/detection.cfg @@ -0,0 +1,180 @@ +[net] +# Testing +batch=1 +subdivisions=1 +# Training +# batch=16 +# subdivisions=8 +width=416 +height=416 +channels=3 +momentum=0.9 +decay=0.0005 +angle=0 +saturation = 1.5 +exposure = 1.5 +hue=0 + +learning_rate=0.001 +burn_in=1000 +max_batches = 100200 +policy=steps +steps=40000,45000 +scales=.1,.1 + +[convolutional] +batch_normalize=1 +filters=16 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=32 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=1 + +[convolutional] +batch_normalize=1 +filters=1024 +size=3 +stride=1 +pad=1 +activation=leaky + +########### + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=18 +activation=linear + +[yolo] +mask = 3,4,5 +anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 +classes=1 +num=6 +jitter=.3 +ignore_thresh = .5 +truth_thresh = 1 +random=1 + +[route] +layers = -4 + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[upsample] +stride=2 + +[route] +layers = -1, 8 + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=18 +activation=linear + +[yolo] +mask = 0,1,2 +anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319 +classes=1 +num=6 +jitter=.3 +ignore_thresh = .5 +truth_thresh = 1 +random=1 \ No newline at end of file diff --git a/models/detection.weights b/models/detection.weights new file mode 100644 index 0000000..b895756 --- /dev/null +++ b/models/detection.weights @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92e42295a8ee742fe0f12fed8d204988220bc19f6a957c6e48e645071bc7edf8 +size 34704996 diff --git a/models/recognition.cfg b/models/recognition.cfg new file mode 100644 index 0000000..8226313 --- /dev/null +++ b/models/recognition.cfg @@ -0,0 +1,150 @@ +[net] +# Testing +batch=1 +subdivisions=1 +# Training +# batch=16 +# subdivisions=8 +width=140 +height=120 +channels=3 +momentum=0.9 +decay=0.0005 +angle=0 +saturation = 1.5 +exposure = 1.5 +hue=.1 + +learning_rate=0.001 +burn_in=1000 +max_batches = 50000 +policy=steps +steps=10000,20000 +scales=.1,.1 + +[convolutional] +batch_normalize=1 +filters=32 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=64 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=64 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=3 +stride=1 +pad=1 +activation=leaky + +[maxpool] +size=2 +stride=2 + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=128 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=256 +size=1 +stride=1 +pad=1 +activation=leaky + +[convolutional] +batch_normalize=1 +filters=512 +size=3 +stride=1 +pad=1 +activation=leaky + +[convolutional] +size=1 +stride=1 +pad=1 +filters=75 +activation=linear + + +[region] +anchors = 1.08,1.19, 3.42,4.41, 6.63,11.38, 9.42,5.11, 16.62,10.52 +bias_match=1 +classes=10 +coords=4 +num=5 +softmax=1 +jitter=.2 +rescore=1 + +object_scale=5 +noobject_scale=1 +class_scale=1 +coord_scale=1 + +absolute=1 +thresh = .6 +random=0 diff --git a/models/recognition.weights b/models/recognition.weights new file mode 100644 index 0000000..3623a71 --- /dev/null +++ b/models/recognition.weights @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c40736e7e3e3bcb37e2aaa87b1b12a1e0bcde87e634aa835576b12625e39b6ae +size 13342912 diff --git a/script.bat b/script.bat new file mode 100644 index 0000000..1386fe4 --- /dev/null +++ b/script.bat @@ -0,0 +1,21 @@ +@echo off +SET "SCRIPT_PATH=%~1" +SET VENV_DIR="C:\Users\piero\Desktop\AIFotoONLUS\my_venv" +SET "PARAMS=%*" +SET "PARAMS=%PARAMS:*%SCRIPT_PATH%=%" + +IF NOT EXIST %VENV_DIR% ( + python -m venv %VENV_DIR% +) + +call %VENV_DIR%\Scripts\activate.bat + +pip install imutils==0.5.4 +pip install numpy==1.20.1 +pip install opencv-python==4.5.1.48 +pip install Pillow==8.1.0 +pip install pytesseract==0.3.7 + +python "%SCRIPT_PATH%" %PARAMS% + +call %VENV_DIR%\Scripts\deactivate.bat \ No newline at end of file diff --git a/settings.json b/settings.json new file mode 100644 index 0000000..85d7172 --- /dev/null +++ b/settings.json @@ -0,0 +1 @@ +{"SourcePath":"E:\\ORIGINAL\\SANLORENZO","DestinationPath":"E:\\RISULTATI_AI\\SANGIOVANNI.csv","CommandPath":"cmd","ExecuteFrom":"\"C:\\Users\\Utente\\Desktop\\AI Foto ONLUS\"","UseShellExecute":true,"Arguments":"/k python \"C:\\Users\\Utente\\Desktop\\AI Foto ONLUS\\det.py\" -d $source -c $dest","Recursive":true} \ No newline at end of file diff --git a/sni.dll b/sni.dll new file mode 100644 index 0000000..907ff9c --- /dev/null +++ b/sni.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1446d6b26da49a5a9f366972f89f4e236f916955f31ddc38ebb96217c1cace9c +size 136488