Python实现车牌定位及分割

具体步骤

1、将采集到的彩色车牌图像转换成灰度图
2、灰度化的图像利用高斯平滑处理后,再对其进行中直滤波
3、使用Sobel算子对图像进行边缘检测
4、对二值化的图像进行腐蚀,膨胀,开运算,闭运算的形态学组合变换
5、对形态学变换后的图像进行轮廓查找,根据车牌的长宽比提取车牌

代码实现

图像灰度化

1
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

高斯平滑,中值滤波处理

1
2
gaussian = cv2.GaussianBlur(gray, (3, 3), 0, 0, cv2.BORDER_DEFAULT)
median = cv2.medianBlur(gaussian, 5)


Sobel边缘检测

1
sobel = cv2.Sobel(median, cv2.CV_8U, 1, 0,  ksize = 3)

二值化

1
ret, binary = cv2.threshold(sobel, 170, 255, cv2.THRESH_BINARY)

对二值化的图像进行腐蚀,膨胀,开运算,闭运算的形态学组合变换

1
2
3
4
5
6
7
8
9
# 膨胀和腐蚀操作的核函数
element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 6))
# 膨胀一次,让轮廓突出
dilation = cv2.dilate(binary, element2, iterations = 1)
# 腐蚀一次,去掉细节
erosion = cv2.erode(dilation, element1, iterations = 1)
# 再次膨胀,让轮廓明显一些
dilation2 = cv2.dilate(erosion, element2,iterations = 3)

对形态学变换后的图像进行轮廓查找,根据车牌的长宽比提取车牌

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
def findPlateNumberRegion(img):
region = []
# 查找轮廓
contours,hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 筛选面积小的
for i in range(len(contours)):
cnt = contours[i]
# 计算该轮廓的面积
area = cv2.contourArea(cnt)

# 面积小的都筛选掉
if (area < 2000):
continue

# 轮廓近似,作用很小
epsilon = 0.001 * cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt, epsilon, True)

# 找到最小的矩形,该矩形可能有方向
rect = cv2.minAreaRect(cnt)
print "rect is: "
print rect

# box是四个点的坐标
box = cv2.cv.BoxPoints(rect)
box = np.int0(box)

# 计算高和宽
height = abs(box[0][1] - box[2][1])
width = abs(box[0][0] - box[2][0])

# 车牌正常情况下长高比在2.7-5之间
ratio =float(width) / float(height)
if (ratio > 5 or ratio < 2):
continue

region.append(box)

return region

2、用绿线绘出车牌区域和切割车牌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 用绿线画出这些找到的轮廓
for box in region:
cv2.drawContours(img, [box], 0, (0, 255, 0), 2)
ys = [box[0, 1], box[1, 1], box[2, 1], box[3, 1]]
xs = [box[0, 0], box[1, 0], box[2, 0], box[3, 0]]
ys_sorted_index = np.argsort(ys)
xs_sorted_index = np.argsort(xs)

x1 = box[xs_sorted_index[0], 0]
x2 = box[xs_sorted_index[3], 0]

y1 = box[ys_sorted_index[0], 1]
y2 = box[ys_sorted_index[3], 1]

img_org2 = img.copy()
img_plate = img_org2[y1:y2, x1:x2]



代码地址在:https://github.com/hyzhangyong/platenumber

总结

这并不完善,并不能识别所有环境下的车牌,需要进一步改善识别模式。

文章目录
  1. 1. 具体步骤
  2. 2. 代码实现
    1. 2.1. 图像灰度化
    2. 2.2. 高斯平滑,中值滤波处理
    3. 2.3. Sobel边缘检测
    4. 2.4. 二值化
    5. 2.5. 对二值化的图像进行腐蚀,膨胀,开运算,闭运算的形态学组合变换
    6. 2.6. 对形态学变换后的图像进行轮廓查找,根据车牌的长宽比提取车牌
  3. 3. 总结
,