前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于OpenCV和Python的车牌提取和字符分割

基于OpenCV和Python的车牌提取和字符分割

作者头像
荣仔_最靓的仔
发布2021-02-02 16:44:39
3.8K0
发布2021-02-02 16:44:39
举报

这是一篇介绍基于 OpenCV 和 Python 实现车牌提取项目思路和源码的文章,本文涉及一些人工智能和图像识别技术,具体而言,涉及到关于车牌号码识别的研究(车牌提取和字符分割),网上查找到的方案有 tensorflow 和opencv,opencv 也是比较成熟的方案,先从简单的开始,以下是关于使用opencv实现车牌号码提取的部分。

1 车牌提取

1.1 实现思路

  1. 读取彩色的图片
  2. 转换为灰度图
  3. 高斯模糊
  4. Sobel算子进行边缘检测
  5. 图像二值化
  6. 闭操作(腐蚀和扩张)
  7. 循环找到所有的轮廓
  8. 判断车牌区域

1.2 原图

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

1.3 代码详解

1.3.1 导入包库

代码语言:javascript
复制
import cv2 as cv
import matplotlib.pyplot as plt

1.3.2 读取彩色的图片

代码语言:javascript
复制
cv.imread("E:/car.png")
在这里插入图片描述
在这里插入图片描述

1.3.3 转换为灰度图

代码语言:javascript
复制
cv.cvtColor(img, cv.COLOR_BGR2GRAY)
在这里插入图片描述
在这里插入图片描述

1.3.4 高斯模糊

通过高斯模糊,可以去除部分的干扰,让识别更加准确。

代码语言:javascript
复制
cv.GaussianBlur(img1,(5,5),10)
在这里插入图片描述
在这里插入图片描述

1.3.5 用Sobel算子进行边缘检测

便于接下来提取轮廓

代码语言:javascript
复制
cv.Sobel(img2,cv.CV_8U,1,0,ksize=1)
cv.Canny(img3,250,100)
在这里插入图片描述
在这里插入图片描述

1.3.6 进行二值化处理

将图像上的像素点的灰度值设置为0或255,图像呈现出明显的只有黑和白。

代码语言:javascript
复制
cv.threshold(img4,0,255,cv.THRESH_BINARY)
在这里插入图片描述
在这里插入图片描述

1.3.7 闭操作

依次进行腐蚀和扩张,这一步操作可以将目标区域连成一个整体,便于后续轮廓的提取。

代码语言:javascript
复制
cv.getStructuringElement(cv.MORPH_RECT,(43,33))
cv.dilate(img5,kernel)
在这里插入图片描述
在这里插入图片描述

1.3.8 查找轮廓

代码语言:javascript
复制
i,j = cv.findContours(img6,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)

1.3.9 判断车牌区域

代码语言:javascript
复制
result = None
for i1 in i:
    x,y,w,h = cv.boundingRect(i1)
    if w>2*h:
        print(1)
        plt.imshow(img[y:y+h,x:x+w])
        plt.show()
        result = img[y:y+h,x:x+w]
在这里插入图片描述
在这里插入图片描述

1.4 总观代码

代码语言:javascript
复制
import cv2 as cv
import matplotlib.pyplot as plt

# 读取彩色的图片
img = cv.imread("E:/car.png")
plt.imshow(img)
plt.show()
# 转换为灰度图
img1 = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
plt.imshow(img1)
plt.show()
# 用Sobel进行边缘检测
# # 高斯模糊
img2 = cv.GaussianBlur(img1,(5,5),10)
plt.imshow(img2)
plt.show()
# Laplacian进行边缘检测
img3 = cv.Sobel(img2,cv.CV_8U,1,0,ksize=1)
plt.imshow(img3)
plt.show()
img4 = cv.Canny(img3,250,100)
plt.imshow(img4)
plt.show()
# 进行二值化处理
i,img5 = cv.threshold(img4,0,255,cv.THRESH_BINARY)
plt.imshow(img5)
plt.show()
# 可以侵蚀和扩张
kernel = cv.getStructuringElement(cv.MORPH_RECT,(43,33))
img6 = cv.dilate(img5,kernel)
plt.imshow(img6)
plt.show()
# # 循环找到所有的轮廓
i,j = cv.findContours(img6,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
result = None
for i1 in i:
    x,y,w,h = cv.boundingRect(i1)
    if w>2*h:
        print(1)
        plt.imshow(img[y:y+h,x:x+w])
        plt.show()
        result = img[y:y+h,x:x+w]

1.5 最终实现效果

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

2 车牌识别之字符分割

前面对这牌提取做个详细描述,与此相类似,车牌的字符分割也是很重要的一部分,字符分割的思想在其他项目中同样有很重要的作用。因此有必要针对字符分割的思路和实现过程做一个记录。

2.1 实现思路

总的来说,是基于像素直方图的字符分割实现的:首先对图片进行二值化处理,统计水平方向和竖直方向上各行各列的黑色像素的个数,根据像素的特点确定分割位置,进而完成字符分割。

2.2 原图

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

2.3 代码详解

2.3.1 导入包库

代码语言:javascript
复制
import cv2
from matplotlib import pyplot as plt

2.3.2 读取图像,并把图像转换为灰度图像并显示

代码语言:javascript
复制
cv2.imread('E:/3.png')  # 读取图片
cv2.cvtColor(img_, cv2.COLOR_BGR2GRAY)  # 转换了灰度化
在这里插入图片描述
在这里插入图片描述

2.3.3 将灰度图像二值化,设定阈值是100

代码语言:javascript
复制
cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY_INV)
在这里插入图片描述
在这里插入图片描述

2.3.4 分割字符

水平方向:统计每一行黑色像素数量n,并记录。可以根据每一行黑色像素的数目来确定分割的起始和终止;由图可知,当 n减小到一定阈值时,为字符的边缘; 竖直方向:同理,统计每一列的黑色像素数量v,并记录。可以可以根据每一列黑色像素的数目的变化来确定分割的起始和终止。

代码语言:javascript
复制
white = []  # 记录每一列的白色像素总和
black = []  # ..........黑色.......
height = img_thre.shape[0]
width = img_thre.shape[1]
white_max = 0
black_max = 0
# 计算每一列的黑白色像素总和
for i in range(width):
    s = 0  # 这一列白色总数
    t = 0  # 这一列黑色总数
    for j in range(height):
        if img_thre[j][i] == 255:
            s += 1
        if img_thre[j][i] == 0:
            t += 1
    white_max = max(white_max, s)
    black_max = max(black_max, t)
    white.append(s)
    black.append(t)

2.3.5 分割图像

代码语言:javascript
复制
def find_end(start_):
    end_ = start_ + 1
    for m in range(start_ + 1, width - 1):
        if (black[m] if arg else white[m]) > (0.95 * black_max if arg else 0.95 * white_max):  # 0.95这个参数请多调整,对应下面的0.05(针对像素分布调节)
            end_ = m
            break
    return end_

2.4 总观代码

代码语言:javascript
复制
import cv2
from matplotlib import pyplot as plt
## 根据每行和每列的黑色和白色像素数进行图片分割。

# 1、读取图像,并把图像转换为灰度图像并显示
img_ = cv2.imread('E:/3.png')  # 读取图片
img_gray = cv2.cvtColor(img_, cv2.COLOR_BGR2GRAY)  # 转换了灰度化
# cv2.imshow('gray', img_gray)  # 显示图片
# cv2.waitKey(0)

# 2、将灰度图像二值化,设定阈值是100
ret, img_thre = cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY_INV)
# cv2.imshow('white_black image', img_thre)  # 显示图片
# cv2.waitKey(0)

# 4、分割字符
white = []  # 记录每一列的白色像素总和
black = []  # ..........黑色.......
height = img_thre.shape[0]
width = img_thre.shape[1]
white_max = 0
black_max = 0
# 计算每一列的黑白色像素总和
for i in range(width):
    s = 0  # 这一列白色总数
    t = 0  # 这一列黑色总数
    for j in range(height):
        if img_thre[j][i] == 255:
            s += 1
        if img_thre[j][i] == 0:
            t += 1
    white_max = max(white_max, s)
    black_max = max(black_max, t)
    white.append(s)
    black.append(t)
    # print(s)
    # print(t)

arg = False  # False表示白底黑字;True表示黑底白字
if black_max > white_max:
    arg = True

# 分割图像
def find_end(start_):
    end_ = start_ + 1
    for m in range(start_ + 1, width - 1):
        if (black[m] if arg else white[m]) > (0.95 * black_max if arg else 0.95 * white_max):  # 0.95这个参数请多调整,对应下面的0.05(针对像素分布调节)
            end_ = m
            break
    return end_

n = 1
start = 1
end = 2
word = []
while n < width - 2:
    n += 1
    if (white[n] if arg else black[n]) > (0.05 * white_max if arg else 0.05 * black_max):
        # 上面这些判断用来辨别是白底黑字还是黑底白字
        # 0.05这个参数请多调整,对应上面的0.95
        start = n
        end = find_end(start)
        n = end
        if end - start > 5:
            cj = img_[1:height, start:end]
            cj = cv2.resize(cj, (15, 30))
            word.append(cj)

print(len(word))
for i,j in enumerate(word):
    plt.subplot(1,8,i+1)
    plt.imshow(word[i],cmap='gray')
plt.show()

2.5 最终实现效果

在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 车牌提取
    • 1.1 实现思路
      • 1.2 原图
        • 1.3 代码详解
          • 1.3.1 导入包库
          • 1.3.2 读取彩色的图片
          • 1.3.3 转换为灰度图
          • 1.3.4 高斯模糊
          • 1.3.5 用Sobel算子进行边缘检测
          • 1.3.6 进行二值化处理
          • 1.3.7 闭操作
          • 1.3.8 查找轮廓
          • 1.3.9 判断车牌区域
        • 1.4 总观代码
          • 1.5 最终实现效果
          • 2 车牌识别之字符分割
            • 2.1 实现思路
              • 2.2 原图
                • 2.3 代码详解
                  • 2.3.1 导入包库
                  • 2.3.2 读取图像,并把图像转换为灰度图像并显示
                  • 2.3.3 将灰度图像二值化,设定阈值是100
                  • 2.3.4 分割字符
                  • 2.3.5 分割图像
                • 2.4 总观代码
                  • 2.5 最终实现效果
                  相关产品与服务
                  汽车相关识别
                  汽车相关识别(Vehicle Optical Character Recognition,Vehicle OCR)基于行业前沿的深度学习技术,提供驾驶证识别、行驶证识别、车牌识别、车辆 VIN 码识别等多种服务,支持将图片上的文字内容,智能识别为结构化的文本,应用于车主身份认证、ETC 出行、违章识别、停车管理等多种场景,大幅提升信息处理效率。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档