opencv 车牌的定位与分割(基于python)

一、实现效果如下(几乎没有泛化性,但是我看别的文章好像也是有这种问题)

定位的效果

 

 字符分割的效果

二、 车牌定位的实现

就是在这张车屁股的照片里定位到车牌并提取出来,涉及到的图像处理步骤如下

先转为灰度图、进行一个高斯滤波(减小噪声的影响),开运算(原理是先腐蚀后膨胀,效果是能够除去孤立的小点,毛刺和小桥,而总的位置和形状不便),闭运算(与开运算相反,有助于关闭前景物体内部的小孔,或物体上的小黑点),canny边缘检测,二值化处理.

重点:

cv2.findContours,查找二值图像中的轮廓 ,函数首先返回一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。之后在依次计算每个轮廓的面积和面积的长宽比,对轮廓进行一个筛选之后得到这牌的位置。
#实现函数的定位
def getPostion(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_copy = img_gray.copy()
    #高斯滤波 将噪声
    gray_img = cv2.GaussianBlur(img_copy, (5, 5), 0, 0, cv2.BORDER_DEFAULT)
    #开运算 将图像中不同部分分开
    kernel = np.ones((23, 23), np.uint8)
    img_opening = cv2.morphologyEx(gray_img, cv2.MORPH_OPEN, kernel)
    img_opening = cv2.addWeighted(gray_img, 1, img_opening, -1, 0) # 开运算后的图片与原始的灰度图片按一定权重进行一个融合
    # 找到图像边缘
    ret, img_thresh = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)  # 阈值分割
    img_edge = cv2.Canny(img_thresh, 100, 200) #canny 边缘检测
    # # 使用开运算和闭运算让图像边缘成为一个整体
    kernel = np.ones((9, 9), np.uint8)
    img_edge2 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel)
    #img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel) # 我测试时发现有这句代码,开运算就会把中文那部分去除
    # # 查找图像边缘整体形成的矩形区域,可能有很多,车牌就在其中一个矩形区域中
    contours, hierarchy = cv2.findContours(img_edge2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    #从找到的轮廓中找出车牌的位置
    temp_contours = []
    areaAverage = []
    for contour in contours:
        area = cv2.contourArea(contour)
       # print("面积 ", area)
        areaAverage.append(area)
    minArea = np.mean(areaAverage)
    #print("平均面积", minArea)  #我们假设车牌的面积一定大于平均面积
    temp_contours = [] #先筛除较小的轮廓
    for contour in contours:
        if cv2.contourArea(contour) > minArea:
            temp_contours.append(contour)
    car_plates = [] #可能的车牌
    for temp_contour in temp_contours:
        rect = cv2.minAreaRect(temp_contour) # 该函数返回一个rect对象, rect[0]--中心点  rect[1] -- 矩形的长、宽
        rect_width, rect_height = rect[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_plates.append(temp_contour)
    #一车只有一个车牌
    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("车牌", card_img)
            return card_img
    else:
        print("查找车牌失败")

 三、车牌字符的分割

这里用的方法和上面定位用的类似,也是使用找轮廓,设定条件筛选轮廓,显示字符,保存字符,代码如下

#字符分割部分,采用和定位类似的找轮廓的方法
def charSegment(image):
    #先转为灰度图,并二值化
    imgGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #灰度
    imgB = cv2.GaussianBlur(imgGray, (5, 5), 0, 0, cv2.BORDER_DEFAULT) #高斯去噪
    ret, img_thresh = cv2.threshold(imgB, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)  # 阈值分割

    kernel = np.ones((3, 3), np.uint8)
    img_edge = cv2.morphologyEx(img_thresh, cv2.MORPH_CLOSE, kernel)
    cv2.imshow("车牌", img_edge)
    contours, hierarchy = cv2.findContours(img_edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    char = []
    i = 1
    for contour in contours:
        area = cv2.contourArea(contour)
        print(i, "面积", area)
        if area > 154:
            char.append(contour)
            print("选择", i)
        i += 1
    j = 1
    for c in char:
        row_min, col_min = np.min(c[:, 0, :], axis=0)  # 左上角的坐标
        row_max, col_max = np.max(c[:, 0, :], axis=0)  # 右下角的坐标
        ch = image[col_min:col_max, row_min:row_max, :]  # 把矩形框中的图像显示出来
        cv2.imshow(str(j), ch)
        path = "char/" + str(j) + ".jpg"
        cv2.imwrite(path, ch)
        j += 1

四、主函数部分

if __name__ == "__main__":
    #读取一张图片
    srcImage=cv2.imread("car.jpg")#以灰度图形式读入
    # 创建一个窗口
    cv2.namedWindow("车牌")
    cv2.namedWindow("原始图像")
    cv2.namedWindow("定位")
    srcImage = reSize(srcImage)
    cv2.imshow("原始图像", srcImage)
    carPic = getPostion(srcImage)#实现车牌的定位
    cv2.imshow("定位", carPic)
    charSegment(carPic)
    # 等待任意输入
    cv2.waitKey(0)
    cv2.destroyAllWindows();

之后想进行改进,提高泛化能力,现在这个代码纯纯的只能用在一张图上。。。。

  • 3
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值