python实现深度学习+传统方法的车牌识别
系统流程图:
其中,进行灰度转化,高斯滤波,形态学操作等方式,对输入图像进行预处理,处理过程图如下图所示:
处理代码为:
def pre_process(orig_img):
gray_img = cv2.cvtColor(orig_img, cv2.COLOR_BGR2GRAY)
# cv2.imshow('gray_img', gray_img)
# 均值滤波
blur_img = cv2.blur(gray_img, (3, 3))
# cv2.imshow('blur', blur_img)
# 边缘检测
sobel_img = cv2.Sobel(blur_img, cv2.CV_16S, 1, 0, ksize=3)
# 用convertScaleAbs()函数将其转回原来的uint8形式
sobel_img = cv2.convertScaleAbs(sobel_img)
# cv2.imshow('sobel', sobel_img)
hsv_img = cv2.cvtColor(orig_img, cv2.COLOR_BGR2HSV)
h, s, v = hsv_img[:, :, 0], hsv_img[:, :, 1], hsv_img[:, :, 2]
# 黄色色调区间[26,34],蓝色色调区间:[100,124],绿色色调区间:[35,77]
# | ((h > 35) & (h < 77))
choose_img = (((h > 26) & (h < 34)) | ((h > 100) & (h < 124))| ((h > 35) & (h < 77))) & (s > 70) & (v > 70)
choose_img = choose_img.astype('float32')
# 挑选出黄牌、蓝牌、绿牌的区域
mix_img = np.multiply(sobel_img, choose_img)
# cv2.imshow('mix', mix_img)
mix_img = mix_img.astype(np.uint8)
ret, binary_img = cv2.threshold(mix_img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
#cv2.imshow('binary',binary_img)
# 函数可用于构造一个特定大小和形状的结构元素,用于图像形态学处理。
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(21,5))
# 闭运算是对图像先膨胀再腐蚀,可以排除小型黑洞
close_img = cv2.morphologyEx(binary_img, cv2.MORPH_CLOSE, kernel)
# cv2.imshow('close', close_img)
return close_img
采用传统方法与深度学习方法结合的方式,定位车牌图像,定位结果图为:
识别采用改进的Lenet卷积神经网络进行字符识别训练:训练集截图如图
训练过程主要代码如下:
# conv1、pooling1
cw1 = tf.Variable(tf.random_normal(shape=[3, 3, 1, 32], stddev=0.01), dtype=tf.float32)
cb1 = tf.Variable(tf.random_normal(shape=[32]), dtype=tf.float32)
conv1 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(x_input,filter=cw1,strides=[1,1,1,1],padding='SAME'),cb1))
conv1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
conv1 = tf.nn.dropout(conv1, self.keep_place)
# conv2、pooling2
cw2 = tf.Variable(tf.random_normal(shape=[3, 3, 32, 64], stddev=0.01), dtype=tf.float32)
cb2 = tf.Variable(tf.random_normal(shape=[64]), dtype=tf.float32)
conv2 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv1,filter=cw2,strides=[1,1,1,1],padding='SAME'),cb2))
conv2 = tf.nn.max_pool(conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
conv2 = tf.nn.dropout(conv2, self.keep_place)
# conv3、pooling3
cw3 = tf.Variable(tf.random_normal(shape=[3, 3, 64, 128], stddev=0.01), dtype=tf.float32)
cb3 = tf.Variable(tf.random_normal(shape=[128]), dtype=tf.float32)
conv3 = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(conv2,filter=cw3,strides=[1,1,1,1],padding='SAME'),cb3))
conv5 = tf.nn.max_pool(conv3, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
conv5 = tf.nn.dropout(conv5, self.keep_place)
conv_out = tf.reshape(conv5, shape=[-1, 3 * 3 * 128])
fw1 = tf.Variable(tf.random_normal(shape=[3 * 3 * 128, 1024], stddev=0.01), dtype=tf.float32)
fb1 = tf.Variable(tf.random_normal(shape=[1024]), dtype=tf.float32)
fully1 = tf.nn.relu(tf.add(tf.matmul(conv_out, fw1), fb1))
fully1 = tf.nn.dropout(fully1, self.keep_place)
fw2 = tf.Variable(tf.random_normal(shape=[1024, 1024], stddev=0.01), dtype=tf.float32)
fb2 = tf.Variable(tf.random_normal(shape=[1024]), dtype=tf.float32)
fully2 = tf.nn.relu(tf.add(tf.matmul(fully1, fw2), fb2))
fully2 = tf.nn.dropout(fully2, self.keep_place)
fw4 = tf.Variable(tf.random_normal(shape=[1024, self.dataset_len], stddev=0.01), dtype=tf.float32)
fb4 = tf.Variable(tf.random_normal(shape=[self.dataset_len]), dtype=tf.float32)
fully4 = tf.add(tf.matmul(fully2, fw4), fb4, name='out_put')
识别结果图如图所示:
GUI界面代码如下:
import tkinter as tk
from tkinter.filedialog import *
from tkinter import ttk
import cv2
from PIL import Image, ImageTk
import time
import Apply
import numpy as np
import threading
import tkinter.messagebox as mBox
import App_LPR as al
class Surface(ttk.Frame):
pic_path = ""
viewhigh = 300
viewwide = 300
update_time = 0
thread = None
thread_run = False
camera = None
def __init__(self, win):
ttk.Frame.__init__(self, win)
frame_left = ttk.Frame(self)
frame_right1 = ttk.Frame(self)
frame_right2 = ttk.Frame(self)
win.title("车牌识别")
win.state("zoomed")
self.pack(fill=tk.BOTH, expand=tk.YES, padx="5", pady="5")
frame_left.pack(side=LEFT,expand=1,fill=BOTH)
frame_right1.pack(side=TOP,expand=1,fill=tk.Y)
frame_right2.pack(side=RIGHT,expand=0)
ttk.Label(frame_left, text='原图:').pack(anchor="nw")
ttk.Label(frame_right1, text='车牌位置:').grid(column=0, row=0, sticky=tk.W)
from_pic_ctl = ttk.Button(frame_right2, text="打开车牌图片", width=20, command=self.from_pic)
self.image_ctl = ttk.Label(frame_left)
self.image_ctl.pack(anchor="nw")
self.roi_ctl = ttk.Label(frame_right1)
self.roi_ctl.grid(column=0, row=1, sticky=tk.W)
ttk.Label(frame_right1, text='识别结果:').grid(column=0, row=2, sticky=tk.W)
self.r_ctl = ttk.Label(frame_right1, text="")
self.r_ctl.grid(column=0, row=3, sticky=tk.W)
from_pic_ctl.pack(anchor="se", pady="5")
def get_imgtk(self, img_bgr):
img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
im = Image.fromarray(img)
imgtk = ImageTk.PhotoImage(image=im) # 文本框里插入图片
wide = imgtk.width()
high = imgtk.height()
if wide > self.viewwide or high > self.viewhigh:
wide_factor = self.viewwide / wide
high_factor = self.viewhigh / high
factor = min(wide_factor, high_factor)
wide = int(wide * factor)
if wide <= 0:
wide = 1
high = int(high * factor)
if high <= 0:
high = 1
imgtk = ImageTk.PhotoImage(image=im)
return imgtk
def show_roi(self, text, roi):
if text :
roi = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB)
roi = Image.fromarray(roi)
self.imgtk_roi = ImageTk.PhotoImage(image=roi)
self.roi_ctl.configure(image=self.imgtk_roi, state='enable')
self.r_ctl.configure(text=str(text))
self.update_time = time.time()
elif self.update_time + 8 < time.time():
self.roi_ctl.configure(state='disabled')
self.r_ctl.configure(text="")
def from_pic(self):
self.thread_run = False
self.pic_path = askopenfilename(title="选择识别图片", filetypes=[("jpg图片", "*.jpg")])
img = cv2.imread(self.pic_path )
img_1 = cv2.imdecode(np.fromfile(self.pic_path, dtype=np.uint8), cv2.IMREAD_COLOR)
print(self.pic_path)
if self.pic_path:
img_bgr = Apply.pre_process(img)
self.imgtk = self.get_imgtk(img_1) # 将读取的图片插入调整大小并显示
self.image_ctl.configure(image=self.imgtk)
# 车牌定位
car_plate_list = Apply.locate_carPlate(img, img_bgr)
# 字符提取
char_img_list = Apply.extract_char(car_plate_list)
if len(char_img_list) != 7:
print('传统方法检测失误!!!')
res_set, image_rgb = al.SimpleRecognizePlateByE2E(img)
for pstr, confidence, rect in res_set:
self.show_roi(pstr, image_rgb)
else:
# CNN字符识别
char_model_path = os.path.join( './model/model.ckpt-1000.meta')
text = Apply.cnn_recongnize_char(char_img_list, char_model_path)
self.show_roi(text, car_plate_list)
def close_window():
print("destroy")
if surface.thread_run :
surface.thread_run = False
surface.thread.join(2.0)
win.destroy()
if __name__ == '__main__':
win=tk.Tk()
surface = Surface(win)
win.protocol('WM_DELETE_WINDOW', close_window)
win.mainloop()
整个系统实现了从图像采集,到训练,再到识别的整体流程,想要数据集和代码,v:mql13148