OCR传统技术-车牌识别_CodingPark编程公园

本文详细介绍了OCR技术在车牌识别中的应用,涵盖了车牌提取的关键步骤,包括高斯去噪、灰度处理、Sobel算子边缘检测、自适应阈值处理、形态学变换以及轮廓检测。通过这些技术,可以有效地识别和分割车牌字符,为进一步的内容识别奠定基础。
摘要由CSDN通过智能技术生成

OCR传统传统技术-车牌识别

项目流程:车牌提取 -> 字符分割 -> 内容识别

车牌提取

必要函数

# -*- encoding: utf-8 -*-
"""
@File    :   CarLicenseExtraction.py    
@Contact :   ag@team-ag.club
@License :   (C)Copyright 2019-2020, CodingPark

@Modify Time      @Author    @Version    @Desciption
------------      -------    --------    -----------
2020-11-08 19:27   AG         1.0         None
"""
import cv2
from matplotlib import pyplot as plt
import os
import numpy as np

'''

必要函数

'''

# cv图片显示
def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey()
    cv2.destroyAllWindows()


# plt图片显示
def plt_show_rgb(img):
    b, g, r = cv2.split(img)
    img = cv2.merge([r, g, b])
    plt.imshow(img)
    plt.show()


# plt灰度图显示
def plt_show_gray(img):
    plt.imshow(img, cmap='gray')
    plt.show()


# 图片去噪灰度处理
def gray_guss(img):
    image = cv2.GaussianBlur(img, (3, 3), 0)
    gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    return gray_image

读取图片


'''

读取待检测图片

'''
org_img = cv2.imread('test_image/test2.png')
plt_show_rgb(org_img)
print('===已读取到图片===')

在这里插入图片描述

在这里插入图片描述

提取车牌

def get_carLicense_img(img):
    gray_image = gray_guss(img)
    # sobel算子边缘检测(做了一个x方向的检测)
    Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0)
    # 通过线性变换将数据转换成8位[uint8]
    absX = cv2.convertScaleAbs(Sobel_x)
    img = absX
    # 自适应阈值处理
    ret, img = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)      # 非常重要!
    print('ret->', ret)
    plt_show_gray(img)
    # 闭运算,是白色部分练成整体
    kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (17, 5))
    image = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernelX, iterations=3)
    plt_show_gray(image)
    # 去除一些小的白点
    kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (20, 1))
    kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 19))
    # 膨胀,腐蚀
    image = cv2.dilate(image, kernelX)
    image = cv2.erode(image, kernelX)
    # 腐蚀,膨胀
    image = cv2.erode(image, kernelY)
    image = cv2.dilate(image, kernelY)
    # 中值滤波去除噪点
    image = cv2.medianBlur(image, 15)
    plt_show_gray(image)
    # 轮廓检测
    # contours 轮廓
    # cv2.RETR_EXTERNAL表示只检测外轮廓
    # cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
    contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # print('contours->', contours)
    # print('hierarchy->', hierarchy)
    # 这中间的就是给自己看的⬇️
    imageCopy = org_img.copy()
    cv2.drawContours(imageCopy, contours, -1, (0, 255, 0), 5)
    plt_show_rgb(imageCopy)
    # 这中间的就是给自己看的⬆️

    # 筛选出车牌位置的轮廓
    # 这里做了一个车牌的长宽比在3:1到4:1之间这样一个判断
    for item in contours:
        # print('item->', item)
        # cv2.boundingRect用一个最小的矩形,把找到的形状包起来
        rect = cv2.boundingRect(item)
        x = rect[0]
        y = rect[1]
        w = rect[2]
        h = rect[3]

        # 440mm×140mm
        if (w > (h*3)) and (w < (h*4)):
            image_CarLic = org_img[y:y+h, x:x+w]
            plt_show_rgb(image_CarLic)
            # 图像保存
            cv2.imwrite('test_result/test2.png', image_CarLic)
            return image_CarLic


高斯去噪
在这里插入图片描述

灰度处理
在这里插入图片描述

sobel算子边缘检测
在这里插入图片描述

自适应阈值处理
在这里插入图片描述

闭运算,是白色部分练成整体
print(kernelX)
[[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]]
在这里插入图片描述

去除一些小的白点 | 膨胀,腐蚀 | 腐蚀,膨胀
在这里插入图片描述

中值滤波去除噪点
在这里插入图片描述

绘制轮廓
在这里插入图片描述

筛选出车牌
在这里插入图片描述

cv2.Sobel()

函数cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])
概述:利用Sobel算子进行图像梯度计算

参数:
src:输入图像
ddepth: 输出图像的深度(可以理解为数据类型),-1表示与原图像相同的深度
dx,dy:当组合为dx=1,dy=0时求x方向的一阶导数,当组合为dx=0,dy=1时求y方向的一阶导数(如果同时为1,通常得不到想要的结果)
ksize:(可选参数)Sobel算子的大小,必须是1,3,5或者7,默认为3。求X方向和Y方向一阶导数时,卷积核分别为:
在这里插入图片描述

scale:(可选参数)将梯度计算得到的数值放大的比例系数,效果通常使梯度图更亮,默认为1
delta:(可选参数)在将目标图像存储进多维数组前,可以将每个像素值增加delta,默认为0
borderType:(可选参数)决定图像在进行滤波操作(卷积)时边沿像素的处理方式,默认为BORDER_DEFAULT
返回值:
梯度图

cv2.convertScaleAbs()

过线性变换将数据转换成8位[uint8]

cv2.threshold()

Python: cv2.threshold(src, thresh, maxval, type[, dst]) → retval, dst

在其中:
src:表示的是图片源
thresh:表示的是阈值(起始值)
maxval:表示的是最大值
type:表示的是这里划分的时候使用的是什么类型的算法**,常用值为0(cv2.THRESH_BINARY)**

getStructuringElement()

getStructuringElement(int shape, Size esize, Point anchor = Point(-1, -1));

这个函数的第一个参数表示内核的形状,有三种形状可以选择。

矩形:MORPH_RECT;

交叉形:MORPH_CROSS;

椭圆形:MORPH_ELLIPSE;

第二和第三个参数分别是内核的尺寸以及锚点的位置。一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得getStructuringElement函数的返回值。对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心点。element形状唯一依赖锚点位置,其他情况下,锚点只是影响了形态学运算结果的偏移。

morphologyEx()

opencv 形态学变换 morphologyEx函数
高级形态学变换:
开运算:
先腐蚀,再膨胀,可清除一些小东西(亮的),放大局部低亮度的区域
闭运算:
先膨胀,再腐蚀,可清除小黑点
形态学梯度:
膨胀图与腐蚀图之差,提取物体边缘
顶帽:
原图像-开运算图,突出原图像中比周围亮的区域
黑帽:
闭运算图-原图像,突出原图像中比周围暗的区域

1.cv2.morphologyEx(src, op, kernel) 进行各类形态学的变化

参数说明:src传入的图片,op进行变化的方式, kernel表示方框的大小

2.op = cv2.MORPH_OPEN 进行开运算,指的是先进行腐蚀操作,再进行膨胀操作

  1. op = cv2.MORPH_CLOSE 进行闭运算, 指的是先进行膨胀操作,再进行腐蚀操作

开运算:表示的是先进行腐蚀,再进行膨胀操作

闭运算:表示先进行膨胀操作,再进行腐蚀操作

findContours() & drawContours()

cv2.findContours()有三个参数。

第一个是输入图像,第二个是轮廓检索模式,第三个是轮廓近似方法。而返回值根据OpenCV版本不同也不一样,但这俩个版本都会返回一个元组。OpenCV2.x版本第一个元素是轮廓,,而在OpenCV3.x中第二个才是轮廓。这个轮廓是一个列表,每个列表元素代表着一个轮廓。

cv2.findContours()第二个参数有什么用?
对于轮廓来说可能还包含父子关系,也就是说一个轮廓里面可能还包含着其他轮廓(比如说房子的轮廓可以包含一个矩形的窗户,则房子为父,窗户为子,而窗户里可能有个人的头,这又是一种父子关系),这其中的层次结构可以通过对第二个参数设置来选择是否获取。
在这里插入图片描述

在这幅图中,给这几个形状编号为 0-5。 2 和 2a 分别代表最外边矩形的外轮廓和内轮廓。在这里边轮廓 0, 1, 2 在外部或最外边。我们可以称他们为(组织结构)0 级,简单来说就是他们属于同一级。接下来轮廓 2a。 我们把它当成轮廓 2 的子轮廓。它就成为(组织结构)第1 级。同样轮廓 3 是轮廓 2 的子轮廓,成为(组织结构)第 3 级。最后轮廓4,5 是轮廓 3a 的子轮廓,成为(组织结构) 4 级(最后一级)。按照这种方式给这些形状编号。而在OpenCV有哪些参数可选呢?

  • RETR_LIST 从解释的角度来看,这中应是最简单的。它只是提取所有的轮廓,而不去创建任何父子关系。
  • RETR_EXTERNAL 如果你选择这种模式的话,只会返回最外边的的轮廓,所有的子轮廓都会被忽略掉。
  • RETR_CCOMP 在这种模式下会返回所有的轮廓并将轮廓分为两级组织结构。
  • RETR_TREE 这种模式下会返回所有轮廓,并且创建一个完整的组织结构列表。它甚至会告诉你谁是爷爷,爸爸,儿子,孙子等。

findContours()第三个参数什么意思呢?
如果设为cv2.CHAIN_APPROX_NONE,,表示边界所有点都会被储存;而如果设为cv2.CHAIN_APPROX_SIMPLE 会压缩轮廓,将轮廓上冗余点去掉,比如说四边形就会只储存四个角点。

cv2.drawContours()被用来绘制轮廓
第一个参数是一张图片,可以是原图或者其他。第二个参数是轮廓,也可以说是cv2.findContours()找出来的点集,一个列表。第三个参数是对轮廓(第二个参数)的索引,当需要绘制独立轮廓时很有用,若要全部绘制可设为-1。接下来的参数是轮廓的颜色和厚度。

cv2.rectangle()和cv2.boundingRect()

cv2.boundingRect(img)
img是一个二值图,也就是它的参数;返回四个值,分别是x,y,w,h;x,y是矩阵左上点的坐标,w,h是矩阵的宽和高。

然后利用

cv2.rectangle(img, (x,y), (x+w,y+h), (0,255,0), 2)画出矩行

参数解释
第一个参数:img是原图
第二个参数:(x,y)是矩阵的左上点坐标
第三个参数:(x+w,y+h)是矩阵的右下点坐标
第四个参数:(0,255,0)是画线对应的rgb颜色
第五个参数:2是所画的线的宽度

字符分割V1

*CarLicenseExtraction_BASE.py *


'''

字符分割

'''

def carLicense_spilte(image):
    gray_image = gray_guss(image)
    # 自适应阈值处理
    ret, img = cv2.threshold(gray_image, 0, 255, cv2.THRESH_OTSU)
    # plt_show_gray(img)
    # 计算二值图像黑白点的个数,处理绿牌照问题,让车牌号码始终为白色
    area_white = 0
    area_black = 0
    height, width = img.shape
    for i in range(height):
        for j in range(width):
            if img[i, j] == 255:
                area_white += 1
            
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TEAM-AG

编程公园:输出是最好的学习方式

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值