在jupyter notebook上使用python+opencv实现如下简单车牌字符切割。关于opencv库的安装可以参考:python下opencv库的安装过程与一些问题汇总。
1.实现代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
import cv2
import numpy as np
import matplotlib.pyplot as plt
from pil import image
#读取原图片
image1 = cv2.imread( "123456.jpg" )
cv2.imshow( "image1" , image1)
#灰度化处理
image1_1 = cv2.cvtcolor(image1,cv2.color_bgr2gray)
cv2.imshow( "image1_1" , image1_1)
#图像反色
h,w = image1_1.shape
image1_2 = image1_1.copy()
for i in range (h):
for j in range (w):
image1_2[i,j] = 255 - image1_2[i,j]
cv2.imshow( 'image1_2' , image1_2)
#图像二值化
ret,image2 = cv2.threshold(image1_2, 100 , 255 , cv2.thresh_binary)
cv2.imshow( 'image2' , image2)
#水平投影
h1,w1 = image2.shape #返回高和宽
image3 = image2.copy()
a = [ 0 for z in range ( 0 , h1)] #初始化一个长度为w的数组,用于记录每一行的黑点个数
#记录每一行的波峰
for j in range ( 0 ,h1):
for i in range ( 0 ,w1):
if image3[j,i] = = 0 :
a[j] + = 1
image3[j,i] = 255
for j in range ( 0 ,h1):
for i in range ( 0 ,a[j]):
image3[j,i] = 0
plt.imshow(image3,cmap = plt.gray()) #灰度图正确的表示方法
plt.show()
cv2.imshow( 'image3' ,image3)
#垂直投影
h2,w2 = image2.shape #返回高和宽
image4 = image2.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 image4[i,j] = = 0 : #如果该点为黑点
b[j] + = 1 #该列的计数器加一,最后统计出每一列的黑点个数
image4[i,j] = 255 #记录完后将其变为白色,相当于擦去原图黑色部分
for j in range ( 0 ,w2):
for i in range ((h2 - b[j]),h2): #从该列应该变黑的最顶部的点开始向最底部涂黑
image4[i,j] = 0 #涂黑
plt.imshow(image4,cmap = plt.gray())
plt.show()
cv2.imshow( 'image4' ,image4)
#分割字符
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 = image2[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
image2 = cv2.cvtcolor(image2, cv2.color_bgr2rgb) #将灰度图转为rgb彩图
#根据确定的位置分割字符
for m in range ( len (position)):
cv2.rectangle(image2, (position[m][ 0 ],position[m][ 1 ]), (position[m][ 2 ],position[m][ 3 ]), ( 0 , 0 , 255 ), 2 ) #第一个参数是原图;第二个参数是矩阵的左上点坐标;第三个参数是矩阵的右下点坐标;第四个参数是画线对应的rgb颜色;第五个参数是所画的线的宽度
cv2.imshow( 'rect' ,image2)
cv2.waitkey( 0 )
|
2.运行结果
3. 遇到的问题及解决方法
对于二值化后的灰度图,在确定了各个字符坐标后,使用cv2.rectangle()方法画矩形框:cv2.rectangle(image2, (position[m][0],position[m][1]), (position[m][2],position[m][3]), (0, 255, 0), 2)。其中,第一个参数表示原图,第二个参数表示矩阵的左上点坐标,第三个参数表示矩阵的右下点坐标;第四个参数是画线对应的rgb颜色,第五个参数是画线宽度。在设置rgb颜色时发现矩形框颜色只能显示为黑色和白色,原因是在二值图上画图颜色没有三通道,无法显示彩色图像。
解决方法:将灰度图转换为rgb彩图。代码为image2 = cv2.cvtcolor(image2, cv2.color_bgr2rgb)。
到此这篇关于python中opencv实现简单车牌字符切割的文章就介绍到这了,更多相关opencv 车牌字符切割内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://www.cnblogs.com/BIXIABUMO/p/12824111.html