放假前写的代码,pip更新了连注释都不能写,现在看一下真不知道自己写了什么鬼。最邪的是我的能在当前py文件下调用函数生成imread的对象,但是在测试文件就不行,检查过绝对路径和相对路径没有中文,我尝试通过导入imread对象还是None,我纳闷了。所以我决定还是把测试写到同一个地方吧。车牌已经打马赛克。
目录
1 安装
正常pip就行,pycharm会有init错误,Linux下没有错误。
2 代码实现
2.1 调整图片
def pic_resize(img, max_width=1000):
"""
调整车牌的大小
:param img: 传入的图片
:param max_width: 最大的宽度默认1000
:return: 返回车牌
"""
print("168h,The function'{}' is running.".format(sys._getframe().f_code.co_name))
height, width = img.shape[:2]
if width > max_width:
change_rate = max_width / width
# 基于局部像素的重采样
img = cv2.resize(img, (max_width, numpy.int(change_rate * height)), interpolation=cv2.INTER_AREA)
return img
测试
if __name__ == '__main__':
img = cv2.imread(JPG)
# test pic_resiz
height, width = img.shape[:2]
print("164h,The original height:", height, "px width:", width, "px")
res = pic_resize(img)
print("169h,The original height:", res.shape[0], "px width:", res.shape[1], "px")
结果
64h,The original height: 1632 px width: 2048 px
168h,The function'pic_resize' is running.
169h,The original height: 796 px width: 1000 px
Process finished with exit code 0
2.2 去噪声
# erode&dita
def pic_open(img):
# 转成灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 阈值处理
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU | cv2.THRESH_BINARY)
# 返回符合的地方,并用矩形圈起来
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 去燥有一些小的矩形,去除边缘毛躁
er = cv2.erode(binary, kernel)
# 进行膨胀操作
di = cv2.dilate(binary, kernel)
img = cv2.add(er, di)
return img
测试
# main函数中
cv2.imshow("carshow",img)
img = pic_open(img)
cv2.imshow("pic_open", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果
2.3 Candy边缘检测
def pic_extract_edge(binary):
"""
candy边缘检测
:param binary:
:return:
"""
can_res = cv2.Canny(binary, 50, 150)
# cv2.imwrite("write_pic/car_plate_pic/edge50_150.jpg", can_res)
kernel = numpy.ones((25, 25), numpy.uint8)
img_edge = cv2.morphologyEx(can_res, cv2.MORPH_CLOSE, kernel)
img_edge = cv2.morphologyEx(img_edge, cv2.MORPH_OPEN, kernel)
# cv2.imwrite("write_pic/car_plate_pic/pic_tract_edge_openclose_25.jpg", img_edge)
contours, hierarchy = cv2.findContours(img_edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
return contours
因为之前有write结果所以直接看图片
2.4 提取车牌号
要用提取最小的矩形,因为从图片可知马路上会有虚线或者是旁边的草丛或者是其他很多的干扰。
def get_ratio(rect):
"""
用于计算长宽之比
rect:传入一个矩形
"""
width, height = rect[1]
if width > height:
ratio = width / height
else:
ratio = height / width
return ratio
def is_car_plate_box(rect):
"假如比例是2.5到4自检都是可以检测出车牌的"
if 2.5 < get_ratio(rect) < 4:
return True
return False
# extract car plate
def pic_extract_car_plate(contours, minarea=8100, maxarea=11400):
car_plates = []
for contour in contours:
if minarea < cv2.contourArea(contour) < maxarea:
#找最小面积的矩形
rect = cv2.minAreaRect(contour)
if is_car_plate_box(rect):
car_plates.append(contour)
# print(len(car_plates))
return car_plates
图取到以后就可以把它在原图标识出来
def pic_draw_car_plates(src, car_plates):
if len(car_plates) != 1:
print("The length of the car_plates should be 1. I need to adjust the parameters.")
return
plate_result = None
for plate in car_plates:
ltx, lty, rbx, rby = get_position(plate)
cv2.rectangle(src, (ltx, lty), (rbx, rby), (0, 0, 255), 2)
# print(ltx, lty, rbx, rby)
plate_result = src[lty:rby, ltx:rbx, :]
return plate_result
# cv2.imshow("carshow", src)
# cv2.imshow("plate_result", plate_result)
# cv2.imwrite("write_pic/car_plate_pic/pic_draw_car_plates(src).jpg", src)
# cv2.imwrite("write_pic/car_plate_pic/pic_draw_car_plates(plate_result).jpg", plate_result)
结果