Bootstrap

Tensorflow车牌识别完整项目(含完整源代码及训练集)

二、车牌获取

车牌图像获取是进行车牌识别的首要环节,车牌图像可以从摄像机拍摄的车辆图像或者视频图像中进行抽取,车牌图像的获取也可由用户手机拍摄后传入车牌识别系统。

三、灰度图像生成

摄像机拍摄的含有车牌信息的车辆图像是彩色的,为了提高车牌识别的抗外界干扰的能力,先将彩色车辆图像生成二值的灰度图像,实现基于色调的车牌区域定位。由于国内的车牌往往是蓝底白字,因此,可以利用图像的色调或者色彩饱和度特征,生成二值灰度图像,从而实现更加准确地定位车牌位置。

四、车牌区域定位

车牌区域的定位采用基于形状的方法。由于车辆图像背景比较复杂,所以应该根据车牌的特征进行初次筛选。车牌的特征可以选择中国车牌的大小、比例特征,因为车牌都是固定的矩形形状,通过首先寻找图像上拥有矩形特征的区域,然后再抽取这些区域,再结合车牌的长宽的比例特征可以筛选出相应的矩形区域,从而实现对车牌的准确定位。

五、特征轮廓提取

OpenCV 与 Python 的接口中使用 cv2.fifindContours() 函数来查找检测物体的轮廓。

图3 和 图4 为特征轮廓提取前后的效果对比图 :

六、车牌内容识别

车牌内容识别时,通过计算候选车牌区域蓝色数值(均值)的最大值,确定最终的车牌区域。对于选定的车牌轮廓,首先进行粗定位,即对车牌进行左右边界回归处理,去除车牌两边多余的部分,然后进行精定位,即将车牌送入 CRNN 网络进行字符识别,利用左右边界回归模型,预测出车牌的左右边框,进一步裁剪,进行精定位。基于文字特征的方法是根据文字轮廓特征进行识别,经过相应的算法解析,得到结果。

项目实现 核心代码展现

一、检测车牌

def find_car_num_brod(): watch_cascade = cv2.CascadeClassifier(‘D:\pycharm\pycharm_work\chepai\cascade.xml’) # 先读取图片 image = cv2.imread(“D:\pycharm\pycharm_work\chepai\capture_img\car1.jpg”) resize_h = 1000 height = image.shape[0] scale = image.shape[1] / float(image.shape[0]) image = cv2.resize(image, (int(scale * resize_h), resize_h)) image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) watches = watch_cascade.detectMultiScale(image_gray, 1.2, 2, minSize=(36, 9), maxSize=(36 * 40, 9 * 40))

print(“检测到车牌数”, len(watches))

for (x, y, w, h) in watches:

cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 1)

cut_img = image[y + 5:y - 5 + h, x + 8:x + w] # 裁剪坐标为[y0:y1, x0:x1]

cut_gray = cv2.cvtColor(cut_img, cv2.COLOR_RGB2GRAY)

cv2.imwrite(“D:\pycharm\pycharm_work\chepai\num_for_car.jpg”, cut_gray)

im = Image.open(“D:\pycharm\pycharm_work\chepai\num_for_car.jpg”)

size = 720, 180

mmm = im.resize(size, Image.ANTIALIAS)

mmm.save(“D:\pycharm\pycharm_work\chepai\num_for_car.jpg”, “JPEG”, quality=90)

break

二、二值化图像

def cut_car_num_for_chart(): # 1、读取图像,并把图像转换为灰度图像并显示 img = cv2.imread(“D:\pycharm\pycharm_work\chepai\num_for_car.jpg”) # 读取图片 img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换了灰度化 cv2.imshow(‘gray’, img_gray) # 显示图片 cv2.waitKey(0) # 2、将灰度图像二值化,设定阈值是100 转换后 白底黑字 —》 目标黑底白字 img_thre = img_gray # 灰点 白点 加错 # cv2.threshold(img_gray, 130, 255, cv2.THRESH_BINARY_INV, img_thre)

二值化处理 自适应阈值 效果不理想

th3 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)

高斯除噪 二值化处理

blur = cv2.GaussianBlur(img_gray, (5, 5), 0)

ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

cv2.imshow(‘threshold’, th3)

cv2.imwrite(‘D:\pycharm\pycharm_work\chepai\wb_img.jpg’, th3)

cv2.waitKey(0)

第一行imread(),由于flag设为1所以读的是彩图,采用cvtColor函数转化为灰度图。如果你读入就是灰度图可以省略第二行代码,然后转化为二值化函数,阈值180可以修改,后经过增强处理,效果如图所示:

三、单字符切割

单字符分割主要策略就是检测列像素的总和变化,因为没有字符的区域基本是黑色,像素值低;有字符的区域白色较多,列像素和就变大了!

列像素变化的阈值是个问题,看到很多博客是固定的阈值进行检测,除非你处理后的二值化图像非常完美,不然有的图片混入了白色区域就会分割错误!

考虑到车牌中只有7个字符,所以先判断得到宽度大小,如果小于总宽的七分之一视为干扰放弃;其实也可以加大到总宽的8分之一(因为车牌中间可能有连接符)。

n = 1

start = 1

end = 2

temp = 1

while n < width - 2:

n += 1

if (white[n] if arg else black[n]) > (0.05 * white_max if arg else 0.05 * black_max):

上面这些判断用来辨别是白底黑字还是黑底白字

0.05这个参数请多调整,对应上面的0.95

start = n

end = find_end(start, white, black, arg, white_max, black_max, width)

n = end

车牌框检测分割 二值化处理后 可以看到明显的左右边框 毕竟用的是网络开放资源 所以车牌框定位角度真的不准,

所以我在这里截取单个字符时做处理,就当亡羊补牢吧

思路就是从左开始检测匹配字符,若宽度(end - start)小与20则认为是左侧白条 pass掉 继续向右识别,否则说明是

省份简称,剪切,压缩 保存,还有一个当后五位有数字 1 时,他的宽度也是很窄的,所以就直接认为是数字 1 不需要再

做预测了(不然很窄的 1 截切 压缩后宽度是被拉伸的),

shutil.copy()函数是当检测到这个所谓的 1 时,从样本库中拷贝一张 1 的图片给当前temp下标下的字符

if end - start > 5: # 车牌左边白条移除

print(" end - start" + str(end - start))

if temp == 1 and end - start < 20:

pass

elif temp > 3 and end - start < 20:

认为这个字符是数字1 copy 一个 32*40的 1 作为 temp.bmp

shutil.copy(

os.path.join(“D:\pycharm\pycharm_work\chepai\fuzhi”, “111.bmp”), # 111.bmp 是一张 1 的样本图片

os.path.join(“D:\pycharm\pycharm_work\chepai\img_cut\”, str(temp) + ‘.bmp’))

pass

else:

cj = th3[1:height, start:end]

cv2.imwrite(“D:\pycharm\pycharm_work\chepai\img_cut_not_3240\” + str(temp) + “.jpg”, cj)

im = Image.open(“D:\pycharm\pycharm_work\chepai\img_cut_not_3240\” + str(temp) + “.jpg”)

size = 32, 40

mmm = im.resize(size, Image.ANTIALIAS)

mmm.save(“D:\pycharm\pycharm_work\chepai\img_cut\” + str(temp) + “.bmp”, quality=95)

temp = temp + 1

车牌的切割效果如图所示:

四、单字符识别

max1 = 0

max2 = 0

max3 = 0

max1_index = 0

max2_index = 0

max3_index = 0

for j in range(NUM_CLASSES):

if result[0][j] > max1:

max1 = result[0][j]

max1_index = j

continue

在这里插入图片描述

感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的:

① 2000多本Python电子书(主流和经典的书籍应该都有了)

② Python标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

⑤ Python学习路线图(告别不入流的学习)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

;