当前位置:   article > 正文

opencv-python车牌识别_opencv车牌识别python

opencv车牌识别python

opencv-python车牌识别

本文尚有很多不足的地方,例如车牌字符的定位,车牌种类的不同,复杂环境下车牌识别的问题等等。。。
不足之处请多指教
  • 1
  • 2

主要步骤

  1. 读入图像
  2. 颜色识别,设定阈值
  3. 掩模、按位运算
  4. 图形灰度化、二值化
  5. 边缘检测
  6. 开运算、闭运算
  7. 轮廓识别,输出矩阵
  8. 判断长宽比
  9. 找出车牌四角坐标
  10. 检测字符位置
  11. 字符切割
  12. 模板匹配,找出匹配最大值
  13. 结果输出

子函数介绍

(1)color_change(picture)函数
对输入的图片,现进行阈值的设定,不同颜色的车牌有不同的阈值,一般为蓝色,黄色和绿色。然后通过掩模运算突出二值化车牌的位置,极大的降低了其他背景对识别的干扰。然后在进行按位运算回复车牌原有的颜色,并返回处理过的图像。
颜色识别后的车牌
(2)binaryzation(value)函数
把color_change(picture)返回的结果转化为和灰度图并进行二值化,然后进行边缘检测,并对检测后的图像进行开运算和开运算,将车牌区域的轮廓连为一个整体。然后通过cv2.findContours()函数找出图像中单独的轮廓并返回。
cv2.findContours()参数说明:img为寻找轮廓的图像,且为二值图(黑白图)。
mode为轮廓的检索模式,有四种:cv2.RETR_EXTERNAL只检测外轮廓。cv2.RETR_LIST检测的轮廓不建立等级关系。cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。cv2.RETR_TREE建立一个等级树结构的轮廓。
method为轮廓的近似方法。cv2.CHAIN_APPROX_NONE存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1)) == 1。cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息。
返回值contours表示图像中的所有轮廓的list,np.array类型。
开闭运算输出的轮廓:
在这里插入图片描述
函数画出的轮廓:
在这里插入图片描述
(3)cut_out(value1,value2)函数
函数接收 binaryzation(value)返回的结果,利用cv2.minAreaRect(contour)函数计算识别轮廓的长宽比,确定车牌的位置。然后利用v2.boxPoints(rect)函数找出车牌四个角的坐标,最后切割车牌。
切割出的车牌:
在这里插入图片描述
(4)car_binaryzation_cut(value)函数
将cut_out(value1,value2)函数返回的图像进行二值化,然后获取图像行方向和列方向上字符的分布图,确定字符的分布位置。然后根据位置进行字符的分割。最后将分割后的字符和保存的字符库进行匹配,找出匹配度最高的图像,最后输出匹配结果。
车牌二值化的图像:
在这里插入图片描述
字符行列像素分布图:
在这里插入图片描述
字符分割后的图像:
在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述
(5)show(value,picture)函数
该函数主要用于在原始图像上添加识别后的结果,因为有汉字,所以运用PIL库进行输出。其参数为原始图像和识别后的字符串结果。
在这里插入图片描述

主代码

import cv2 
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image,ImageDraw,ImageFont

def color_change(picture):
    '''
    将图片转化到HSV空间,并按位取反,突出车牌区域
    '''
    hsv=cv2.cvtColor(picture,cv2.COLOR_BGR2HSV)     #转化为HSV颜色空间
    lower_blue=np.array([100,43,46])                              #蓝色阈值
    upper_blue=np.array([124,255,255])
    mask1=cv2.inRange(hsv,lower_blue,upper_blue)     #构建掩模
    res1=cv2.bitwise_and(image,image,mask=mask1)  #按位运算
    cv2.imwrite('111.jpg',res1)
    return res1


def binaryzation(value):
    '''
    把图象进行二值化,并进行开闭运算,最后找到可能存在的区域,并返回区域信息
    '''
    gray=cv2.cvtColor(value,cv2.COLOR_BGR2GRAY)                                          #转化为灰度图                                            
    ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)                       #图像二值化

    canny = cv2.Canny(thresh, 100, 200)                                                                #边缘检测
    kernel1 = np.ones((12,40), np.uint8)  
    img_edge1 = cv2.morphologyEx(canny, cv2.MORPH_CLOSE, kernel1)         # 闭运算  
    img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel1)  # 开运算
    cv2.imwrite('222.jpg',img_edge2)

    contours ,hierarchy = cv2.findContours(img_edge2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    #c=cv2.drawContours(image, contours, -1, (0, 255, 0), 3)
    return contours


def cut_out(value1,value2):
    '''
    通过长宽比判断车牌的位置,并截取
    '''                                
    for contour in value1:
        rect = cv2.minAreaRect(contour)   #找出最小外接矩形 中心点、宽和高、角度
        if rect[1][1]>rect[1][0]:
            k=rect[1][1]/rect[1][0]
        else:
            k=rect[1][0]/rect[1][1]
        if (k>2.5)&(k<5):    #判断车牌的轮廓
        
            a=cv2.boxPoints(rect)     #获取外接矩形的四个点
            box = np.int0(a)
            aa=cv2.drawContours(value2, [box], -1, (0, 255, 0), 3)  #找出车牌的位置     
            cv2.imwrite('aa.jpg',aa)
            x=[]
            y=[]
            for i in range(4):
                x.append(box[i][1])
                y.append(box[i][0])
            min_x=min(x)
            max_x=max(x)
            min_y=min(y)
            max_y=max(y)         
            cut=image[min_x:max_x,min_y:max_y]
            cv2.imwrite('333.jpg',cut)  
            return cut


def car_binaryzation_cut(value):
    '''
    截取车牌的二值化并切割
    '''  
    # RGB转GARY
    change_size= cv2.resize(value, (440, 140))
    gray_img = cv2.cvtColor(change_size, cv2.COLOR_BGR2GRAY)  
    ret,thresh=cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY)       #图像二值化
    cv2.imwrite('444.jpg', thresh)
    
    x=list(range(440))
    y=[]
    for i in range(440):         #获取列方向上的字符像素分布图
        n=0
        for j in range(140):
            if thresh[j,i]==255:
                n=n+1
        y.append(n)
    plt.subplot(1,2,1)
    plt.plot(x,y)     
    
    x1=list(range(140))
    y1=[]
    for i in range(140):         #获取行方向上的字符像素分布图
        n=0
        for j in range(440):
            if thresh[i,j]==255:
                n=n+1
        y1.append(n)
    plt.subplot(1,2,2)
    plt.plot(x1,y1)     
    plt.show()

    p1=thresh[15:120,12:63]
    p2=thresh[15:120,65:117]
    p3=thresh[20:120,142:197]
    p4=thresh[20:120,200:260]
    p5=thresh[20:120,260:317]
    p6=thresh[20:120,320:365]
    p7=thresh[20:120,370:425]

    cv2.imshow('1',p1)
    cv2.imshow('2',p2)
    cv2.imshow('3',p3)
    cv2.imshow('4',p4)
    cv2.imshow('5',p5)
    cv2.imshow('6',p6)
    cv2.imshow('7',p7)

    p=[p1,p2,p3,p4,p5,p6,p7]
    tem=['0.jpg','5.jpg','6.jpg','7.jpg','8.jpg','9.jpg','B.jpg','C.jpg','E.jpg','J.jpg','K.jpg','M.jpg','Q.jpg','T.jpg','U.jpg','jin.jpg','chuan.jpg','yu.jpg','lu.jpg','su.jpg','ee.jpg']
    a=['0','5','6','7','8','9','B','C','E','J','K','M','Q','T','U','晋','川','豫','鲁','苏','鄂']
    ss=[]
    for i in range(7):    #模板匹配
        s=[]
        for j in range(len(tem)):
            image1=cv2.imread(tem[j],0)      #读入图像
            __,aaa=cv2.threshold(image1,127,255,cv2.THRESH_BINARY)
            bbb= cv2.resize(aaa, (50, 100))
            result=cv2.matchTemplate(p[i],bbb,cv2.TM_CCOEFF_NORMED)
            min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
            s.append(max_val)
        ss.append(a[s.index(max(s))])
    car=ss[0]+ss[1]+'.'+ss[2]+ss[3]+ss[4]+ss[5]+ss[6]
    print(car)
    return car


def show(value,picture):
      cv2img = cv2.cvtColor(picture, cv2.COLOR_BGR2RGB) # cv2和PIL中颜色的hex码的储存顺序不同
      pilimg = Image.fromarray(cv2img)
      # PIL图片上打印汉字
      draw = ImageDraw.Draw(pilimg) # 图片上打印
      font = ImageFont.truetype("simhei.ttf", 40, encoding="utf-8") # 参数1:字体文件路径,参数2:字体大小
      draw.text((200, 200), value, (255, 0, 0), font=font) # 参数1:打印坐标,参数2:文本,参数3:字体颜色,参数4:字体
 
      # PIL图片转cv2 图片
      cv2charimg = cv2.cvtColor(np.array(pilimg), cv2.COLOR_RGB2BGR)
      cv2.imshow("result", cv2charimg)
      cv2.imwrite('555.jpg',cv2charimg)


if __name__=='__main__':                                    
    image=cv2.imread('bbb.jpg')     #读入图像
    image = cv2.resize(image, (570, 430))
    
    res=color_change(image)        #转化到HSV,并大致取出车牌位置
    a=binaryzation(res)                  #对颜色识别过的区域进行二值化,并进行开闭运算识别轮廓
    b=cut_out(a,image)                  #找到符合条件的区域,并进行切割
    c=car_binaryzation_cut(b)
    show(c,image)

    while(1):
        k=cv2.waitKey(5)&0xFF
        if k==27:
            cv2.destroyAllWindows()
            break

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/763704
推荐阅读
相关标签
  

闽ICP备14008679号