车牌检测与定位

进行车牌识别包含车牌检测+车牌识别

车牌检测:图像分割+特征提取
车牌识别:对检测到的车牌进行内容识别

车牌检测的方法

车牌主要包括以下几种:

蓝牌白字:普通小型车(其中包括政府机关专用号段、政法部门警车以外的行政用车)的牌照

黄牌黑字:大型车辆、摩托车、驾校教练车牌照

黑牌白字:涉外车辆牌照,式样和蓝牌基本相同

白牌:政法部门(公安、法院、检察院、国安、司法)警车、武警部队车辆、解放军军车的牌照都是白牌

警车:公安警车的牌照样式为[某·A1234警],除“警”为红字外其他的都是黑字,一共4位数字,含义与普通牌照相同

车牌检测定位的方法:

  1. 基于边缘
  2. 基于颜色
  3. 基于机器学习

对于边缘图像,如果车牌在图像中占得比例不是很小,普通的差分或者全局二值化就可以达到很好的效果;

对于高清图像或场景很复杂的情况,车牌所占比例很小,或车牌处于较暗的地方,而整个场景很亮,此时差分不会得到很好的效果,可以对图像进行对比度增强,但对比度增强可能导致噪声点特别多,导致车牌区域检测不到边缘。

检测可以用到的特征:

  1. 颜色特征

    每种车牌的底色具有各自特殊的RGB值,例如程序中使用的蓝底车牌的典型RGB值为 R = 28,G = 63, B = 138;
    当RGB值接近时则认为可能是车牌,将该点像素赋值为255,否则0;利用颜色特征可以获取二值图像,可以去除大部分的其他物体,但是会有很多的干扰。

  2. 大小特征

    对二值图像进行膨胀处理和腐蚀处理之后,可以去掉很小的噪点。对于灰度图获取轮廓边缘,轮廓具有一定的面积。车牌应该具有一定的大小,如果面积过小则认为不是车牌。此法可以去除大部分的小面积的干扰物。

    颜色特征和大小特征是初选。形状特征是精选。

  3. 形状特征

    矩形度:提取轮廓之后,轮廓包围的面积和轮廓最小外接矩形的面积之比称为矩形度,值越接近1,则是矩形的概率越大。

    长宽比:正常车牌的长宽比为3:1,最小外接矩形的长宽比越接近1则认为是车牌的概率最大。

    如果三个筛选条件都符合,则是车牌的概率非常大。

流程:

  1. 对图像进行灰度转换(如果不利用颜色的话要先进行该步骤)
  2. 高斯滤波进行去噪
  3. 定位竖直边缘,利用sobel算子,因为车牌的字符主要是竖直方向分开的
  4. 阈值化提取边缘
  5. 闭操作对提取的边缘进行连通,找到连通区域,为后续定位做准备
  6. 去除背景干扰
  7. 利用矩阵找到矩形连通域,此时会有很多矩形框被认为可能是车牌区域
  8. 利用车牌的长:宽来去掉很多不可能是车牌区域的框
  9. 去掉因拍摄带来的仿射变换
  10. 得到若干个大小相同的矩形区域
  11. 调用已经利用正负样本训练好的SVM对是否为车牌区域进行分类,找到车牌区域
import cv2
import numpy as np
import math

""" 输入图像归一化 """


def stretch(img):
    max = float(img.max())
    min = float(img.min())

    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            img[i, j] = (255 / (max - min)) * img[i, j] - (255 * min) / (max - min)

    return img


def dobinaryzation(img):
    max = float(img.max())
    min = float(img.min())

    x = max - ((max - min) / 2)
    ret, thresholdimg = cv2.threshold(img, x, 255, cv2.THRESH_BINARY)

    return thresholdimg


def find_retangle(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, orgimg):
    img, contours, hierachy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

    # 找到最大的三个区域
    blocks = []
    for c in contours:
        # 找出轮廓的左上和右下点,计算出其面积和长宽比
        r = find_retangle(c)
        a = (r[2] - r[0]) * (r[3] - r[1])
        s = (r[2] - r[0]) / (r[3] - r[1])

        blocks.append([r, a, s])

    # 选出面积最大的3个区域
    blocks = sorted(blocks, key=lambda b: b[2])[-3:]

    # 使用颜色识别判断出最像车牌的区域
    maxweight, maxinedx = 0, -1

    for i in range(len(blocks)):
        b = orgimg[blocks[i][0][1]:blocks[i][0][3], blocks[i][0][0]:blocks[i][0][2]]
        # RGB 转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)

        # 统计权值
        w1 = 0
        for m in mask:
            w1 += m / 255

        w2 = 0
        for w in w1:
            w2 += w

        # 选出最大权值的区域
        if w2 > maxweight:
            maxindex = i
            maxweight = w2

    return blocks[maxindex][0]


def find_license(img):
    '''预处理'''
    # 压缩图像
    a = 400 * img.shape[0] / img.shape[1]
    a = int(a)
    img = cv2.resize(img, (400, a))
    cv2.imshow('img',img)
    cv2.waitKey()

    # RGB转灰色
    grayimg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    cv2.imshow('grayimg', grayimg)
    cv2.waitKey()

    # 灰度拉伸
    stretchedimg = stretch(grayimg)
    cv2.imshow('stretchedimg', stretchedimg)
    cv2.waitKey()

    # 进行开运算,用来去除噪声
    r = 16
    h = w = r * 2 + 1
    kernel = np.zeros((h, w), dtype=np.uint8)
    cv2.circle(kernel, (r, r), r, 1, -1)
    openingimg = cv2.morphologyEx(stretchedimg, cv2.MORPH_OPEN, kernel)
    cv2.imshow('openingimg', openingimg)
    cv2.waitKey()

    strtimg = cv2.absdiff(stretchedimg, openingimg)
    cv2.imshow('strtimg', strtimg)
    cv2.waitKey()

    # 图像二值化
    binaryimg = dobinaryzation(strtimg)
    cv2.imshow('binaryimg', binaryimg)
    cv2.waitKey()

    # Canny算子进行边缘检测
    cannyimg = cv2.Canny(binaryimg, binaryimg.shape[0], binaryimg.shape[1])
    cv2.imshow('cannyimg', cannyimg)
    cv2.waitKey()

    '''消除小区域,连通大区域'''
    # 进行闭运算
    kernel = np.ones((5, 19), np.uint8)
    closingimg = cv2.morphologyEx(cannyimg, cv2.MORPH_CLOSE, kernel)
    cv2.imshow('closingimg', closingimg)
    cv2.waitKey()

    # 进行开运算
    openingimg = cv2.morphologyEx(closingimg, cv2.MORPH_OPEN, kernel)
    cv2.imshow('openingimg', openingimg)
    cv2.waitKey()

    # 再次进行开运算
    kernel = np.ones((11, 5), np.uint8)
    openingimg = cv2.morphologyEx(openingimg, cv2.MORPH_OPEN, kernel)
    cv2.imshow('openingimg', openingimg)
    cv2.waitKey()

    # 消除小区域,定位车牌位置
    rect = locate_license(openingimg, img)
    return rect, img


if __name__ == '__main__':
    orgimg = cv2.imread('car3.jpg')
    rect, img = find_license(orgimg)

    cv2.rectangle(img, (rect[0], rect[1]), (rect[2], rect[3]), (0, 255, 0), 2)
    cv2.imshow('img', img)
    cv2.waitKey()
    cv2.destroyAllWindows()


  1. 原图
    车牌检测与定位_第1张图片

  2. 灰度化
    车牌检测与定位_第2张图片

  3. 灰度拉伸
    车牌检测与定位_第3张图片

  4. 开运算
    车牌检测与定位_第4张图片

  5. 将灰度拉伸后的图和开运算后的图的差的绝对值输出
    车牌检测与定位_第5张图片

  6. 二值化
    车牌检测与定位_第6张图片

  7. Canny边缘检测
    车牌检测与定位_第7张图片

  8. 对边缘进行闭运算消除小区域,连通大区域
    车牌检测与定位_第8张图片

  9. 开运算
    车牌检测与定位_第9张图片

  10. 再次进行开运算

    车牌检测与定位_第10张图片

  11. 消除小区域,使用颜色识别出车牌位置

    车牌检测与定位_第11张图片

你可能感兴趣的:(图像处理)