引言
接上篇,我们搭建完了环境,并下载好所需要的功能包后,我们需要对图像首先进行一个预处理,由于是教大家入门pytorch,因此CV部分的预处理方法会比较粗糙。 下面进入正题!
正文
由于仅仅是教学例程,我们就不利用摄像头采集图像了,直接百度一些带车牌的车的图片进行处理。 首先,我们在工程目录下创建image文件夹,将选中的几张带车牌的图片存放在该文件夹下。 我把这些图片打包成压缩文件,大家可以保存自提,也可以自行搜索一些类似的车牌足够清晰的图片进行测试。 image链接:https://pan.baidu.com/s/1kRE7va7vpxTXr5NIBraELQ 提取码:8y3d
在获取到图片之后,我们需要对图片中的车牌位置进行标记,并且需要将整个车牌截取下来。 下面开始处理,首先我们包含一些需要用到的包。
import cv2
import numpy as np
from PIL import Image
接下来我们创建一个用于车牌图像预处理的类,在类方法中完成对车牌的识别,以及字符的分割。 我们在该类的初始化构造方法中存储图片所在的路径,以及添加一些用户的输入,这样在后面测试的时候可以方便选择识别其中某一张图片,代码如下:
class Carlicense_distinguish:
def __init__(self):
self.content = 'D:/PycharmProjects/Num_distinguish/image/'
self.after = '.jpg'
self.choice = input('Please choose one from \'car1\',\'car2\',\'car3\',\'car4\'.\n')
if self.choice == 'car1' or self.choice == 'car2' or self.choice == 'car3' or self.choice == 'car4' or self.choice == 'car5':
self.carlicense_content = self.content + self.choice + self.after
print('Identify success !')
else:
self.carlicense_content = 'D:/PycharmProjects/Num_distinguish/image/car1.jpg'
print('Input wrong !\nInitialize to \'car1\'')
im = Image.open(self.carlicense_content)
im.show()
完成初始化构造函数之后,我们开始对车牌进行处理,我们定义carlicense_distinguish方法,在该方法中实现图像的预处理。 首先我们的思路是利用图像的rgb三通道值,选出车牌蓝色的三通道范围。我们可以利用鼠标回调函数,来显示图片中具体某一点的rgb三通道值。下面我们开始逐步实现, 首先我们将图像读取出来,并利用resize函数定义图像的尺寸,并对图像滤波。 然后我们将滤波后的图像显示出来并利用鼠标回调函数读取某像素点的三通道值,代码如下:
def carlicense_distinguish(self):
lower_limi = np.array([80, 30, 0]) # 设置色域上下界
upper_limi = np.array([230, 110, 70])
img_init = cv2.imread(self.carlicense_content) # 加载原始图片
img_resize = cv2.resize(img_init, dsize=(1000, 600), fx=0, fy=0) # 重置图片尺寸
img_blur = cv2.blur(img_resize, (2, 2)) # 对图片进行降噪
def mouse_callback(event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDBLCLK:
print('BGR:', img_resize[y, x], 'x:', x, 'y:', y)
cv2.namedWindow('IMG', cv2.WINDOW_NORMAL)
cv2.imshow('IMG', img_blur)
cv2.setMouseCallback('IMG', mouse_callback)
cv2.waitKey(0)
上面的代码是开头定义的类中的方法,不是全局方法。 接下来只需要实例化这个类,并调用这个方法就可以显示滤波后的图片了,代码如下:
img_dist = Carlicense_distinguish()
img_dist.carlicense_distinguish()
然后我们用鼠标在img窗口中点击车牌区域的蓝色部分,就可以在调试端口打印图片的三通道值了。效果如下图:
接下来我们把图片中我们规定的范围进行加入限定,并把限定完之后的图片显示出来,代码如下:(此处代码是对上面的扩充,无需添加在上面代码的下方)
def carlicense_distinguish(self):
lower_limi = np.array([80, 30, 0]) # 设置色域上下界
upper_limi = np.array([230, 110, 70])
img_init = cv2.imread(self.carlicense_content) # 加载原始图片
img_resize = cv2.resize(img_init, dsize=(1000, 600), fx=0, fy=0) # 重置图片尺寸
img_blur = cv2.blur(img_resize, (2, 2)) # 对图片进行降噪
img_limi = cv2.inRange(img_blur, lower_limi, upper_limi) # 选出指定色域(二值化,黑色:0,白色:255)
cv2.namedWindow('IMG', cv2.WINDOW_NORMAL)
cv2.imshow('IMG', img_limi)
cv2.waitKey(0)
运行代码后,我们可以看到选出的区域为白色,效果如下图:
我们大致将车牌的区域显示出来了,接下来我们需要在原图中剥离出该车牌,首先用findContours找二值化图像中的连接色域,并用max方法获取最大区域,该色域在图中显然是车牌处,再利用minAreaRect获取该区域的外界矩形,并利用drawContours方法绘制该矩形。最后再将抠出来的车牌进行二值化。 代码如下:
def carlicense_distinguish(self):
lower_limi = np.array([80, 30, 0]) # 设置色域上下界
upper_limi = np.array([230, 110, 70])
img_init = cv2.imread(self.carlicense_content) # 加载原始图片
img_resize = cv2.resize(img_init, dsize=(1000, 600), fx=0, fy=0) # 重置图片尺寸
img_blur = cv2.blur(img_resize, (2, 2)) # 对图片进行降噪
img_limi = cv2.inRange(img_blur, lower_limi, upper_limi) # 选出指定色域(二值化,黑色:0,白色:255)
cont = cv2.findContours(img_limi, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] # 找出色域外边界
c = max(cont, key=cv2.contourArea) # 在边界中找最大面积的区域
rect = cv2.minAreaRect(c) # 绘制出该区域最小外接矩形
box = cv2.boxPoints(rect) # 记录上述矩形四点坐标
cv2.drawContours(img_resize, [np.int0(box)], -1, (0, 255, 255), 2) #绘制出矩形轮廓'''
img_final = img_resize[int(min(box[1][1], box[2][1]))
:int(max(box[0][1], box[3][1]))
, int(min(box[0][0], box[1][0]))
:int(max(box[2][0], box[3][0]))] # 圈出车牌
img_final_resize = cv2.resize(img_final, dsize=(200, 50), fx=0, fy=0)
lower_limi2 = np.array([100, 100, 100]) # 设置色域上下界
upper_limi2 = np.array([255, 255, 255])
img_final_bin = cv2.inRange(img_final_resize, lower_limi2, upper_limi2)
cv2.namedWindow('IMG', cv2.WINDOW_NORMAL)
cv2.imshow('IMG', img_resize)
cv2.imshow('IMG2', img_final_resize)
cv2.imshow('IMG3', img_final_bin)
cv2.waitKey(0)
运行上述代码之后,效果如下:
到此我们便完成了一个比较粗糙的车牌识别,到这步,实现了对车牌区域的识别以及车牌的二值化处理。
总结
本节任务完成之后,仅仅只完成了CV预处理的前百分之五十,还有后百分之五十的任务内容是车牌的字符分割。这部分内容将在下期讲解。 当然预处理不是我们学习的重点,为了后面对pytorch的入门,我们需要经历整个神经网络项目的流程,包括训练数据集的搭建,神经网络的搭建,以及误差函数等的定义,到最后训练识别,输出结果。这部分的预处理只是为了方便我们提供合适的数据集。