机器视觉 车牌字符切割

Posted 朱不住

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了机器视觉 车牌字符切割相关的知识,希望对你有一定的参考价值。

1.实验目的

利用opencv python实现对下图车牌进行字符切割。实验包括:灰度变化、图像反色、转成二值图、水平投影、垂直投影、字符切割和矩形标示等。

2.实验过程

(1)编写代码

代码如下:

import cv2
import numpy as np

dst=cv2.imread("carplate.png")
plate_original = dst.copy()
cv2.imshow("yuantu", dst)

#高斯滤波
img_aussian = cv2.GaussianBlur(dst,(5,5),1)
#中值滤波
dst = cv2.medianBlur(img_aussian,3)


# 灰度化
gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray',gray)

#二值化处理,低于阈值的像素点灰度值置为0;高于阈值的值置为参数3
ret,thresh1 = cv2.threshold(gray,180,255,cv2.THRESH_BINARY)
cv2.imshow('threshold',thresh1)

gray=thresh1.copy()
LICENSE_HIGH,LICENSE_WIDTH=gray.shape

#-------------------------------跳变次数去掉铆钉和边框----------------------------------
times_row = []  #存储哪些行符合跳变次数的阈值
for row in range(LICENSE_HIGH): # 按行检测 白字黑底
    pc = 0
    for col in range(LICENSE_WIDTH):
        if col != LICENSE_WIDTH-1:
            if gray[row][col+1] != gray[row][col]:
                pc = pc + 1
    times_row.append(pc)


#找车牌的下边缘-从下往上扫描
row_end = 0
row_start = 0
for row in range(LICENSE_HIGH-2):
    if times_row[row] <10:
        continue
    elif times_row[row+1] <10:
        continue
    elif times_row[row+2] <10:
        continue
    else:
        row_end = row + 2
print("row_end",row_end)

#找车牌的上边缘-从上往下扫描
i = LICENSE_HIGH-1
row_num = [] #记录row_start可能的位置
while i > 1:
    if times_row[i] < 10:
        i = i - 1
        continue
    elif times_row[i-1] < 10:
        i = i - 1
        continue
    elif times_row[i-2] < 10:
        i = i - 1
        continue
    else:
        row_start = i - 2
        row_num.append(row_start)
        i = i - 1
#确定row_start最终位置
for i in range(len(row_num)):
    if i != len(row_num)-1:
        if abs(row_num[i] - row_num[i+1])>1:
            row_start = row_num[i]
print("row_start",row_start)

times_col = [0]
for col in range(LICENSE_WIDTH):
    pc = 0
    for row in range(LICENSE_HIGH):
        if row != LICENSE_HIGH-1:
            if gray[row,col] != gray[row+1,col]:
                pc = pc + 1
    times_col.append(pc)

# 找车牌的左右边缘-从左到右扫描
col_start = 0
col_end = 0
for col in range(len(times_col)):
    if times_col[col] > 1:
        col_end = col
print('col_end',col_end)

#j = LICENSE_WIDTH-1
#while j >= 0:
#    if times_col[j] > 0:
#        col_start = j
#   j = j-1
col_start=0
print('col_start',col_start)


# 将车牌非字符区域变成纯黑色
for i in range(LICENSE_HIGH):
    if i > row_end or i < row_start:
        gray[i] = 0
for j in range(LICENSE_WIDTH):
    if j < col_start or j > col_end:
        gray[:,j] = 255
#cv2.imshow("res",gray)

#图像反色
h,w = gray.shape#返回图像的(h)高和(w)宽
image4=gray.copy()
for i in range(h):
    for j in range(w):
        image4[i,j] = 255-image4[i,j]
cv2.imshow('pointinvert', image4)


#水平投影
h1,w1=image4.shape #返回高和宽
image5=image4.copy()
a = [0 for z in range(0, h1)] #初始化一个长度为w的数组,用于记录每一行的黑点个数                                                                                                 
#记录每一行的波峰
for j in range(0,h1):  
    for i in range(0,w1):  
        if  image5[j,i]==0: 
            a[j]+=1 
            image5[j,i]=255
            
for j in range(0,h1):  
    for i in range(0,a[j]):   
        image5[j,i]=0    
        
cv2.imshow('hproject',image5)  

#垂直投影
h2,w2=image4.shape #返回高和宽
image6=image4.copy()
b = [0 for z in range(0, w2)]  #b = [0,0,0,0,0,0,0,0,0,0,...,0,0]初始化一个长度为w的数组,用于记录每一列的黑点个数
#记录每一列的波峰
for j in range(0,w2): #遍历一列 
    for i in range(0,h2):  #遍历一行
        if  image6[i,j]==0:  #如果该点为黑点
            b[j]+=1  #该列的计数器加一,最后统计出每一列的黑点个数  
            image6[i,j]=255  #记录完后将其变为白色,相当于擦去原图黑色部分
            
for j in range(0,w2):  
    for i in range((h2-b[j]),h2):  #从该列应该变黑的最顶部的点开始向最底部涂黑
        image6[i,j]=0   #涂黑
        
cv2.imshow('vproject',image6)



#分割字符
Position = []
start = 0
a_Start = []
a_End = []

#根据水平投影获取垂直分割位置
for i in range(len(a)):
    if a[i] > 0 and start ==0:
        a_Start.append(i)
        start = 1
    if a[i] <= 0 and start == 1:
        a_End.append(i)
        start = 0

#分割行,分割之后再进行列分割并保存分割位置
for i in range(len(a_Start)):
    #获取行图像
    cropImg = image4[a_Start[i]:a_End[i],0:w1]
    #对行图像进行垂直投影
    bstart = 0
    bend = 0
    b_Start = 0
    b_End = 0
    for j in range(len(b)):
        if b[j] > 0 and bstart ==0:
            b_Start =j
            bstart = 1
            bend=0
        if b[j] <= 0 and bstart == 1:
            b_End =j
            bstart = 0
            bend=1
        if bend == 1:
            Position.append([b_Start,a_Start[i],b_End,a_End[i]])
            bend =0

image4 = cv2.cvtColor(image4, cv2.COLOR_BGR2RGB)#将灰度图转为RGB彩图


#根据确定的位置分割字符
for m in range(len(Position)):
    if m == 2:
        continue  #去除圆点画框
    cv2.rectangle(image4, (Position[m][0],Position[m][1]), (Position[m][2],Position[m][3]), (0, 0, 255), 2)
        #第一个参数是原图;第二个参数是矩阵的左上点坐标;第三个参数是矩阵的右下点坐标;第四个参数是画线对应的rgb颜色;第五个参数是所画的线的宽度
        
cv2.imshow('rect',image4)

cv2.waitKey(0)
cv2.destroyAllWindows()

3.运行结果

  1. 原图显示

  2. 灰度变化

  3. 阈值分割(二值化)

  4. 图像反色

  5. 水平投影

  6. 垂直投影

  7. 矩形标示

4.问题及解决方法

问题:参考博客https://blog.csdn.net/dongjinkun/article/details/105429239方法对车牌铆钉去除失败

解决:修改阈值后成功,并对除字符以外区域进行描黑,得到一张干净的车牌图像

5.实验总结

  1. 跳变次数法去除车牌边框和铆钉。
  2. 了解车牌切割流程。

以上是关于机器视觉 车牌字符切割的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV+Python实现将车牌数字分割为单个的字符图片

毕业设计python 机器视觉 车牌识别 - opencv 深度学习 机器学习

车牌识别原理

LabVIEW OCR 实现车牌识别

Python项目演练:使用深度学习自动识别车牌号附源代码

基于pytorch的无需分割字符的车牌识别