# 基于SVM的车牌识别算法

## 二、图像预处理

``````    hsv = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)  # 将RGB图像转换为HSV图像
h, s, v = cv2.split(hsv)  # 分离H,S,V
lower = np.array([100, 90, 40])
upper = np.array([124, 255, 255])  # 设置阈值
mask = cv2.inRange(hsv, lower, upper)  # 获取图像蒙版

``````

``````    img = cv2.equalizeHist(img)  # 直方图均衡化，增强对比度：将已知灰度概率密度分布的图像经过变换，使其称为一个均匀灰度概率密度分布的新图像
img = cv2.GaussianBlur(img, (3, 3), 0, 0, cv2.BORDER_DEFAULT)  # 高斯滤波
``````

``````    flipped = cv2.flip(img, 1)  # 图像翻转，1：水平翻转
sobel1 = cv2.Sobel(img, cv2.CV_8U, 1, 0, ksize=3)  # 图像边缘检测，Sobel算子，对x轴方向求导
sobel2 = cv2.flip(cv2.Sobel(flipped, cv2.CV_8U, 1, 0, ksize=3), 1)  # 先平滑图像边缘，再翻转
img = sobel1 / 2 + sobel2 / 2
img = img.astype('uint8')  # 强制类型转换
``````

``````    th = (np.mean(img) + (np.max(img) - np.mean(img)) * 0.6)
ret, img = cv2.threshold(img, th, 255, cv2.THRESH_BINARY)  # 简单阈值函数，从灰度图像中获取二进制图像
``````

``````img = close_op(img, 36)
``````

## 三、车牌定位

``````    for contour in contours:
area = cv2.contourArea(contour)  # 计算图像轮廓面积
if area < 200 or area > 50000:  # 判断车牌轮廓区域
continue

rect = cv2.minAreaRect(contour)  # 求出点集contour的最小矩形面积，返回值rec[0]为矩形的中心点，rec[1]为矩形的长和宽，rec[2]矩形的旋转角度
if rect[1][0] * rect[1][1] < 666 or area < rect[1][0] * rect[1][1] * 0.6:
continue

dy, dx = contour.flatten().reshape(contour.shape[0], -1).T.ptp(1)
cwb = rect[1][1] / rect[1][0] if rect[1][1] > rect[1][0] else rect[1][0] / rect[1][1]
if dy < dx or cwb < 2.5 or cwb > 6:
continue

if not check_plate(src, rect):
continue

plate = extract_plate(src, rect)  # src为原始图像，rect为车牌区域坐标
``````

## 四、车牌字符分割

``````def plate_cut_text(img):
'''
车牌字符分割，将分割好的车牌区域进行字符分割
'''
sum = np.sum(img, 1)
limit = np.mean(sum) * 0.2
bound = []
start = 0
for i in range(len(sum) - 1):
if sum[i] < limit and sum[i + 1] >= limit:
start = i
elif sum[i] >= limit and sum[i + 1] < limit:
bound.append([start, i])
start = 0
if start != 0:
bound.append([start, len(sum - 1)])
up, down = 0, 0
for b in bound:
if b[1] - b[0] > down - up:
up = b[0]
down = b[1]

return img[up: down + 1, :]
``````

## 五、基于SVM的车牌字符识别

``````reader = SVM_ocr.Reader()
def plate_recognition(plate):  #字符识别代码
'''
车牌识别核心代码，使用SVM对分割的车牌字符进行识别，并将识别结果返回
'''
img = cv2.cvtColor(plate, cv2.COLOR_BGR2GRAY)
th = (np.mean(img) + (np.max(img) - np.mean(img)) * 0.2)
_, img = cv2.threshold(img, th, 255, cv2.THRESH_BINARY) #阈值函数
img = plate_cut_text(img)
display('plate th', img, 360)
bound = plate_split(img) #调用plate_split函数，对车牌字符进行拆分，返回一个列表，列表每个值记录车牌每个字符起始位置
print('拆分出来的各个字符起始位置：',bound)
plate_res = []
for i, b in enumerate(bound):
display('character_'+str(i), img[:,b[0]:b[1]], 50)
if b[1] - b[0] > 5 and b[1] - b[0] < 28: #判断每个分割出来的字符宽度是否正常
if len(plate_res) == 0: