First commit
This commit is contained in:
parent
8dc8759b81
commit
314761bf9e
15 changed files with 1686 additions and 0 deletions
334
det3.py
Normal file
334
det3.py
Normal file
|
|
@ -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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue