手撕系列:原生python实现汽车牌照识别

本文介绍了一种使用Python实现汽车车牌识别的方法,包括车牌定位、字符分割和识别。通过图像处理、KNN算法、逻辑回归和决策树等机器学习技术,详细阐述了每个步骤的实现过程,涉及HSV转换、二值化、形态学操作和连通分量分析等技术。
摘要由CSDN通过智能技术生成

前言

这几天一直在做一个车牌识别的小程序,除了python中numpy作为操作像素的工具,其他部分均为自己实现,也算是检验自己,并锻炼自己的编码能力了。

文章中的算法仅为实现,效率不一定好,希望有大佬可以指点。机器学习算法中只贴出了最主要的一部分,关于一些数学计算函数实现,由于太多就不贴了。

问题

想要实现一个车牌识别的程序,我们要处理的一个最最基本的问题就是要对车牌进行定位,定位出来车牌之后,还要对车牌上的字进行分割,然后再对这些字一个一个的识别。

为了识别这些字,我们需要自己训练模型,然而训练模型的过程中,又需要用到数据,这里提一下,如果真的为了提高准确率,还是自己去做一个数据集,因为当你使用别人的数据集的时候,你对切割出来的字的处理方式如果和别人不一样,就会导致识别准确率特别低。

所以总结一下,在整个项目中,需要解决以下问题:

  1. 对车牌进行定位
  2. 对车牌进行分割
  3. 收集数据,训练模型
  4. 写一个图形化界面,简化操作

再总结一下就是

  • 图像处理
  • 模式识别算法(机器学习)

解决问题:车牌定位

我们在对车牌定位的时候,一定要尽可能的利用先验知识,比如说,现在绝大部分车的车牌为蓝底白字,大部分车牌的比例约为4:1,且车牌是有七个字符组成。后面在解决问题的过程中,我们会用到上述先验知识,废话不多说,下面说一下怎么解决车牌定位问题。

第一步,我们肯定是要读取图片,为了体现手撕二字,所以这一部分我们要自己写,这里之前的博客有记录过不过多描述,直接上代码,这里以BMP位图为例,点击这里详细了解

    def Parse(self,fileName):
        f=open(fileName,'rb')
        file_type=str(f.read(2),encoding='utf-8')
        assert file_type=='BM',"文件类型错误"
        file_size_byte = f.read(4)  # 这个可以用来读取文件的大小 需要读取4个字节
        f.seek(f.tell() + 4)  # 跳过中间无用的四个字节
        file_ofset_byte = f.read(4)  # 读取位图数据的偏移量
        f.seek(f.tell() + 4)  # 跳过无用的两个字节
        file_wide_byte = f.read(4)  # 读取宽度字节
        file_height_byte = f.read(4)  # 读取高度字节
        f.seek(f.tell() + 2)  ## 跳过中间无用的两个字节
        file_bitcount_byte = f.read(4)  # 得到每个像素占位大小
        #下面就是将读取的字节转换成指定的类型
        self.f_size,=struct.unpack('l',file_size_byte)
        self.f_ofset,=struct.unpack('l',file_ofset_byte)
        self.f_width,=struct.unpack('l',file_wide_byte)
        self.f_height,=struct.unpack('l',file_height_byte)
        self.f_bitcount,=struct.unpack('i',file_bitcount_byte)
        # 判断是否有颜色表
        if self.f_ofset==1078:
            self.__256Image__(fileName)#处理伪彩色图像
        else:
            self.__24BImage(fileName) #处理真彩色图像
    def __256Image__(self,f_name):
        '然后来读取颜色表'
        f=open(f_name,'rb')
        self.colorTab = np.array([],dtype=int)
        f.seek(54)  # 跳过文件信息头和位图信息头
        for i in range(0, 256):
            b = struct.unpack('B', f.read(1))[0]
            g = struct.unpack('B', f.read(1))[0]
            r = struct.unpack('B', f.read(1))[0]
            alpha = struct.unpack('B', f.read(1))[0]
            self.colorTab=np.append(self.colorTab,np.array([r,g,b,255]))
        self.colorTab=self.colorTab.reshape(256,4)
        '下面部分用来读取BMP位图数据区域,将数据存入numpy数组'
        # 首先对文件指针进行偏移
        f.seek(self.f_ofset)
        # 因为图像是8位伪彩色图像,所以一个像素点占一个字节,即8位
        img = np.empty(shape=[self.f_height, self.f_width, 4], dtype=int)
        cout = 0
        for y in range(0, self.f_height):
            for x in range(0, self.f_width):
                cout = cout + 1
                index = struct.unpack('B', f.read(1))[0]
                img[self.f_height - y - 1, x] = self.colorTab[index]
            while cout % 4 != 0:
                f.read(1)
                cout = cout + 1
        self.Img=img
    def __24BImage(self,f_name):
        f=open(f_name,'rb')
        f.seek(self.f_ofset)
        img=np.empty(shape=[self.f_height,self.f_width,3],dtype=int)
        cout=0
        for y in range(0,self.f_height):
            for x in range(0,self.f_width):
                BYTES=f.read(3)
                x1,x2,x3=struct.unpack('BBB',BYTES)
                cout=cout+3
                img[self.f_height - y - 1, x]=np.array([x3,x2,x1])
            while cout%4!=0:
                cout=cout+1
                f.read(1)
        self.Img=img

当我们把一副图片读取出来,转换成一个个像素之后,剩下的工作就是对这些像素点进行操作了。

来看看我们读取后的图片长什么样子
在这里插入图片描述

第二步,将RGB图像转换成HSV图像。

这里之所以这么做,是因为我们利用大部分车牌为蓝底白字的特点,我们想通过蓝色来找到车牌的大概位置。但是如果你想在RGB颜色空间中准确定位蓝色是很不容易的,但是在HSV颜色空间中就很容易了。如果想要了解HSV颜色空间,请点击这里。对于RGB转换为HSV,以及HSV转换为RGB也是有公式的,利用下面公式我们就可以很轻松的进行编码。
在这里插入图片描述

在这里插入图片描述
利用python实现上述转换很容易,代码如下:

'RGB转HSV'
def convertHSV(img):
    HSV=np.empty(shape=img.shape)
    art60 = np.pi / 3
    for y in range(0,len(img)):
        for x in range(0,len(img[y])):
            rgb=img[y,x]
            rgb=rgb/255
            r=rgb[0]
            g=rgb[1]
            b=rgb[2]
            c_m,c_n=0,255
            for color in rgb:
                if color>c_m:
                   c_m=color
                if color<c_n:
                    c_n=color
            eta=c_m-c_n
            H,S,V=0,0,0
            if eta==0:
                H=0
            elif c_m==r:
                H=art60*((g-b)/eta)
            elif c_m==g:
                H=art60*((b-r)/eta+2)
            elif c_m==b:
                H=art60 * ((r - g)/eta+4)
            if c_m==0:
                S=0
            else:
                S=eta/c_m
            V=c_m
            HSV[y,x,0]=H
            HSV[y, x, 1] = S
            HSV[y, x, 2] = V
    return HSV
'HSV转RGB'
def HSVtoRGB(img):
    temp=np.empty(shape=img.shape,dtype=int)
    for y in range(0,len(img)):
        for x in range(0,len(img[y])):
            H, S, V = img[y, x]
            C=V*S
            X=C*(1-np.abs((H/1.047198)%2-1))
            m=V-C
            r,g,b=0,0,0
            if H>=0 and H<1.47198:
                r,g,b=C,X,0
            elif H>=1.47198 and H<2.094395:
                r,g,b=X,C,0
            elif H>=2.094395 and H<3.141593:
                r,g,b=0,C,X
            elif H>=3.141593 and H<4.18879:
                r,g,b=0,X,C
            elif H>=4.18879 and H<5.235988:
                r,g,b=X,0,C
            elif H>=5.235988 and H<6.283185:
                r,g,b=C,0,X
            R,G,B=(int((r+m)*255),int((g+m)*255),int((b+m)*255))
            temp[y,x,0]=R
            temp[y, x, 1]=G
            temp[y, x, 2]=B
    temp[temp>255]=255
    return temp

第三步,我们把RGB图像转换为HSV图像目的就是为了通过颜色进行定位,所以我们需要在HSV颜色空间中对图像进行二值化,而二值化的标准蓝色置为白色,其他颜色都置为黑色,这在RGB空间中是非常难以实现的,然后在HSV空间中却轻而易举。

经过数次实验,我发现可以比较好筛选出蓝色的HSV的范围如下
3.14 < H < 4.53 3.14<H<4.53 3.14<H<4.53
0.4 < S < 0.9 0.4<S<0.9 0.4<S<0.9
0.4 < V < 0.9 0.4<V<0.9 0.4<V<

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReWz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值