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