IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> 车牌分割实战 -> 正文阅读

[人工智能]车牌分割实战

对于车牌分割我会从以下几个知识点来论述,最后对车牌分割的代码进行详解

1.图像边缘

图像边缘,即表示图像中一个区域的终结和另一个区域的开始,图像中相邻区域之间的像素集合构成了图像的边缘。所以,图像边缘可以理解为图像灰度发生空间突变的像素的集合。图像边缘有两个要素,即:方向和幅度。沿着边缘走向的像素值变化比较平缓;而沿着垂直于边缘的走向,像素值则变化得比较大。因此,根据这一变化特点,通常会采用一阶和二阶导数来描述和检测边缘。
综上,图像中的边缘检测可以通过对灰度值求导数来确定,而导数可以通过微分算子计算来实现。在数字图像处理中,通常是利用差分计算来近似代替微分运算。如下图所示。
在这里插入图片描述

2.Canny算子

Canny边缘检测算法的原理:

  1. 首先要对原始图像进行灰度化
  2. 对图像进行高斯滤波:这个应该都很清楚了,就是采用高斯核函数,根据其sigma 的不同对图像进行不同程度的模糊处理,虽然叫模糊处理,实质是滤除了高频的噪声。
  3. 根据Canny算法所采用的卷积算子,对灰度图像求梯度。
    卷积算子为:在这里插入图片描述
    在这里插入图片描述
  4. 对梯度幅值进行非极大值抑制。
    通过上面的计算,就已经确定了每个像素的梯度和幅值,该点的像素梯度方向会根据邻域像素,计算8个方向的梯度直方图,由此确定该点像素的主方向。通常像素点局部最大值就是边缘点,垂直于该梯度方向,下一个点(可能点 s 和 r)为下一个边缘点(在两个像素点之间,可以通过邻域两个像素点进行插值来计算)

3.形态学(膨胀和腐蚀)

膨胀就是求局部最大值的操作。按数学方面来说,膨胀或者腐蚀操作就是将图像(或图像的一部分区域,我们称之为A)与核(我们称之为B)进行卷积,即计算核B覆盖的区域的像素点的最大值,并把这个最大值赋值给参考点指定的像素。这样就会使图像中的高亮区域逐渐增长。(膨胀的处理效果)如下图所示。
在这里插入图片描述
腐蚀就是求局部最小值的操作。(腐蚀的处理效果)如下图所示。
在这里插入图片描述
数学公式对比:
在这里插入图片描述

4.开运算和闭运算

因为没有深入去了解基于数学基础是怎么实现的,这里只赘述了开运算和闭运算对图像有什么作用,以及试验的结果:
开运算(Opening Operation)其实就是先腐蚀后膨胀的过程:开运算可以用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积,如下图所示。
在这里插入图片描述
闭运算(Closing Operation)是先膨胀后腐蚀的过程:闭运算能够排除小型黑洞。如下图所示。
在这里插入图片描述

5.车牌分割完整代码

import cv2
import numpy as np
from PIL import Image
import os.path
from skimage import io,data

def stretch(img):
    #图像拉伸函数
    maxi = float(img.max())
    #print(maxi) #255.0
    mini = float(img.min())
    #print(mini) 0.0
    #[0]图像的高 [1]图像的宽 [2]图像的通道数
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            img[i,j] = (255/(maxi-mini)*img[i,j]-(255*mini)/(maxi-mini))
    #print(img.shape[0]) 266
    #print(img.shape[1]) 400
    return img

def dobinaryzation(img):
    #二值化处理函数
    maxi = float(img.max())
    #print(img.max())   #205
    mini = float(img.min())
    #print(img.min())   0
    x = maxi-((maxi-mini)/2)
    #print(x)   102.5
    #二值化,返回阈值ret和二值化操作后的图像thresh
    ret,thresh = cv2.threshold(img,x,255,cv2.THRESH_BINARY)
    #返回二值化后的黑白图像
    return thresh

def find_rectangle(contour):
    #寻找矩形轮廓
    y,x = [],[]
    for p in contour:
        y.append(p[0][0])
        x.append(p[0][1])
    return [min(y),min(x),max(y),max(x)]

def locate_license(img,afterimg):
    #定位车牌号
    img,contours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    #找出最大的三个区域
    n=len(contours)
    print(n)  #16
    block = []
    for c in contours:
        #找出轮廓的左上点和右下点,由此计算它的面积和长度比
        r = find_rectangle(c)
        a = (r[2]-r[0])*(r[3]-r[1])#面积
        s = (r[2]-r[0])/(r[3]-r[1])#长度比
        block.append([r,a,s])
        #选出面积最大的三个区域
        block = sorted(block,key=lambda b:b[1])[-3:]
        # print(len(block))  16
        #使用颜色识别判断找出最像车牌的区域
        maxweight,maxindex = 0,-1
    for i in range(len(block)):
        b = afterimg[block[i][0][1]:block[i][0][3],block[i][0][0]:block[i][0][2]]
        #bgr转hsv
        hsv = cv2.cvtColor(b,cv2.COLOR_BGR2HSV)
        #蓝色车牌的范围
        lower = np.array([100,50,50])
        upper = np.array([140,255,255])
        #根据阈值构建掩摸
        mask = cv2.inRange(hsv,lower,upper)
        #print(mask)
        #统计权值
        w1 = 0
        for m in mask:
            w1 += m/255
        w2 = 0
        #选出权值最大的区域
        for n in w1:
            w2 += n
        if w2 > maxweight:
            maxindex = i    #16个矩形框中的哪一个
            maxweight = w2
    return block[maxindex][0]

def find_license(img):
    #预处理函数
    m = 400*img.shape[0]/img.shape[1]
    print(m)
    #print(img.shape[0])  600 高
    #print(img.shape[1])  900 宽
    #压缩图像
    img = cv2.resize(img,(400,int(m)),interpolation=cv2.INTER_CUBIC)
    #print(img.shape[0])  266  img.shape[1]  400  (266,400)
    #bgr转换成灰度图像
    gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    #灰度拉伸
    stretchedimg = stretch(gray_img)
    #开运算,用来去除噪声
    r=16
    h=w=r*2+1
    kernel =np.zeros((h,w),np.uint8)
    cv2.circle(kernel,(r,r),r,1,-1)
    #开运算
    openingimg = cv2.morphologyEx(stretchedimg,cv2.MORPH_OPEN,kernel)
    #获取差分图像,两幅图像做差
    strtimg = cv2.absdiff(stretchedimg,openingimg)
    #图像二值化
    binaryimg = dobinaryzation(strtimg)
    #canny边缘检测
    canny = cv2.Canny(binaryimg,binaryimg.shape[0],binaryimg.shape[1])
    #消除小的区域,保留大的区域,从而定位车牌
    #进项闭运算
    kernel = np.ones((5,19),np.uint8)
    closingimg = cv2.morphologyEx(canny,cv2.MORPH_CLOSE,kernel)
    #进行开运算
    openingimg = cv2.morphologyEx(closingimg, cv2.MORPH_OPEN, kernel)
    #再次进行开运算
    kernel = np.ones((11,5),np.uint8)
    openingimg = cv2.morphologyEx(openingimg,cv2.MORPH_OPEN,kernel)
    #消除小区域,定位车牌位置
    rect = locate_license(openingimg,img)
    return rect,img
def cut_license(afterimg,rect):
    #图像分割函数
    #转换为宽度和高度
    rect[2]=rect[2]-rect[0]
    rect[3]=rect[3]-rect[1]
    rect_copy = tuple(rect.copy())
    rect=[0,0,0,0]
    #创建掩摸
    mask = np.zeros(afterimg.shape[:2],np.uint8)
    #创建背景模型,大小只能为13*5 行数只能为1 单通道浮点数
    bgdmodel = np.zeros((1,65),np.float64)
    #创建前景模型
    fgdmodel = np.zeros((1,65),np.float64)
    #分割图像
    cv2.grabCut(afterimg,mask,rect_copy,bgdmodel,fgdmodel,5,cv2.GC_INIT_WITH_RECT)
    mask2 = np.where((mask==2)|(mask==0),0,1).astype('uint8')
    #找到所有确定的背景或可能的背景像素,并将它们设置为0 ,所有其他像素应该标记为1(即:,前景)
    img_show = afterimg*mask2[:,:,np.newaxis]
    return img_show
def deal_license(licenseimg):
#车牌图片二值化
    #车牌变为灰度图像
    gray_img = cv2.cvtColor(licenseimg,cv2.COLOR_BGR2GRAY)
    #均值滤波,去除噪声
    kernel = np.ones((3,3),np.float32)/9
    gray_img = cv2.filter2D(gray_img,-1,kernel)
    #二值化处理
    ret,thresh = cv2.threshold(gray_img,120,255,cv2.THRESH_BINARY)
    return thresh

if __name__ == '__main__':
    img = cv2.imread('car3.jpg',cv2.IMREAD_COLOR)
    #预处理图像
    #img = stretch(img)
    #cv2.imshow('img',img)
    rect,afterimg = find_license(img)
    #框处车牌号
    cv2.rectangle(afterimg,(rect[0],rect[1]),(rect[2],rect[3]),(0,255,0),2)
    cv2.imshow('afterimg',afterimg)
    #分割车牌与背景
    cutimg = cut_license(afterimg,rect)
    cv2.imshow('cutimg',cutimg)
    #二值化生成黑白图
    thresh = deal_license(cutimg)
    cv2.imshow('thresh',thresh)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

6.实验结果

以上是车牌区域分割的完整代码,分割效果如下:
在这里插入图片描述
在这里插入图片描述
从分割结果来看,还是不错的,那么接下来我们就仔细的剖析一下代码(说明:图片完全是我自己整理的笔记然后截图过来的,因为这是老师给我们布置的一次小实验,我是Word整理好的。图片解析的顺序也是根据函数的顺序依次进行排列的,有想要PDF或者Word的小伙伴可以直接私信我):

7.代码解析

1.预处理 图像拉伸
在这里插入图片描述
2.图像预处理 二值化处理
在这里插入图片描述
3.寻找矩形轮廓
在这里插入图片描述
在这里插入图片描述
4.对图像拉伸(涉及函数的调用)、开运算和闭运算、以及对图像Canny边缘检测
在这里插入图片描述
在这里插入图片描述
5.图像分割函数
在这里插入图片描述
6.分割得到的车牌区域二值化
在这里插入图片描述
到这里车牌分割的代码就解读完了,其实车牌分割还可以应用很多种方法,一般的车牌区域都是长方形区域,就可以根据查找车身的矩形框来做;还可以根据车牌的颜色来分割,一般的车牌都是蓝白和黄白,完全可以根据颜色实现分割。

7.实验不足与展望
首先对于车牌区域模糊的图像,处理的效果并不是很理想,还有对倾斜车身的这样的情况,车牌分割的效果也不是很理想,我看了很多的文章,有很多人用到了仿射变换的方法,这个我没有尝试。另外就是程序中,对图像进行开运算和闭运算,这个开和闭的顺序朋友们可以自己去尝试,也可以试试两次开运算一次闭运算,反之两次闭运算一次开运算。总的来说,需要改进的地方还很多~~

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2021-07-25 11:39:27  更:2021-07-25 11:43:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/25 9:38:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码