OpenCV(项目)车牌识别3 -- 模板匹配

Posted _睿智_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV(项目)车牌识别3 -- 模板匹配相关的知识,希望对你有一定的参考价值。

目录

一、基础理论

1、思想

2、大致过程

二、详细过程

1、首先需要模板库

2、得到模板

3、原图限定大小

4、模板匹配

5、匹配所有子文件夹,保存最佳得分(最匹配项)

三、大致过程(细分类,节省时间)

1、汉字匹配

 2、英文字符匹配

3、数字/英文匹配

 4、显示

模板匹配总代码

参考资料


一、基础理论

1、思想

把提取到的每一张字符,和模板库中的所有字符进行对比

2、大致过程

先拿到模板库,把模板和待匹配的图像大小限制一致,匹配每一张子模板图,匹配每张模板图匹配后都会有一个得分,得分最高的最相近。再把每个子文件夹最高得分对比,用index找到最高的那个子文件夹下标,得到模板。

二、详细过程

1、首先需要模板库

模板库下载链接1:(推荐)

https://download.csdn.net/download/great_yzl/21974008

模板库下载链接2:(不推荐)

http://www.zengqiang.club/blog/34

一个大文件夹下包含很多子文件夹:

 

 每一个子文件夹内包含该字符的一系列模板(为了更精确,牺牲了不少时间):

2、得到模板

# 路径
                path = 'Template/' + List[i] + '/' + filename
                # 1、得到模板
                template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1)    #彩(类似imread)
                gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY)                 #灰
                ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU)      #二值
                cv.imshow('template', template)
                cv.waitKey(0)

3、原图限定大小

# 2、原图限定大小(和模板相似)
                h, w = template.shape
                image = cv.resize(image, (w, h))
                cv.imshow('image_', image)
                cv.waitKey(0)

4、模板匹配

  按照名称列表的方式,遍历模板库的所有子文件夹、子文件夹内的所有子图。

# 3、模板匹配,得到得分(匹配度越高,得分越大)
                result = cv.matchTemplate(image, template, cv.TM_CCOEFF)
                score.append(result[0][0])          #得分(每张模板图)

 

5、匹配所有子文件夹,保存最佳得分(最匹配项)

匹配所有子文件夹的子图: 

# 模板匹配,得到得分(匹配度越高,得分越大)
                result = cv.matchTemplate(image, template, cv.TM_CCOEFF)
                score.append(result[0][0])          #得分(每张模板图)

 每个文件夹的最佳得分:

# 一个文件夹的最高得分(得分越高,匹配度越高)
            best_score.append(max(score))
            # 根据所有文件夹的最佳得分确定下标
            index = best_score.index(max(best_score))+34

三、大致过程(细分类,节省时间)

由于第一个必定是汉字,第二个必定是英文字符,后面的必定是英文字符/数字,我们在那里只需要做相应的判断即可。节约了很多时间。

1、汉字匹配

# (1) 汉字(首个位置只能是汉字(省))(为了节约时间)
    if con == 0:
        # 遍历34——65文件夹(汉字)
        for i in range(34,65):
            # 单个图片的得分
            score = []
            ForderPath = 'Template/' + List[i]
            # 遍历单文件夹(每一个文件匹配)
            for filename in os.listdir(ForderPath):
                # 路径
                path = 'Template/' + List[i] + '/' + filename
                # 1、得到模板
                template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1)    #彩(类似imread)
                gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY)                 #灰
                ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU)      #二值

                # 2、原图限定大小(和模板相似)
                h, w = template.shape
                image = cv.resize(image, (w, h))
                cv.imshow('image_', image)
                cv.waitKey(0)

                # 3、模板匹配,得到得分(匹配度越高,得分越大)
                result = cv.matchTemplate(image, template, cv.TM_CCOEFF)
                score.append(result[0][0])          #得分(每张模板图)

            # 4、保存子文件夹的最高得分(得分越高,匹配度越高)
            best_score.append(max(score))
            # 5、根据所有文件夹的最佳得分确定下标
            index = best_score.index(max(best_score))+34

 

 2、英文字符匹配

# (2) 字母(第二个位置只能为字母)
    elif con == 1:
        # 遍历10~34文件夹(字母文件夹)
        for i in range(10,34):
            # 单个图片的得分
            score = []
            ForderPath = 'Template/' + List[i]
            # 遍历单文件夹(每一个文件匹配)
            for filename in os.listdir(ForderPath):
                # 路径
                path = 'Template/' + List[i] + '/' + filename
                # 模板
                template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1)    #彩(类似imread)
                gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY)                 #灰
                ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU)      #二值
                h, w = template.shape
                image = cv.resize(image, (w, h))

                # 模板匹配,得到得分(匹配度越高,得分越大)
                result = cv.matchTemplate(image, template, cv.TM_CCOEFF)
                score.append(result[0][0])          #得分(每张模板图)

            # 一个文件夹的最高得分(得分越高,匹配度越高)
            best_score.append(max(score))
            # 根据所有文件夹的最佳得分确定下标
            index = best_score.index(max(best_score)) + 10

3、数字/英文匹配

# (3) 数字+字母
    else:
        # 遍历0~34文件夹(数字+字母)
        for i in range(34):
            # 单个图片的得分
            score = []
            ForderPath = 'Template/' + List[i]
            # 遍历单文件夹(每一个文件匹配)
            for filename in os.listdir(ForderPath):
                # 路径
                path = 'Template/' + List[i] + '/' + filename
                # 模板
                template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1)    #彩(类似imread)
                gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY)                 #灰
                ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU)      #二值
                h, w = template.shape
                image = cv.resize(image, (w, h))

                # 模板匹配,得到得分(匹配度越高,得分越大)
                result = cv.matchTemplate(image, template, cv.TM_CCOEFF)
                score.append(result[0][0])          #得分(每张模板图)

            # 一个文件夹的最高得分(得分越高,匹配度越高)
            best_score.append(max(score))
            # 根据所有文件夹的最佳得分确定下标
            index = best_score.index(max(best_score))

 

 4、显示

在切割字符函数的尾部,所有字符切割完、立刻进行模板匹配,同一张车牌所有字符切割完毕后,进行显示。 

# 显示识别结果(图像)
    Show_Result_Image()
# 显示识别结果(图像)
def Show_Result_Image():
    p = image_rect[0], image_rect[1]
    w, h = image_rect[2] , image_rect[3]
    # 框出车牌
    cv.rectangle(img, (p[0],p[1]), (p[0]+w, p[1]+h), (0,0,255), 2)
    # 输出字符(中文)
    result = Text(img, str(final_result), p, (255,0,0), 16)
    cv.imshow('result-%d'%count, result)
    # cv.waitKey(0)

 

模板匹配总代码

# 显示文字(中文)(用的PIL,RGB正常显示,即和opencv的RGB相反)
def Text(image, text, p, color, size):
    # cv2读取图片
    # BGR转RGB:cv2和PIL中颜色的hex码的储存顺序不同
    cv2_image = cv.cvtColor(image, cv.COLOR_RGB2BGR)
    pil_image = Image.fromarray(cv2_image)

    # PIL图片上打印汉字
    draw = ImageDraw.Draw(pil_image)  # 图片上打印
    font = ImageFont.truetype("./simhei.ttf", size, encoding="utf-8")  # 参数1:字体文件路径,参数2:字体大小
    draw.text((p[0]-60, p[1]-20), text, color, font=font)

    # PIL图片转cv2 图片
    cv2_result = cv.cvtColor(np.array(pil_image), cv.COLOR_RGB2BGR)
    # cv2.imshow("图片", cv2_result)      # 汉字窗口标题显示乱码
    # cv.imshow("photo", cv2_result)     # 输出汉字
    return cv2_result


# 显示识别结果(文字)
def Show_Result_Words(index):
    print(List[index])
    final_result.append(List[index])
    print(final_result)


# 显示识别结果(图像)
def Show_Result_Image():
    p = image_rect[0], image_rect[1]
    w, h = image_rect[2] , image_rect[3]
    # 框出车牌
    cv.rectangle(img, (p[0],p[1]), (p[0]+w, p[1]+h), (0,0,255), 2)
    # 输出字符(中文)
    result = Text(img, str(final_result), p, (255,0,0), 16)
    cv.imshow('result-%d'%count, result)
    # cv.waitKey(0)

# 三、模板匹配
# 原图和模板进行对比,越匹配,得分越大
def Template_Match(image):
    # 单文件夹内的最佳得分
    best_score = []
    # 遍历所有文件夹(每一个文件夹匹配)
    # (1) 汉字(首个位置只能是汉字(省))(为了节约时间)
    if con == 0:
        # 遍历34——65文件夹(汉字)
        for i in range(34,65):
            # 单个图片的得分
            score = []
            ForderPath = 'Template/' + List[i]
            # 遍历单文件夹(每一个文件匹配)
            for filename in os.listdir(ForderPath):
                # 路径
                path = 'Template/' + List[i] + '/' + filename
                # 1、得到模板
                template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1)    #彩(类似imread)
                gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY)                 #灰
                ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU)      #二值

                # 2、原图限定大小(和模板相似)
                h, w = template.shape
                image = cv.resize(image, (w, h))

                # 3、模板匹配,得到得分(匹配度越高,得分越大)
                result = cv.matchTemplate(image, template, cv.TM_CCOEFF)
                score.append(result[0][0])          #得分(每张模板图)

            # 4、保存子文件夹的最高得分(得分越高,匹配度越高)
            best_score.append(max(score))
            # 5、根据所有文件夹的最佳得分确定下标
            index = best_score.index(max(best_score))+34


    # (2) 字母(第二个位置只能为字母)
    elif con == 1:
        # 遍历10~34文件夹(字母文件夹)
        for i in range(10,34):
            # 单个图片的得分
            score = []
            ForderPath = 'Template/' + List[i]
            # 遍历单文件夹(每一个文件匹配)
            for filename in os.listdir(ForderPath):
                # 路径
                path = 'Template/' + List[i] + '/' + filename
                # 模板
                template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1)    #彩(类似imread)
                gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY)                 #灰
                ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU)      #二值
                h, w = template.shape
                image = cv.resize(image, (w, h))

                # 模板匹配,得到得分(匹配度越高,得分越大)
                result = cv.matchTemplate(image, template, cv.TM_CCOEFF)
                score.append(result[0][0])          #得分(每张模板图)

            # 一个文件夹的最高得分(得分越高,匹配度越高)
            best_score.append(max(score))
            # 根据所有文件夹的最佳得分确定下标
            index = best_score.index(max(best_score)) + 10


    # (3) 数字+字母
    else:
        # 遍历0~34文件夹(数字+字母)
        for i in range(34):
            # 单个图片的得分
            score = []
            ForderPath = 'Template/' + List[i]
            # 遍历单文件夹(每一个文件匹配)
            for filename in os.listdir(ForderPath):
                # 路径
                path = 'Template/' + List[i] + '/' + filename
                # 模板
                template = cv.imdecode(np.fromfile(path, dtype=np.uint8), 1)    #彩(类似imread)
                gray = cv.cvtColor(template, cv.COLOR_RGB2GRAY)                 #灰
                ret, template = cv.threshold(gray, 0, 255, cv.THRESH_OTSU)      #二值
                h, w = template.shape
                image = cv.resize(image, (w, h))

                # 模板匹配,得到得分(匹配度越高,得分越大)
                result = cv.matchTemplate(image, template, cv.TM_CCOEFF)
                score.append(result[0][0])          #得分(每张模板图)

            # 一个文件夹的最高得分(得分越高,匹配度越高)
            best_score.append(max(score))
            # 根据所有文件夹的最佳得分确定下标
            index = best_score.index(max(best_score))

    # 显示结果(文字)(每识别一个显示一次)
    Show_Result_Words(index)

        总的来讲,为了追求较高的精度,匹配时间较长, 一张车牌约20秒。这里的模板匹配不算非常的精确,并且耗时严重,已经逐渐被淘汰了,这里只是作为学习用途,没有太高的实际应用价值。(后期进军深度学习/机器学习,可能会对这些进行优化)。有什么好的建议大家可以提出来,共同进步,谢谢~

参考资料

https://www.bilibili.com/video/BV1yg4y187kU?p=3

以上是关于OpenCV(项目)车牌识别3 -- 模板匹配的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV C++案例实战十《车牌号识别》

车牌识别基于matlab GUI模板匹配车牌识别含Matlab源码 958期

车牌识别模板匹配新能源轿车货车车牌识别含GUI Matlab源码 2169期

OpenCV(项目)车牌识别4 -- 总结篇

车牌识别基于matlab GUI模板匹配新能源轿车货车车牌识别含Matlab源码 2169期

车牌识别基于matlab投影模板匹配车牌识别含Matlab源码 1359期