Opencv车牌号字符分割

Opencv车牌号字符分割

字符分割的任务,就是把多字符图像中的每个字符从整体图像中分割出来,使其成为单个的字符图像,为下一步单个字符的图像识别做准备。

在这里插入图片描述

在这里插入图片描述

字符分割是字符识别的基础,字符分割的质量直接影响到字符识别的效果。

一、算法流程

输入原始图片,将其resize到(320, 100)尺寸,灰度化处理:

在这里插入图片描述
利用cv2.bilateralFilter函数,在保持边界清晰的情况下有效去除噪声:

在这里插入图片描述
利用cv2.Canny函数,检测图像的边缘信息:

在这里插入图片描述
对纹理图片进行裁减,主要为了消除边框纹理对后续分割带来的干扰。由于前面已经把图片固定到(320, 100)尺寸,所以边框的裁减尺寸也可以固定下来。

在这里插入图片描述
利用cv2.findContours函数,基于前面提取的纹理信息进行聚类。此时聚类出现很多无效区域,并且单个字符也会被聚类成不同区域块,不符合要求。

在这里插入图片描述
添加各种if语句做判断,筛除不合理聚类区域:

在这里插入图片描述
此时仍会出现单个字符被聚类成不同区域块的情况。借助垂直投影的思路,在水平方向上统计被投影、未被投影的位置,进而确定每个字符的起始点和结束点。

在这里插入图片描述

二、效果展示

该算法对图片分辨率要求较高。在图片清晰的情况下,分割效果能非常好。从测试集中任意选取10张车牌号图片,分割结果如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我从网上任意找了50张车牌号图片,字符分割精度能达到75%以上。如果图片分辨率足够,算法精度还能更高。

三、源码

车牌号字符分割:

import numpy as np
import cv2


if __name__ == "__main__":

    accuracy_num = 0

    for i in range(50):

        # img : original image
        path = '/home/archer/CODE/Number_Segmentation/dataset2/' + str(i+1) + '.png'
        img = cv2.imread(path)

        # img1 : resize image
        img1 = cv2.resize(img, (320, 100), interpolation=cv2.INTER_AREA)

        # img2 : gray image
        img2 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

        # img3 : noise reduction image
        img3 = cv2.bilateralFilter(img2, 11, 17, 17)

        # img4 : texture information image
        img4 = cv2.Canny(img3, 50, 150)

        # img5 : image removal image
        img5 = img4[10:90, 10:310]
        crop_img = img1[10:90, 10:310, :]

        contours, hierarchy = cv2.findContours(img5, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        candidate = []
        for cnt in contours:
            x, y, w, h = cv2.boundingRect(cnt)

            if w*h < 500:
                continue
            if w * h > 4000:
                continue
            if h < 20:
                continue
            if w > 80:
                continue

            candidate.append([x, (x + w)])

        loc = np.zeros(300)

        for j in range(len(candidate)):
            x1 = candidate[j][0]
            x2 = candidate[j][1]
            loc[x1:x2] = 1

        start = []
        end = []

        if loc[0] == 1:
            start.append(0)

        for j in range(300-1):
            if loc[j] == 0 and loc[j+1] == 1:
                start.append(j)
            if loc[j] == 1 and loc[j+1] == 0:
                end.append(j)

        if loc[299] == 1:
            end.append(299)

        print('Character start coordination : ', start, len(start))
        print('Character end coordination : ', end, len(start))

        if len(start) == 7 and len(end) == 7:

            print('The Segmentation looks well ! ')

            cv2.rectangle(crop_img, (0, 0), (start[1]-5, 80), (0, 0, 255), 2)

            for j in range(1, 7):
                x1 = start[j]
                x2 = end[j]
                y1 = 0
                y2 = 80
                cv2.rectangle(crop_img, (x1, y1), (x2, y2), (0, 0, 255), 2)

            accuracy_num = accuracy_num + 1

        cv2.namedWindow("final_crop_img")
        cv2.imshow("final_crop_img", crop_img)
        cv2.waitKey(0)

        cv2.imwrite('/home/archer/CODE/Number_Segmentation/demo/' + str(i+1) + '.jpg', crop_img)

    print('The character segmentation accuracy : ', accuracy_num/50)



四、项目链接

如果代码跑不通,或者想直接使用我自己制作的数据集,可以去下载项目链接:
https://blog.youkuaiyun.com/Twilight737

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值