分组实验报告提交

master
UnknownObject 2 years ago
parent c5ce4d1f6d
commit 1a937ae790

@ -0,0 +1,422 @@
Python分组实验报告
题目 车牌识别与分类
院 系 计算机与控制工程学院
专 业 软件工程
班 级 计237-2
姓 名 王昱博
学 号 202358507208
同组同学 刘钰廷、冯雅君、冯昌盛、潘浩宇、戴晓齐、焦雅雯
指导教师 李瑞旭
2023年 12月 10日
教师批改意见
|序号|评价 |评分标准 |评分 | |
| |指标 | | | |
|1 |软件 |主要指标5项各6分满分30分。 |30 | |
| |情况 |1技术先进性3-6之间 | | |
| | |2功能齐全2-6之间 | | |
| | |3软件设计合理性3-6之间 | | |
| | |4工作量饱满3-6之间 | | |
| | |5安全性3-6之间 | | |
|2 |验收情况|1根据自述对软件和设计整体掌|20 | |
| | |握程度0-10之间 | | |
| | |2回答问题正确程度0-10之间 | | |
|3 |报告结构|根据报告完整性情况在5-10之间打 |10 | |
| |完整情况|分 | | |
|4 |图文 |根据图文规范性在1-10分打分 |10 | |
| |规范 | | | |
|5 |报告论 |根据报告条理清晰、表达准确、要素 |30 | |
| |述情况 |齐全、论述充分等在10-30之间打分| | |
| |合计 |满分100 |100 | |
|其它| | |
|意见| | |
| | | |
| | | |
| |批改教师: | |
| |年 月 日 | |
目录
1项目简介 1
2 需求分析 1
3 概要设计和详细设计 2
4 关键技术和系统实现 3
5 系统测试 4
6 综合设计总结 5
参考文献 6
源代码摘录(部分) 7
1项目简介
本项目是基于计算机视觉、卷积神经网络和OCR技术对符合中华人民共和国交通部标
准的车牌进行识别和分类的程序。程序使用计算机视觉技术将车牌从图像中取出,使用
OCR光学字符识别技术对车牌中的文字即车牌号进行识别处理并使用训练好的神
经网络图像分类模型对车牌进行分类。
2 需求分析
1. 需求概述
本项目需要实现以下功能:
输入与预处理:接收包含车牌的图片,找出图片中车牌所在的具体位置并将其切分为独
立图像。
基于OCR的车牌识别接收预处理过程完成后的图片识别图片中车牌的车牌号并对识
别结果进行修正。
车牌分类:使用图像分类模型对车牌的种类进行分类,输出分类的结果。
--
分类模型的训练使用一个已妥善分类的车牌训练集对预训练的ResNet34模型进行进一
步训练调整,使其能高效准确地完成车牌分类任务。
2. 功能需求
2.1 输入与预处理
接收图片文件作为输入支持jpg/jpeg/png等多种格式。
对输入图像进行预处理,包括图像增强、去噪等操作。
定位图片中车牌具体位置,将车牌切分为独立图像
2.2 车牌识别
使用OCR技术对车牌号进行识别。
按照中华人民共和国交通部相关标准对识别结果进行纠错。
2.3 车牌分类
根据OCR识别结果按照中华人民共和国交通部相关标准进行推测。
使用经过训练地神经网络模型对车牌类型进行识别。
2.4 训练识别模型
使用指定的训练数据集对预训练的图像分类模型进行微调,使其适用于针对车牌
的分类。
3. 非功能需求
系统应能对各种状态下的车牌进行识别
系统应提供用户友好的输出
系统应具有一定的容错能力
3 概要设计和详细设计
本系统的概要设计包括以下模块:
输入和预处理模块:负责接收输入图像数据,并进行预处理。提供图像增强和去
噪的功能。
车牌检测模块:用于检测输入图像中的车牌区域,并对其进行定位。
字符识别模块:对定位到的车牌区域进行字符识别,转换为文本格式。
车牌分类模块使用AI模型对车牌进行分类。
输入和预处理模块详细设计
数据结构:接收和存储输入图像数据。
输入处理函数:实现图像预处理算法,如图像增强、去噪等。
车牌检测模块详细设计
数据结构:接收预处理后的图像作为输入,保存车牌区域的位置信息。
车牌检测函数:实现车牌区域检测算法。可以使用基于边缘检测和特征匹配的方
法来定位车牌。
字符识别模块详细设计
数据结构:接收车牌图像作为输入,保存字符识别的文本结果。
字符识别函数使用深度学习模型进行OCR识别。
车牌分类模块详细设计
数据结构:接收车牌图像作为输入,保存车牌的分类信息。
车牌分类函数:使用预训练的模型对车牌进行分类。
4 关键技术和系统实现
1. 车牌定位
中华人民共和国交通部对车牌的形式、大小、长宽比、底色和背景色等参数做
出了严格的规定。这部分规定就可以成为从图像中提取车牌的依据。
考虑到照片拍摄过程中可能会存在的色差、畸变等问题,我们决定从车牌的形状
(矩形)和长宽比作为突破点进行处理。
通过使用功能完善且开源的计算机视觉库OpenCV我们实现了对图像中符合特定
特征矩形的选取,该矩形的位置即为车牌的位置。
2. OCR识别车牌号
OCR即光学字符识别技术是最常用的从图像中提取文字信息的技术手段
般采用卷积神经网络的方式实现。一个优秀的OCR模型可以识别多种语言且拥有较
高的准确率。
训练一个OCR模型要求大量的文字数据集和长时间的反复调整以及一定的技
术积累,这种从零开始的路线并不适合我们的开发过程。因此我们选用经过检验
的通用OCR库——EasyOCR作为识别使用的库文件。
经过反复的测试我们发现通用OCR库对车牌识别的准确率有限。由于车牌面
积小、文字密度大、排列方式多样的特点导致通用OCR库的优势无法完全发挥
此我们引入了专用于车牌的HyperLPR库作为车牌号识别的主力而EasyOCR作为补
充。通过二者配合,我们获得了不错的识别率。
3. 车牌分类
由中华人民共和国交通部的规范文件可知,不同种类的车牌的底色和背景色由
明显的区别,这一点可以作为对车牌进行分类的依据。
尽管我们可以使用传统的计算机视觉方案比对色彩进行分类,但这样的方案代
码复杂且准确率低因此我们选择了更高效的方案——图像分类AI。
但是正如上文所述,从零开始构建神经网络模型的方案并不理想,因此我们使
用了经过预训练的模型ResNet34并在它的基础上进行进一步微调使它更适用
于对车牌的分类工作。
实际测试表明我们的选择是正确的,预训练模型减轻了我们准备训练集的工作
压力也允许了我们在GPU性能较低的情况下完成多次反复的AI训练工作。最终我
们将最低识别错误率降至6.25%平均错误率降至12.5%以下。
5 系统测试
在开发过程中,我们对每个模块都进行了独立的测试工作,在确认模块运行正常后我
们将它们整合在一起,并对整合后的代码进行了新的测试。
对于图像预处理部分我们使用Pillow库的显示功能将图片处理过程可视化根据处
理的中间结果进一步调整代码:
# plt显示彩色图片
def plt_show0(img):
b, g, r = cv2.split(img)
img = cv2.merge([r, g, b])
plt.imshow(img)
plt.show()
# plt显示灰度图片排除颜色对识别的干扰
def plt_show(img):
plt.imshow(img, cmap='gray')
plt.show()
对于OCR识别和矫正的部分我们编写了一个主函数通过传入不同的图片来测试不
同的情况下算法的表现:
def main():
image_path = "src/image3.jpg"
license_plate, car_type = recognize_license_plate(image_path)
if license_plate:
license_plate = swap_chars(license_plate)
print("number", license_plate)
print("car_type", car_type)
else:
print("ERROR!")
对于训练出的图像分类AI我们采取于OCR类似的测试方案
image_path = 'E:\\VLPR\\Images\\SmallCar\\川A8K059.jpg'
pred_class, confidence = predict_image(image_path)
print(f"图片类别: {pred_class}, 置信度: {confidence}")
6 综合设计总结
在程序整合完成之后,我们准备了测试集对系统进行测试。经过测试发现程序对水平的
车牌识别准确率高,而对倾斜、倒置等情况的车牌识别率偏低,猜测可能为切分程序对
长宽比的筛选所致。而分类AI的表现则非常优秀只要可以完成切分就可以准确的识别
出车牌的类型即使车牌倾斜或者不清晰识别准确率也能在95%以上。以我们项目的开
发周期而言已经远超过了我们的预期结果。
学习心得:
在整个实训过程中,我们通过分工合作完成了代码的各个模块,并进行了最终的整合过
程。实际表明了适当分工可以有效的提升开发效率,降低开发压力。各位组员对项目都
做出了自己的贡献,才有了现在的项目。
——王昱博
在实训中愈发了解使用图像分类AI对车牌种类进行区分的处理过程。深刻认识到使用
收集到的数据对模型进行训练时,需要根据实际情况不断调整模型参数,这样才能使模
型能够更好地拟合数据,提高识别准确率。
——刘钰廷
车牌识别系统可以实现自动化管理,减少了人工成本,降低了管理难度。虽然车牌识别
技术已经取得了很大的进步,但仍然存在一定的误识别率
——冯雅君
Python是一门简洁易学的编程语言相较于其他编程语言更加容易上手。学习过程中
需要多动手实践,多看官方文档和优秀的代码,不断提高自己的编程能力。
——戴晓齐
该项目使用的python库有opencv、panda、easyocr等通过对车牌图片进行剪裁去噪等
处理再到easyocr进行图片文字到识别并进一步对识别后对结果进行分类。在使用e
asyocr识别文字的时候easyocr识别准确率低可能是由于文字不规范所导致的。通过该
项目让我更加了解了python库的强大相对于其他编程语言python提供了大量的内
置函数和库,使得编程变得简单高效。
——焦雅雯
通过这次python项目让我懂得了open CV图像识别的功能通过分辨颜色形状和质地
,用于检测图像中的各种特征,更加方便广泛的应用到我们的生活中,让我学习到了很
多知识。
——潘浩宇
Python作为一门编程语言还是有着不同的优缺点。但是Python无疑是一门值得学
习的编程语言,它为我们提供了丰富的工具和框架来解决实际问题。相信在未来的学习
和实践中我也会对Python有更深入的认识和应用。
——金小杰
通过这次的Python项目让我充分体会到了Python语言的优势——拥有各种各样可以使
编程变得简单的内置函数和库像项目中使用到的opencv,easyocr,fastai等库都简化
了很多的代码量。
——冯昌盛
参考文献
EasyOCR项目文档 https://github.com/JaidedAI/EasyOCR
OpenCV-Python官方文档
https://docs.opencv.org/3.4/d6/d00/tutorial_py_root.html
HyperLPR3官方文档 https://github.com/szad670401/HyperLPR
FastAI项目 https://github.com/fastai/fastai
FasiAI官方教程 https://course.fast.ai/Lessons/lesson1.html
PyTorch官方网站 https://pytorch.org/
项目协作支持:
Gitee https://gitee.com/
U.N.S. Git Server http://git.unknownnetworkservice.com:8013/
文件分发支持:
U.N.S. PFS http://www.unknownnetworkservice.com:40000/
U.N.S. Cloud http://cloud.unknownnetworkservice.com:8020/
源代码摘录(部分)
图像预处理和切分:
@classmethod
def ImagePreProcess(cls, image_path: str) -> tuple:
# 复制一张图片,在复制图上进行图像操作,保留原图
origin_image = cv2.imread(image_path)
# 图像去噪灰度处理
image = origin_image.copy()
# x方向上的边缘检测增强边缘信息
gray_image = cls.gray_guss(image)
Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0)
absX = cv2.convertScaleAbs(Sobel_x)
image = absX
#
图像阈值化操作——获得二值化图将像素置为0或者255。将灰度转成黑白
ret, image = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU)
#
形态学(从图像中提取对表达和描绘区域形状有意义的图像分量)——闭操作
#
使用形状为3010的矩形kernelX对图像进行偏X方向的闭运算将图像进行X方向融
合找出车牌区域。
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 10))
image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelX,
iterations=1)
return origin_image, image
@classmethod
def CutPlateRect(cls, origin_image: cv2.Mat, image: cv2.Mat) ->
cv2.Mat:
# 去除细小的边缘
# 腐蚀erode和膨胀dilate
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 1))
kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 20))
# x方向进行闭操作抑制暗细节
image = cv2.dilate(image, kernelX)
image = cv2.erode(image, kernelX)
# y方向的开操作
image = cv2.erode(image, kernelY)
image = cv2.dilate(image, kernelY)
# 中值滤波(去噪)将边缘平滑
image = cv2.medianBlur(image, 21)
# 获得轮廓 RETR_EXTERNAL矩形的外边缘
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
# 筛选
for item in contours:
rect = cv2.boundingRect(item)
x = rect[0]
y = rect[1]
weight = rect[2]
height = rect[3]
# 根据轮廓的形状特点,确定车牌的轮廓位置并截取图像
if (weight > (height * 3.5)) and (weight < (height * 4)): #
对长宽比例进行确定
_image = origin_image[y:y + height, x:x + weight] #
对图片进行裁剪
return cv2.Mat(_image)
return origin_image
图像分类AI的训练
@classmethod
def TrainAI(cls, data_set_path: str, export_path: str) -> None:
blocks = (ImageBlock, CategoryBlock)
batch_size = 32
dls = DataBlock(
blocks=blocks,
get_items=get_image_files,
splitter=RandomSplitter(),
get_y=parent_label,
item_tfms=Resize(460),
batch_tfms=[*aug_transforms(size=224, min_scale=0.75),
Normalize.from_stats(*imagenet_stats)]
).dataloaders(data_set_path, num_workers=0, bs=batch_size)
model = vision_learner(dls, resnet34, metrics=error_rate)
model.fine_tune(5, freeze_epochs=3) # 5 - 训练的轮次, 3 -
冻结的轮次
model.export(Path(export_path) / 'model.pkl')
OCR识别于基于OCR的车牌类型推测
@classmethod
def RecognizeLicensePlate(cls, image: cv2.Mat, lpr_text: str) ->
tuple:
reader = easyocr.Reader(['ch_sim', 'en'],
model_storage_directory='./easyocr_model')
result = reader.readtext(image)
license_plate = ""
for res in result:
license_plate += res[-2] #
如果车牌号码是两行的,按行识别出来再拼接起来
license_plate = cls.SwapChars(license_plate)
if lpr_text is not None:
license_plate = lpr_text
if '\u8b66' in license_plate:
car_type = '警用车辆'
elif '\u573a\u5185' in license_plate:
car_type = '场内车辆'
elif '\u6302' in license_plate:
car_type = '挂车/半挂车'
elif len(license_plate) > 7:
car_type = '新能源车辆'
else:
car_type = '小型轿车'
return license_plate, car_type
带有功能选择的主程序:
if __name__ == '__main__':
result = input('请选择运行模式(训练(t)/识别(r)): ')
if result == 't' or result == 'T':
data_path = input('输入训练集路径: ')
export_path = input('输入模型保存路径: ')
try:
train(data_path, export_path)
except Exception as e:
print(f'训练过程中发生错误: {e}')
else:
print('模型已成功训练')
finally:
print('训练结束')
elif result == 'r' or result == 'R':
model_index = input('选择使用的识别模型(1/2/3): ')
image_path = input('输入图片路径: ')
if (not model_index.isdigit()) or (int(model_index) < 1) or
(int(model_index) > 3):
print('输入有误')
else:
main(int(model_index), image_path)
else:
print('输入有误')
-----------------------
1
Loading…
Cancel
Save