机器视觉 车牌字符切割
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.运行结果
-
原图显示
-
灰度变化
-
阈值分割(二值化)
-
图像反色
-
水平投影
-
垂直投影
-
矩形标示
4.问题及解决方法
问题:参考博客https://blog.csdn.net/dongjinkun/article/details/105429239方法对车牌铆钉去除失败
解决:修改阈值后成功,并对除字符以外区域进行描黑,得到一张干净的车牌图像
5.实验总结
- 跳变次数法去除车牌边框和铆钉。
- 了解车牌切割流程。
以上是关于机器视觉 车牌字符切割的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV+Python实现将车牌数字分割为单个的字符图片