# -*- coding: utf-8 -*-
# [email protected]
import sys
import cv2
import numpy as np
def preprocess(gray):
# # 直方图均衡化
# equ = cv2.equalizeHist(gray)
# 高斯平滑
gaussian = cv2.GaussianBlur(gray, (3, 3), 0, 0, cv2.BORDER_DEFAULT)
cv2.imwrite('c:/img/gaussian.jpg',gaussian)
# 中值滤波
median = cv2.medianBlur(gaussian, 5)
cv2.imwrite('c:/img/median.jpg', median)
# Sobel算子,X方向求梯度
sobel = cv2.Sobel(median, cv2.CV_8U, 1, 0, ksize=3)
cv2.imwrite('c:/img/sobel.jpg', sobel)
# 二值化
# ret, binary = cv2.threshold(sobel, 127, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
ret, binary = cv2.threshold(sobel, 127, 255, cv2.THRESH_BINARY)
cv2.imwrite('c:/img/binary.jpg', binary)
ret, thresh2 = cv2.threshold(sobel, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imwrite('c:/img/thresh2.jpg', thresh2)
ret, thresh3 = cv2.threshold(sobel, 127, 255, cv2.THRESH_TRUNC)
cv2.imwrite('c:/img/thresh3.jpg', thresh3)
ret, thresh4 = cv2.threshold(sobel, 127, 255, cv2.THRESH_TOZERO)
cv2.imwrite('c:/img/thresh4.jpg', thresh4)
ret, thresh5 = cv2.threshold(sobel, 127, 255, cv2.THRESH_TOZERO_INV)
cv2.imwrite('c:/img/thresh5.jpg', thresh5)
# 膨胀和腐蚀操作的核函数
element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 1))
element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
# 膨胀一次,让轮廓突出
dilation = cv2.dilate(binary, element2, iterations=1)
cv2.imwrite('c:/img/dilation.jpg', dilation)
# 腐蚀一次,去掉细节
erosion = cv2.erode(dilation, element1, iterations=1)
cv2.imwrite('c:/img/erosion.jpg', erosion)
# 再次膨胀,让轮廓明显一些
dilation2 = cv2.dilate(erosion, element2, iterations=3)
cv2.imwrite('c:/img/dilation2.jpg', dilation2)
# cv2.imshow('dilation2', dilation2)
# cv2.waitKey(0)
return dilation2
def findPlateNumberRegion(img):
region = []
# 查找轮廓
_a,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 < 1):
continue
# 轮廓近似,作用很小
epsilon = 0.001 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
# 找到最小的矩形,该矩形可能有方向
rect = cv2.minAreaRect(cnt)
print ("rect is: ",rect)
# box是四个点的坐标
box = cv2.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)
print(ratio)
# if (ratio > 20 or ratio < 2):
# continue
region.append(box)
return region
def detect(img):
# 转化成灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite('c:/img/gray.jpg',gray)
# 形态学变换的预处理
dilation = preprocess(gray)
# 查找车牌区域
region = findPlateNumberRegion(dilation)
print('----------------------------------------------------------')
print(len(region))
# 用绿线画出这些找到的轮廓
v=0
for box in region:
v+=1
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]
cv2.imwrite("c:/img/"+str(v)+".jpg",img_plate)
# 带轮廓的图片
cv2.imwrite('c:/img/0.jpg', img)
cv2.imwrite('c:/img/contours.png', img)
# cv2.imshow('带轮廓的图片',img)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
if __name__ == '__main__':
imagePath = 'c:/1.jpg'
img = cv2.imread(imagePath)
detect(img)