OpenCV基于颜色信息的车牌提取
车牌提取的方法主要有:基于纹理特征分析法、基于数学形态学分析法、基于边缘检测的定位分析法、基于小波分析的定位分析法、基于彩色信息的定位分析法,本文采用的方法是基于颜色信息的定位分析法。
本文主要参考了以下这一篇博客,该博客是用C++编写的算法,我参考其方法用Python实现了一遍。
参考的博客(C++编写的算法)
在代码中,我详细地注释了每一个步骤流程以及一些注意事项,看注释应该比较容易理解,代码可以直接使用。
注意把cv2.imread()函数中的图片路径修改一下,原始图片我放在了博客的最后。
#基于颜色信息的车牌提取
#识别普通民用小型车,车牌号是蓝底白字,正常光照下蓝色车牌的BGR大约是(138,63,23);车牌形状是矩形,长宽比是3:1
import cv2
import numpy as np
#读取车辆原始图像
car_original = cv2.imread('C:\\Users\\Administrator\\Desktop\\car.jpg')
rows,cols,td = car_original.shape #图像的行/高、列/宽、通道数
#print(rows,cols,td) #输出图像的大小,方便对图像的尺寸有一个了解
cv2.imshow('car_original',car_original) #显示原始图像
#基于颜色信息进行二值化
#正常光照下蓝色车牌的BGR大约是(138,63,23),由于存在一定的偏差,在二值化的时候设置一个范围,在范围之内
#的颜色(车牌的蓝色背景)设置成白色,否则设置成黑色。
blue_goal = 138
green_goal = 63
red_goal = 23
threshold = 50 #二值化的时候,通过设置一个阈值来设置一个范围
#注意:OpenCV中彩色图像的像素值是BGR格式,即(blue,green,red)
for i in range(0,rows):
for j in range(0,cols):
B = car_original[i,j,0]
G = car_original[i,j,1]
R = car_original[i,j,2]
if abs(B-blue_goal)<threshold and abs(G-green_goal)<threshold and abs(R-red_goal)<threshold:
car_original[i,j,0] = 255
car_original[i,j,1] = 255
car_original[i,j,2] = 255
else:
car_original[i,j,0] = 0
car_original[i,j,1] = 0
car_original[i,j,2] = 0
cv2.imshow('car_binarization',car_original) #显示基于颜色信息二值化之后的图像
#接下来进行形态学处理
#先膨胀再腐蚀
kernel = np.ones((3,3),np.int8)
dilation = cv2.dilate(car_original,kernel,iterations=1) #膨胀一次
dilation = cv2.dilate(dilation,kernel,iterations=1) #再膨胀一次
dilation = cv2.dilate(dilation,kernel,iterations=1) #再膨胀一次
cv2.imshow('car_dilation',dilation) #膨胀三次之后,可以看出车牌矩形区域内全部是白色
#再腐蚀三次
erosion = cv2.erode(dilation,kernel,iterations=1)
erosion = cv2.erode(erosion,kernel,iterations=1)
erosion = cv2.erode(erosion,kernel,iterations=1)
cv2.imshow('car_erosion',erosion) #形态学处理之后最终得到的图像
#形态学处理之后的图像还是三通道的黑白图,通过灰度化转换成单通道的黑白图
car = cv2.cvtColor(erosion,cv2.COLOR_BGR2GRAY)
#查找轮廓
contours,hierarchy = cv2.findContours(car,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
x,y,w,h = cv2.boundingRect(c) #轮廓的边界矩形,x,y是矩形左上角的坐标,w,h是矩形的宽度和高度
if w>60 and h>20: #如果当前的这个轮廓区域足够大,它一定是车牌号矩形区域。
# 如果原始图像有大面积的蓝色背景,例如车的颜色是蓝色的,则可以设置w和h的上限值,即min<w<max and min<h<max
x_goal = x
y_goal = y
w_goal = w
h_goal = h
goal = c
car_goal = cv2.imread('C:\\Users\\Administrator\\Desktop\\car.jpg')
cv2.rectangle(car_goal,(x_goal,y_goal),(x_goal+w_goal,y_goal+h_goal),(0,255,0),2) #把车牌号在原始图像上标记出来
cv2.imshow('goal',car_goal)
cv2.waitKey(0)
下图是代码中使用的原始图片car.jpg