车牌识别项目全过程——opencv知识自学(1)

这篇具有很好参考价值的文章主要介绍了车牌识别项目全过程——opencv知识自学(1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是opencv?

  1. OpenCV(Open Source Computer Vision Library)是开源的计算机视觉和机器学习库,提供了C++、C以及python等接口,并支持Windows、Linux、Android、MacOS平台。
  2. 在2016年以后,深度学习的应用越来越广泛,OpenCV里也添加了CNN之类的模块,可以与Tensorflow、Caffe2这些框架训练出来的模型对接。

图像数字化基础知识

一张图片,是由无数个小方格组成的。
彩色图片——是由彩色小方格组成,每一个彩色的方格都是由三个数值组成的向量量化的。(0,0,0)代表黑色,(255,255,255)代表白色,(255,0,0)代表红色。
灰色图片——是由灰色小方格组成,每一个灰色小方格都是由一个数值组成的向量量化的。
车牌识别项目全过程——opencv知识自学(1)
508行(高度)672列(宽度)的二维数字矩阵。
车牌识别项目全过程——opencv知识自学(1)
计算机会将每一个像素数字化为一个数值,灰度图的”位深度“是8bit(彩色是24位),代表将每一个方格数字化为[0,255]之间的uchar类型数字,即用256个数字来衡量灰度的深浅,值越大,代表越亮,值越小,代表越灰,255代表白色,0代表黑色。

图像获取

车牌识别项目全过程——opencv知识自学(1)

import cv2
gray_img = cv2.imread(r'C:\Users\fujie\Pictures\shunli.jpg',1) # 读入图像
cv2.imshow('Image', gray_img) # 显示图像
cv2.imwrite('images/output.jpg', gray_img)     # 保存图像
cv2.waitKey()  #等待时间,毫秒级,0表示任意中止

图像变换

对图像进行一些操作,可以看作是一种图像扩充的手段。

  • 图像增强的目的是要改善图像的视觉效果,针对给定图像的应用场合,有目的的增强图像的整体或局部特性,将原来不清晰的图像变得清晰或增强某些感兴趣的特征,扩大图像中不同物体的特征之间的差别,抑制不感兴趣的特征,使之改善图像质量、丰富信息量,将强图像判读和识别效果,满足某些特征分析的需求。

改变大小

(x,y,3)
行x——高
列y——宽
车牌识别项目全过程——opencv知识自学(1)

车牌识别内容分析

  1. 汽车牌照自动识别技术是把处理图像的方法与计算机的软件技术相连接在一起,以准确识别出车牌牌照的字符为目的,将识别出的数据传送至交通实时管理系统,以最终实现交通监管的功能。
  2. 我国的汽车车牌一般由七个字符和一个点组成。
    车牌识别大致分为四部分:图像获取(从视觉传感器中获取车辆的图像信息)——定位车牌(从原始图像中找到车牌的位置)——字符分割(将车牌进行分割,分割出七个字符用于后续的字符识别)——字符识别(对分离出的单个字符进行识别,从而识别出车牌的值)

定位车牌

从获取的图像中找到车牌所在位置(定位所在区域),并把车牌从该区域中分割出来,以便后续的字符分割使用。
车牌定位的方法主要分为四类:

  1. 基于颜色的分割:利用颜色空间的信息,包括彩色边缘算法、颜色距离算法、相似度算法。
  2. 基于纹理的分割:如利用车牌区域水平方向的纹理特征进行分割,包括小波纹理、水平梯度差纹理。
  3. 基于边缘检测的分割
  4. 基于数学形态法的分割

图像降噪

获取图像,原始图像为彩色,变为灰度图像便于后续处理。
车牌识别项目全过程——opencv知识自学(1)
原始图像包含噪声信息,噪声可以理解为由一种或多种原因造成的灰度值的随机变化,在大多数情况下,需要平滑技术(滤波)进行去除。常用的平滑处理算法包括基于二维离散卷积的高斯平滑、均值平滑。。。本次操作使用高斯平滑方法。

高斯滤波:如果有一个像素点的值远高于周围的点则可能是噪声或高频的边缘,高斯滤波对用该点周围多个点与其做加权平均等于用周边的值拉低了这个高值,也就是所谓平滑。高斯滤波在数学上的体现就是对整个图像像素值通过加权平均重赋值的操作。(加权平均可以理解为不同部分按照不同的比重进行计算再相加的结果。)
细节链接

——得到的图像与原始图像相比有些轻微的模糊。这样,单独的一个像素点在经过高斯平滑的图像上变得几乎没有影响。
车牌识别项目全过程——opencv知识自学(1)

  • OpenCV之高斯平滑:
    高斯平滑是通过做两个矩阵之间的二维离散卷积运算完成的,高斯卷积核和原始图像进行卷积。
    车牌识别项目全过程——opencv知识自学(1)

车牌识别项目全过程——opencv知识自学(1)

  • 卷积:
    车牌识别项目全过程——opencv知识自学(1)
  • 在OpenCV中给出了构建一维垂直方向上的高斯卷积核的函数:Mat getGaussianKernel(int ksize, double sigma, in ktype = CV/_64F)

形态学处理

形态学处理主要用于从图像中提取对表达和描绘区域形状有意义的图像分量,使后续的识别工作能够抓住目标对象最为本质〈最具区分能力-most discriminative)的形状特征,如边界和连通区域等。同时像细化、像素化和修剪毛刺等技术也常应用于图像的预处理和后处理中,成为图像增强技术的有力补充。

形态学处理的基本运算:腐蚀、膨胀、开运算、闭运算,击中与击不中、骨架抽取等。如腐蚀是让暗的区域变大,膨胀是让亮的区域变大。
车牌识别项目全过程——opencv知识自学(1)

进行开运算(开运算可以使图像的轮廓变得光滑, 还能使狭窄的连接断开和消除细毛刺。该操作为后面更加准确的提取车牌的轮廓做铺垫):

开运算详情链接
开运算主要是黑吃白,黑色区域变大。去除没用的信息点。
闭运算主要是白吃黑,白色区域变大。加大白色高亮区域。
车牌识别项目全过程——opencv知识自学(1)

将原始灰度图片和形态学图片结合成为一张图片进行后续的阈值分割操作:
车牌识别项目全过程——opencv知识自学(1)

阈值分割+边缘检测

阈值分割是常见的直接对图像进行分割的算法,根据图像像素的灰度值的不同而定。对应单一目标图像,只需选取一个阈值,即可将图像分为目标和背景两大类,这个称为单阈值分割;如果目标图像复杂,选取多个阈值,才能将图像中的目标区域和背景被分割成多个,这个称为多阈值分割,此时还需要区分检测结果中的图像目标,对各个图像目标区域进行唯一的标识进行区分。

通过阈值处理,就是希望能够从背景中分离出我们的研究对象。把图像分成若干个特定的、具有独特性质的区域,每一个区域代表一个像素的集合,每一个集合又代表一个物体。

采用Ostu阈值处理:在使用函数cv.threshold()进行阈值处理时,需要自定义一个阈值,并以此阈值作为图像阈值处理的依据。OTSU可以帮我们遍历所有可能的阈值,从而找到最佳的阈值。

车牌识别项目全过程——opencv知识自学(1)

进行闭运行平滑(阈值分割后未进行边缘检测)

阈值分割后加入边缘检测:(在这里使用canny边缘检测)
车牌识别项目全过程——opencv知识自学(1)
之后进行闭运算增加白色高亮区域:
车牌识别项目全过程——opencv知识自学(1)
进行开运算去除无用的白色部分 填充缝隙:
车牌识别项目全过程——opencv知识自学(1)
最后进行膨胀再次填充缝隙并增大白色高亮部分:
车牌识别项目全过程——opencv知识自学(1)
每个轮廓我们可以看作是一系列的点(像素)构成的一个有序的点集,而现在我们要提取这些白色区域的轮廓。(画出带有轮廓的原始图片)
车牌识别项目全过程——opencv知识自学(1)
现在我们已经有了轮廓,我们需要筛选出车牌所在的那个轮廓(可以看到车牌所在的区域为矩形),由于车牌宽和高的比例是固定的(车牌字符的高度和宽度是固定的,分别为90mm和45mm),依据这个几何特征,我们进行筛选,然后用绿色的线条将得到的车牌框选出来,同时截取出车牌用来做下一步的字符分割。
车牌识别项目全过程——opencv知识自学(1)
定位车牌的全部代码:文章来源地址https://www.toymoban.com/news/detail-452514.html

import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
#########该函数能够读取磁盘中的图片文件,默认以彩色图像的方式进行读取
def imread_photo(filename, flags=cv2.IMREAD_COLOR):
    return cv2.imread(filename, flags)


##############这个函数的作用就是来调整图像的尺寸大小,当输入图像尺寸的宽度大于阈值(默认1000),我们会将图像按比例缩小#######
def resize_photo(imgArr,MAX_WIDTH = 1000):
    img = imgArr
    rows, cols= img.shape[:2]     #获取输入图像的高和宽即第0列和第1列
    if cols >  MAX_WIDTH:
        change_rate = MAX_WIDTH / cols
        img = cv2.resize(img ,( MAX_WIDTH ,int(rows * change_rate) ), interpolation = cv2.INTER_AREA)
    return img

# ################高斯平滑###############
#我们首先会对图像水平方向进行卷积,然后再对垂直方向进行卷积,其中sigma代表高斯卷积核的标准差
def gaussBlur(image,sigma,H,W,_boundary = 'fill', _fillvalue = 0):
    #水平方向上的高斯卷积核
    gaussKenrnel_x = cv2.getGaussianKernel(sigma,W,cv2.CV_64F)
    #进行转置
    gaussKenrnel_x = np.transpose(gaussKenrnel_x)
    #图像矩阵与水平高斯核卷积
    gaussBlur_x = signal.convolve2d(image,gaussKenrnel_x,mode='same',boundary=_boundary,fillvalue=_fillvalue)
    #构建垂直方向上的卷积核
    gaussKenrnel_y = cv2.getGaussianKernel(sigma,H,cv2.CV_64F)
    #图像与垂直方向上的高斯核卷积核
    gaussBlur_xy = signal.convolve2d(gaussBlur_x,gaussKenrnel_y,mode='same',boundary= _boundary,fillvalue=_fillvalue)
    return gaussBlur_xy


def chose_licence_plate(contours, Min_Area=2000):
    temp_contours = []
    for contour in contours:
        if cv2.contourArea(contour) > Min_Area:
            temp_contours.append(contour)
    car_plate = []
    for temp_contour in temp_contours:
        rect_tupple = cv2.minAreaRect(temp_contour)
        rect_width, rect_height = rect_tupple[1]
        if rect_width < rect_height:
            rect_width, rect_height = rect_height, rect_width
        aspect_ratio = rect_width / rect_height
        # 车牌正常情况下宽高比在2 - 5.5之间
        if aspect_ratio > 2 and aspect_ratio < 5.5:
            car_plate.append(temp_contour)
            rect_vertices = cv2.boxPoints(rect_tupple)
            rect_vertices = np.int0(rect_vertices)
    return car_plate

def license_segment( car_plates ):
    if len(car_plates)==1:
        for car_plate in car_plates:
            row_min,col_min = np.min(car_plate[:,0,:],axis=0)
            row_max, col_max = np.max(car_plate[:, 0, :], axis=0)
            cv2.rectangle(img, (row_min,col_min), (row_max, col_max), (0,255,0), 2)
            card_img = img[col_min:col_max,row_min:row_max,:]
            cv2.imshow("img", img)
        cv2.imwrite( "card_img.png", card_img)
        cv2.imshow("card_img.png", card_img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    return  "card_img.png"


if __name__ == "__main__":

    img = imread_photo("car_test.png")  # 默认读取彩色图片
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 将彩色图片转换为灰色图片,灰色图像更便于后续处理。
    rgray_img = resize_photo(gray_img)

    # 高斯平滑
    blurImage = gaussBlur(gray_img, 5, 400, 400, 'symm')
    #对bIurImage进行灰度级显示
    blurImage = np.round(blurImage)
    blurImage = blurImage.astype(np.uint8)

    kernel = np.ones((10, 10), np.uint8)
    #开运算
    img_opening = cv2.morphologyEx(blurImage, cv2.MORPH_OPEN, kernel)
    # cv2.imshow("GaussBlur_gray_img", blurImage)
    # cv2.imshow("xingtai_gray_img", img_opening)


    #将两幅图像合成为一幅图像
    img_opening = cv2.addWeighted(rgray_img, 1, img_opening, -1, 0)
    # cv2.imshow("hecheng_gray_img", img_opening)



    #阈值分割
    t, result_img = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    # cv2.imshow("yuzhi_gray_img",result_img)
    #canny边缘检测
    img_edge = cv2.Canny(result_img, 100, 200)
    # cv2.imshow("bianyuan_gray_img", img_edge)
    #闭运算来填充白色物体内细小黑色空洞的区域并平滑其边界
    kernel1 = np.ones((18, 18), np.uint8)
    img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel1)
    # cv2.imshow("biyunsuan", img_edge1)

    kernel2 = np.ones((10, 10), np.uint8)
    img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel2)
    # cv2.imshow("kaiyunsuan", img_edge2)

    kernel = np.ones((20, 20), np.uint8)
    img_dilate = cv2.dilate(img_edge2, kernel)  # 膨胀
    cv2.imshow("dilate", img_dilate)  # 显示图片

    # #查找图像边缘整体形成的矩形区域, contours是找到的多个轮廓
    image, contours, hierarchy = cv2.findContours(img_dilate,cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    # cv2.imshow("xunzhao", hierarchy)

    draw_img = img.copy()
    result = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)
    # 画出带有轮廓的原始图片
    cv2.imshow('ret',result)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    car_plates = chose_licence_plate(contours)
    card_img = license_segment(car_plates)

到了这里,关于车牌识别项目全过程——opencv知识自学(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 探索 Spring Boot 项目全过程

    在 Java 这个圈子,一提到框架就不得不提到 Spring Boot;那 Spring Boot 到底是何许物也呢?Spring Boot 就是简化 Spring 程序开发的框架。怎样理解 Spring Boot 和Spring 之间的关系呢?一句话总结: “Spring 的诞⽣是为了简化 Java 程序的开发的,而 Spring Boot 的诞⽣是为了简化 Spring 程序开

    2024年02月11日
    浏览(43)
  • 探索Maven创建项目全过程(超详细~~~)

    Maven 这个词翻译为“专家”,“内行”。作为一个 Apache 组织中一个成功的开源项目,Maven 主要服务于基于 java 平台的项目构建,依赖管理和项目信息管理,还可以用来帮助实现项目的构建、测试、打包和部署。 这次演示建立的Mavenue项目是关于Servlet的,下面介绍一下Servlet

    2024年02月06日
    浏览(26)
  • Vue项目部署上线全过程(保姆级教程)

    上线前准备 1.先在vue.config.js文件中配置反向代理解决跨域请求问题 2.在vue项目根目录运行 npm run build 打包完成后会在根目录生成dist文件夹,这个dist文件夹需要上传到服务器 3.链接云服务器,在 /usr/local/ 下创建 web文件夹 用来存放dist文件夹 通过可视化工具上传dist文件夹,上

    2024年01月23日
    浏览(38)
  • opencv-python学习笔记(十一):HOG+SVM进行行人检测全过程

    本次是接着python-opencv学习笔记(七):滑动窗口与图像金字塔 一起在实验楼所做实验,为啥中间隔了四篇才接着发出来,主因是我发文比较随意(懒),当时这部分并没有总结完,至少我感觉我看的相关资料还不够多,整体理解不深,另外就是项目需求,在做很多其它的东

    2024年02月05日
    浏览(36)
  • Vue项目分包打包配置(包含dev)全过程

    今天领导要求支援某项目的分包配置,emmm,在参考了公司其他项目的分包操作后,依葫芦画瓢,中间也踩了好几个坑,简单记录下过程。 哈哈哈,上来就踩坑了,我拉了代码后,直接哐哐整,然后一堆依赖报错,我才发现,同事新增了依赖包,我并不知道,然后就乖乖安装

    2024年02月05日
    浏览(44)
  • DockerCompose - 微服务项目部署全过程(最佳实践)

    目录 一、微服务项目部署 1.1、项目介绍 1.2、准备 MySQL 初始化文件 1.3、pom.xml 插件 1.4、测试工作 1.5、编写 Dockerflie 文件 1.6、编写 DockerCompose.yml 文件 1.7、修改 application.yml 文件 1.8、打包上传服务器 1.9、微服务,启动! 1.10、测试结果 a)技术选型:SpringCloud 2021.0.1 、SpringC

    2024年04月16日
    浏览(28)
  • .net core 项目部署linux系统全过程

      使用Xshell远程连接阿里云服务器 - 程序员大本营 使用Xshell远程连接阿里云服务器,程序员大本营,技术文章内容聚合第一站。 https://www.pianshen.com/article/2750375233/      配置完之后 绑定密钥对。   保存密钥文件到桌面。   家庭/学校免费 - NetSarang Website https://www.xshell.com/z

    2024年02月05日
    浏览(31)
  • 关于建立一个Java项目全过程(专对于新手)

    JDK = JRE + 开发工具集(例如Javac编译工具等) JRE = JVM + Java SE标准类库 下载网址(Oracle公司官网):www.oracle.com 这里链接具体下载网址:https://www.oracle.com/java/technologies/downloads/ 复制链接打开后会出现以下内容 这里我们选择JDK17,因为这个版本的更稳定,更完善一些 然后点击链

    2024年02月07日
    浏览(39)
  • Ubuntu20.04 使用Python实现全过程离线语音识别(包含语音唤醒,语音转文字,指令识别,文字转语音)

      因为手头有一个项目,该项目需要在香橙派上实现语音控制,并且带有语音唤醒功能。简单来说,就是通过唤醒词唤醒香橙派,然后说出相关指令,香橙派去执行指令。   但是,在弄香橙派的时候,自带的麦克风不好使了,单独进行麦克风测试的时候是好使的,但是程

    2024年02月05日
    浏览(32)
  • gitlab上传新项目全过程+常见问题解决

    基本操作 1、首先需要在gitlab上新建一个空项目 2、编辑项目名称 3、在本地电脑上新建一个空的文件夹(或者是一个固定统一的文件夹),方便后续找到,这里会将gitlab的项目拉到这个文件内,点击进入这个文件夹,右键选择git bash here。 4、输入 git clone 地址 ,此地址可以在

    2024年02月09日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包