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

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

环境准备


   Anaconda 4.10.3

   Tensorflow 2.6.0

   python3.7.8

   coding: utf-8

   pycharm解释器:D:\Anaconda\envs\tensorflow\python.exe

   以及各种第三方库


思路流程


1、将图片通过opencv切割识别定位车牌,切割保存


2、识别省份简称、识别城市代号、识别车牌编号


功能描述


   car_num_main.py  :将图片转为灰度图像,灰度图像二极化,分割图像并分别保存为.jpg和.bmp文件

   train-license-province.py : 省份简称训练识别  

   train-license-letters.py :城市代号训练识别

   train-license-digits.py :车牌编号训练识别

细节阐述


   1、图片切割后分别保存在两个文件夹./img_cut   and    ./img_cut_not_3240

   2、识别车牌需进入终端,在命令行中进入脚本所在目录,

   输入执行如下命令:python train-license-province.py train 进行省份简称训练

   输入执行如下命令:python train-license-province.py predict 进行省份简称识别

   输入执行如下命令:python train-license-letters.py train 进行城市代号训练

   输入执行如下命令:python train-license-letters.py predict 进行城市代号识别

   输入执行如下命令:python train-license-digits.py train 进行车牌编号训练

   输入执行如下命令:python train-license-digits.py predict 进行车牌编号识别

   3、将要识别的图片调为.jpg格式,大小调为像素600*413最佳,可依据代码酌情调试

   4、具体可以准确识别的车牌号参见数据集中训练集


测试数据集


项目总体框架


687c5e584f2e4a9ab3aa34f7c7cae39a.png


capture_img :存放将要识别的车牌图片


img_cut:运行car_num_main.py后生成切割后的图片


img_cut_not_3240 :运行  car_num_main.py  后生成切割后的图片(对比度加强)


test_images:存放测试图片


train_images:  存放训练图片


train-saver: 训练模型

过程展示


03fe9c6aafd3432eb7dbbdaa894b0b03.png



PS D:\pycharm\pycharm_work> cd .\chepai\
PS D:\pycharm\pycharm_work\chepai> python train-license-province.py train

c07bd3d6606b4e10a4ecc1bd8a597f80.png


PS D:\pycharm\pycharm_work\chepai> python train-license-province.py predict

e8bceb6222e7435ca071aecc8bd8eb6f.png


PS D:\pycharm\pycharm_work\chepai> python train-license-digits.py predict


5167c7d43f234a2f9c57ac6612e7e578.png


技术简介


一、Tensorflow

       TensorFlow是一个开放源代码软件库,用于进行高性能数值计算。借助其灵活的架构,用户可以轻松地将计算工作部署到多种平台(CPU、GPU、TPU)和设备(桌面设备、服务器集群、移动设备、边缘设备等)。


       TensorFlow 是一个用于研究和生产的开放源代码机器学习库。TensorFlow 提供了各种 API,可供初学者和专家在桌面、移动、网络和云端环境下进行开发。


       TensorFlow是采用数据流图(data flow graphs)来计算,所以首先我们得创建一个数据流流图,然后再将我们的数据(数据以张量(tensor)的形式存在)放在数据流图中计算。节点(Nodes)在图中表示数学操作,图中的边(edges)则表示在节点间相互联系的多维数据数组, 即张量(tensor)。训练模型时tensor会不断的从数据流图中的一个节点flow到另一节点。


二、OpenCV

       OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。


       OpenCV提供的视觉处理算法非常丰富,并且它部分以C语言编写,加上其开源的特性,处理得当,不需要添加新的外部支持也可以完整的编译链接生成执行程序,所以很多人用它来做算法的移植,OpenCV的代码经过适当改写可以正常的运行在DSP系统和ARM嵌入式系统中。其应用领域诸如:人机互动,物体识别,图像分割,人脸识别,动作识别,运动跟踪,机器人,运动分析,机器视觉,结构分析,汽车安全驾驶等领域。


系统设计


       车牌自动识别是以计算机视觉处理、数字图像处理、模式识别等技术为基础,对摄像机所拍摄的车辆图像或者视频图像进行处理分析,得到每辆车的车牌号码,从而完成识别的过程。在此基础上,可实现停车场出入口收费管理、盗抢车辆管理、高速公路超速自动化管理、闯红灯电子警察、公路收费管理等各种交通监管功能。


一、系统处理流程


       车牌自动识别系统的设计包含车辆图像获取、车牌区域定位、车牌特征轮廓提取和车牌内容识别环节。


d0902faf1f334a9396157e8609a5a97a.png


二、车牌获取


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


三、灰度图像生成


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


四、车牌区域定位


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


五、特征轮廓提取


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


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


4348d66242bc4e438ba4d960669d787e.png


六、车牌内容识别


       车牌内容识别时,通过计算候选车牌区域蓝色数值(均值)的最大值,确定最终的车牌区域。对于选定的车牌轮廓,首先进行粗定位,即对车牌进行左右边界回归处理,去除车牌两边多余的部分,然后进行精定位,即将车牌送入 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可以修改,后经过增强处理,效果如图所示:


6563680e7c6049749fa22715d4d6e407.png


三、单字符切割


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


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


       考虑到车牌中只有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


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


ea6b8c38b8fd463c81104594a6343999.png


四、单字符识别


     

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
                if (result[0][j] > max2) and (result[0][j] <= max1):
                    max2 = result[0][j]
                    max2_index = j
                    continue
                if (result[0][j] > max3) and (result[0][j] <= max2):
                    max3 = result[0][j]
                    max3_index = j
                    continue
            license_num = license_num + LETTERS_DIGITS[max1_index]
            print("概率:  [%s %0.2f%%]    [%s %0.2f%%]    [%s %0.2f%%]" % (
            LETTERS_DIGITS[max1_index], max1 * 100, LETTERS_DIGITS[max2_index], max2 * 100, LETTERS_DIGITS[max3_index],
            max3 * 100))
        print("车牌编号是: 【%s】" % license_num)


最终效果如图所示:


1e33f1d831514bb292aa4a4532a991bd.png


        注:此图为以下三个程序的运行结果图,我将图片拼接到一块了。。


train-license-province.py : 省份简称训练识别  

train-license-letters.py :城市代号训练识别

train-license-digits.py :车牌编号训练识别


最后


       车牌识别做不到100%识别成功,但通过训练已经基本可以达到98%以上的识别度,可以将capture_img文件中的图片(注意图片格式与大小会间接影响识别度,车牌名改为 car1.jpg)替换为自己的车牌照通过训练进行识别车牌照。


相关文章
|
2月前
|
并行计算 Shell TensorFlow
Tensorflow-GPU训练MTCNN出现错误-Could not create cudnn handle: CUDNN_STATUS_NOT_INITIALIZED
在使用TensorFlow-GPU训练MTCNN时,如果遇到“Could not create cudnn handle: CUDNN_STATUS_NOT_INITIALIZED”错误,通常是由于TensorFlow、CUDA和cuDNN版本不兼容或显存分配问题导致的,可以通过安装匹配的版本或在代码中设置动态显存分配来解决。
55 1
Tensorflow-GPU训练MTCNN出现错误-Could not create cudnn handle: CUDNN_STATUS_NOT_INITIALIZED
|
2月前
|
数据采集 TensorFlow 算法框架/工具
【大作业-03】手把手教你用tensorflow2.3训练自己的分类数据集
本教程详细介绍了如何使用TensorFlow 2.3训练自定义图像分类数据集,涵盖数据集收集、整理、划分及模型训练与测试全过程。提供完整代码示例及图形界面应用开发指导,适合初学者快速上手。[教程链接](https://www.bilibili.com/video/BV1rX4y1A7N8/),配套视频更易理解。
54 0
【大作业-03】手把手教你用tensorflow2.3训练自己的分类数据集
|
3月前
|
机器学习/深度学习 算法 TensorFlow
动物识别系统Python+卷积神经网络算法+TensorFlow+人工智能+图像识别+计算机毕业设计项目
动物识别系统。本项目以Python作为主要编程语言,并基于TensorFlow搭建ResNet50卷积神经网络算法模型,通过收集4种常见的动物图像数据集(猫、狗、鸡、马)然后进行模型训练,得到一个识别精度较高的模型文件,然后保存为本地格式的H5格式文件。再基于Django开发Web网页端操作界面,实现用户上传一张动物图片,识别其名称。
111 1
动物识别系统Python+卷积神经网络算法+TensorFlow+人工智能+图像识别+计算机毕业设计项目
|
2月前
|
机器学习/深度学习 人工智能 算法
【玉米病害识别】Python+卷积神经网络算法+人工智能+深度学习+计算机课设项目+TensorFlow+模型训练
玉米病害识别系统,本系统使用Python作为主要开发语言,通过收集了8种常见的玉米叶部病害图片数据集('矮花叶病', '健康', '灰斑病一般', '灰斑病严重', '锈病一般', '锈病严重', '叶斑病一般', '叶斑病严重'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。再使用Django搭建Web网页操作平台,实现用户上传一张玉米病害图片识别其名称。
72 0
【玉米病害识别】Python+卷积神经网络算法+人工智能+深度学习+计算机课设项目+TensorFlow+模型训练
|
3月前
|
机器学习/深度学习 算法 TensorFlow
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
交通标志识别系统。本系统使用Python作为主要编程语言,在交通标志图像识别功能实现中,基于TensorFlow搭建卷积神经网络算法模型,通过对收集到的58种常见的交通标志图像作为数据集,进行迭代训练最后得到一个识别精度较高的模型文件,然后保存为本地的h5格式文件。再使用Django开发Web网页端操作界面,实现用户上传一张交通标志图片,识别其名称。
123 6
交通标志识别系统Python+卷积神经网络算法+深度学习人工智能+TensorFlow模型训练+计算机课设项目+Django网页界面
|
4月前
|
机器学习/深度学习 API 算法框架/工具
【Tensorflow+keras】Keras API两种训练GAN网络的方式
使用Keras API以两种不同方式训练条件生成对抗网络(CGAN)的示例代码:一种是使用train_on_batch方法,另一种是使用tf.GradientTape进行自定义训练循环。
49 5
|
4月前
|
UED 开发者
哇塞!Uno Platform 数据绑定超全技巧大揭秘!从基础绑定到高级转换,优化性能让你的开发如虎添翼
【8月更文挑战第31天】在开发过程中,数据绑定是连接数据模型与用户界面的关键环节,可实现数据自动更新。Uno Platform 提供了简洁高效的数据绑定方式,使属性变化时 UI 自动同步更新。通过示例展示了基本绑定方法及使用 `Converter` 转换数据的高级技巧,如将年龄转换为格式化字符串。此外,还可利用 `BindingMode.OneTime` 提升性能。掌握这些技巧能显著提高开发效率并优化用户体验。
68 0
|
4月前
|
UED 存储 数据管理
深度解析 Uno Platform 离线状态处理技巧:从网络检测到本地存储同步,全方位提升跨平台应用在无网环境下的用户体验与数据管理策略
【8月更文挑战第31天】处理离线状态下的用户体验是现代应用开发的关键。本文通过在线笔记应用案例,介绍如何使用 Uno Platform 优雅地应对离线状态。首先,利用 `NetworkInformation` 类检测网络状态;其次,使用 SQLite 实现离线存储;然后,在网络恢复时同步数据;最后,通过 UI 反馈提升用户体验。
106 0
|
4月前
|
安全 Apache 数据安全/隐私保护
你的Wicket应用安全吗?揭秘在Apache Wicket中实现坚不可摧的安全认证策略
【8月更文挑战第31天】在当前的网络环境中,安全性是任何应用程序的关键考量。Apache Wicket 是一个强大的 Java Web 框架,提供了丰富的工具和组件,帮助开发者构建安全的 Web 应用程序。本文介绍了如何在 Wicket 中实现安全认证,
49 0
|
4月前
|
机器学习/深度学习 数据采集 TensorFlow
从零到精通:TensorFlow与卷积神经网络(CNN)助你成为图像识别高手的终极指南——深入浅出教你搭建首个猫狗分类器,附带实战代码与训练技巧揭秘
【8月更文挑战第31天】本文通过杂文形式介绍了如何利用 TensorFlow 和卷积神经网络(CNN)构建图像识别系统,详细演示了从数据准备、模型构建到训练与评估的全过程。通过具体示例代码,展示了使用 Keras API 训练猫狗分类器的步骤,旨在帮助读者掌握图像识别的核心技术。此外,还探讨了图像识别在物体检测、语义分割等领域的广泛应用前景。
39 0
下一篇
DataWorks