在计算机专业的毕业设计、课程设计选题中,基于计算机视觉的车牌识别系统是经典且热门的方向——既有技术深度,又有明确的实际应用场景,答辩认可度高。但很多同学从零实现时,常会遇到车牌定位不准、字符识别率低、界面开发繁琐等问题,网上零散的免费源码又普遍存在缺文件、跑不通、无售后的痛点。
本文就完整拆解一套基于Python+PyQt5+SVM算法的车牌识别系统,从算法原理、核心代码到界面实现逐一讲解,完整覆盖车牌定位、字符分割、模型训练、可视化交互全流程,非常适合用作毕设、课程设计、期末大作业的参考项目。
本项目是一套客户端式车牌识别软件,支持上传本地汽车图片,自动完成车牌定位、矫正、字符分割与识别,最终输出完整车牌号码与车牌颜色。
支持蓝牌、绿牌、黄牌三种主流车牌识别
自带可视化交互界面,操作直观
识别速度快,清晰场景下准确率高
适用于智能交通、园区车辆管理等场景,也可直接用于计算机专业毕设、课程设计项目
| 技术模块 | 选用工具/算法 |
|---|---|
| 开发语言 | Python 3.x |
| 图像处理 | OpenCV |
| 字符识别算法 | SVM支持向量机 |
| 图形界面 | PyQt5 |
| 开发环境 | PyCharm |
系统整体分为两层,职责清晰,便于二次开发与功能扩展:
界面UI层:基于PyQt5实现,负责图片导入、识别结果展示、操作交互,直观呈现车牌定位区域与识别号码
算法核心层:包含图像预处理、车牌定位、倾斜矫正、字符分割、SVM字符识别五大模块,是系统的核心功能支撑
系统按标准化步骤处理图像,流程可控且可针对不同场景优化参数:
图像缩放 → 灰度化与去噪 → 边缘检测与形态学处理 → 轮廓筛选定位车牌 → 倾斜矫正 → 颜色判别 → 字符分割 → 特征提取 → SVM识别 → 结果输出
车牌定位是识别的第一步,直接决定最终识别准确率。本项目通过“去噪-边缘提取-轮廓筛选-颜色校验”多步组合,实现稳定的车牌区域提取。
先对原图进行高斯模糊去除噪声,再转换为灰度图,降低计算量同时保留边缘特征。
import cv2
import numpy as np
# 高斯去噪 + 灰度化
def preprocess_image(img, blur=5):
if blur > 0:
# 高斯模糊去除噪声
img = cv2.GaussianBlur(img, (blur, blur), 0)
# BGR转灰度图
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
return gray_img
通过Canny算子提取边缘,再用开闭运算将离散边缘连成完整区域,便于后续轮廓查找。
def edge_detect(gray_img):
# 顶帽处理突出车牌区域
kernel = np.ones((20, 20), np.uint8)
img_opening = cv2.morphologyEx(gray_img, cv2.MORPH_OPEN, kernel)
img_opening = cv2.addWeighted(gray_img, 1, img_opening, -1, 0)
# Otsu二值化 + Canny边缘检测
ret, img_thresh = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
img_edge = cv2.Canny(img_thresh, 100, 200)
# 闭运算连接边缘,开运算去除噪点
kernel_close = np.ones((4, 19), np.uint8)
img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel_close)
img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel_close)
return img_edge2
根据车牌长宽比(2:1~5.5:1)筛选候选矩形轮廓,再对倾斜的车牌进行仿射变换矫正,保证字符水平。
def find_plate_contours(img_edge, min_area=1000):
# 查找所有轮廓
contours, hierarchy = cv2.findContours(img_edge, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
plate_rects = []
for cnt in contours:
if cv2.contourArea(cnt) < min_area:
continue
# 获取最小外接矩形
rect = cv2.minAreaRect(cnt)
w, h = rect[1]
if w < h:
w, h = h, w
# 按车牌长宽比筛选
ratio = w / h
if 2 < ratio < 5.5:
plate_rects.append(rect)
return plate_rects
转换到HSV颜色空间,通过色调范围判断车牌颜色(蓝/绿/黄),同时反向处理黄、绿车牌,提升后续字符分割准确率。
def detect_plate_color(card_img):
hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)
row_num, col_num = card_img.shape[:2]
total = row_num * col_num
yellow = green = blue = 0
for i in range(row_num):
for j in range(col_num):
H, S, V = hsv[i, j]
if 11 < H <= 34 and S > 34:
yellow += 1
elif 35 < H <= 99 and S > 34:
green += 1
elif 99 < H <= 124 and S > 34:
blue += 1
if yellow * 2 >= total:
return "yellow"
elif green * 2 >= total:
return "green"
elif blue * 2 >= total:
return "blue"
return "unknown"
通过水平、垂直灰度直方图查找波峰,分离出单个字符,同时去除铆钉、边框等干扰因素。
def split_chars(gray_img, color):
# 黄绿牌字符反转,便于分割
if color in ["green", "yellow"]:
gray_img = cv2.bitwise_not(gray_img)
ret, binary = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 水平直方图裁剪上下边缘
x_hist = np.sum(binary, axis=1)
x_min = np.min(x_hist)
x_avg = np.sum(x_hist) / x_hist.shape[0]
x_thresh = (x_min + x_avg) / 2
# 查找水平波峰,截取有效车牌区域
# 垂直直方图分割单个字符
y_hist = np.sum(binary, axis=0)
# 按波峰分割字符,处理汉字与分隔点
# 最终返回分割后的单字符图像列表
pass
对单个字符提取HOG方向梯度直方图特征,作为SVM模型的输入,提升识别准确率。
def preprocess_hog(digits):
samples = []
for img in digits:
# Sobel算子计算梯度
gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
mag, ang = cv2.cartToPolar(gx, gy)
bin_n = 16
bin = np.int32(bin_n * ang / (2 * np.pi))
# 分块计算直方图
bin_cells = bin[:10,:10], bin[10:,:10], bin[:10,10:], bin[10:,10:]
mag_cells = mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]
hists = [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]
hist = np.hstack(hists)
# Hellinger核归一化
eps = 1e-7
hist /= hist.sum() + eps
hist = np.sqrt(hist)
hist /= np.linalg.norm(hist) + eps
samples.append(hist)
return np.float32(samples)
采用OpenCV内置的SVM分类器,分别训练汉字、字母数字两个模型,完成车牌字符识别。
class SVMClassifier:
def __init__(self, C=1, gamma=0.5):
self.model = cv2.ml.SVM_create()
self.model.setGamma(gamma)
self.model.setC(C)
# RBF核函数,适配非线性分类
self.model.setKernel(cv2.ml.SVM_RBF)
self.model.setType(cv2.ml.SVM_C_SVC)
def train(self, samples, labels):
# 训练模型
self.model.train(samples, cv2.ml.ROW_SAMPLE, labels)
def predict(self, samples):
# 预测字符类别
_, result = self.model.predict(samples)
return result.ravel()
界面采用左右分栏布局:
左侧:图像显示区,展示原始车牌图片
右侧:识别结果区 + 控制面板,展示车牌定位预览、识别号码、车牌颜色,以及打开图片、清空数据按钮
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
import sys
class PlateRecognitionWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("OpenCV SVM车牌识别系统")
self.setMinimumSize(1100, 700)
# 初始化识别器
self.predictor = None
# 构建界面
self.init_ui()
self.clean_state()
def init_ui(self):
# 主布局 左右分栏
central_widget = QWidget()
self.setCentralWidget(central_widget)
main_layout = QHBoxLayout(central_widget)
main_layout.setContentsMargins(30, 30, 30, 30)
main_layout.setSpacing(25)
# 左侧图像显示区
self.image_label = QLabel("欢迎使用车牌识别系统")
self.image_label.setAlignment(Qt.AlignCenter)
self.image_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
main_layout.addWidget(self.image_label, 6)
# 右侧功能区
right_widget = QWidget()
right_widget.setFixedWidth(360)
right_layout = QVBoxLayout(right_widget)
# 识别结果分组
res_group = QGroupBox("识别结果分析")
res_layout = QVBoxLayout(res_group)
self.roi_label = QLabel("车牌预览区")
self.result_label = QLabel("待识别")
self.color_label = QLabel("车牌颜色:---")
res_layout.addWidget(self.roi_label)
res_layout.addWidget(self.result_label)
res_layout.addWidget(self.color_label)
# 控制面板分组
btn_group = QGroupBox("系统控制面板")
btn_layout = QVBoxLayout(btn_group)
self.btn_load = QPushButton("打开本地图片")
self.btn_clear = QPushButton("清空当前数据")
btn_layout.addWidget(self.btn_load)
btn_layout.addWidget(self.btn_clear)
right_layout.addWidget(res_group)
right_layout.addWidget(btn_group)
main_layout.addWidget(right_widget, 4)
# 绑定事件
self.btn_load.clicked.connect(self.load_image)
self.btn_clear.clicked.connect(self.clean_state)
def load_image(self):
# 打开本地图片并执行识别
pass
def clean_state(self):
# 重置界面状态
pass
if __name__ == "__main__":
app = QApplication(sys.argv)
window = PlateRecognitionWindow()
window.show()
sys.exit(app.exec_())
蓝色车牌识别:常规民用蓝牌定位准确,字符识别率高,适合绝大多数日常场景
绿色新能源车牌:支持8位新能源车牌识别,自动适配绿牌颜色特征
黄色车牌:支持大型车辆黄牌识别,自动处理字符颜色反转
系统在光线充足、车牌清晰的场景下识别准确率优异,界面操作简洁,运行稳定,满足日常演示与项目交付需求。
对应的系统全功能操作演示、部署步骤实拍视频,我也同步更新在了B站账号 兵慌码乱,想看动态运行效果、跟着视频一步步部署的同学,可以自行搜索查看。
安装Python 3.8及以上版本
安装依赖库:
pip install opencv-python pyqt5 numpy
导入项目代码,配置好SVM训练模型文件
运行主程序文件,点击“打开本地图片”选择车牌图片即可自动识别
本项目完整实现了从车牌定位到字符识别的全流程,基于Python开发上手难度低,代码结构清晰便于二次修改,同时自带可视化界面,非常适合作为计算机专业的毕业设计、课程设计项目。
留言互动