项目需要对同一画面内出现的多个车牌进行识别,但是HpyerLPR只支持识别一个车牌。查了多方资料,最终确定,为了稳定性着想,放弃修改导入的hyperlpr包,换思路:先进行车辆检测,确定车的位置,再将图片传入车牌检测模块进行车牌检测。
车辆检测和车牌检测分属于两个project(见前面的两节)。
目前存在问题主要是如何将车辆识别的结果截图传至车牌检测。
失败想法:考虑进行图像的加减。简单粗暴将图片直接按框进行切割——识别车牌,打码——再把切下来改过的和剩下的加在一起。这样就不需要改hyperlpr传入的方式,对于后面打码的工作,同样也是直接可对单个区域打码,难度相对较低。但是!!!图像的加减需要保证两个图片的大小完全相同,这里没想到很好的函数去处理这样的抠图。
成功:先进行车辆识别,存储识别结果(单个车的图片),循环扔进车牌识别获得坐标结果,将车牌相对于车的坐标,结合车相对于原图的坐标结合计算得到车牌相对于原图的坐标,用于打框。
具体实施:(1)借助程序原本就有的函数save_crop,令其为真之后,将自动将检测结果裁下保存。同时保存每个车的坐标位置
with open(txt_path + '.txt', 'w') as f:#无论检测多少次,数据都是一次次刷新重叠,不会追加
#先检测是不是已经有了crops目录,也就是之前的检测结果,如果有,覆盖目录重建
if (os.path.exists(str(save_dir / 'crops'))):
tmp = tempfile.mktemp(dir=os.path.dirname(str(save_dir / 'crops')))
shutil.move(str(save_dir / 'crops'), tmp)
shutil.rmtree(tmp)
os.makedirs(str(save_dir / 'crops'))
for *xyxy, conf, cls in reversed(det):#reversed(det)是个逆向序列
if save_txt: # Write to file
c = int(cls) # integer class
if names[c] in ['car', 'bus', 'truck']:
line = (*xyxy, conf) # label format
f.write(('%g ' * len(line)).rstrip() % line + '\n')
#将预测到的目标剪下来
if save_img or save_crop or view_img: # Add bbox to image
c = int(cls) # integer class
if names[c] in ['car', 'bus', 'train', 'truck']:
save_one_box(xyxy, imc, file=save_dir / 'crops' / f'{p.stem}.jpg', BGR=True)
(2)进入循环,读取车辆坐标和车辆图片(一一对应),检测每个图片是否存在车牌,存在则返回车牌坐标,结合车辆坐标,计算车牌在原图中的位置,传递给原本就有的画框函数annotator.box_label进行画框。
with open("runs/detect/standard/labels/carmore.txt", "r") as f:
with open('runs/detect/standard/labels/coordinates_new.txt', 'w') as f1:
image_true = cv2.imread("data/images/carmore.png")
for filename in os.listdir(r"./" + "runs/detect/standard/crops"):
image_detect = cv2.imread("runs/detect/standard/crops" + "/" + filename)
if HyperLPR_plate_recognition(image_detect)==[]:#如果此车的车牌本身已被遮盖,无法检测到
f.readline() # 一行一行读取内容,注意这里需要跳过此车的坐标信息
continue
else:
content,_,coordinates_little=HyperLPR_plate_recognition(image_detect)[0]
data = f.readline()# 一行一行读取内容
coordinates_big = data.split()
#计算车牌相对于原图的位置
x_now1 = int(coordinates_big[0]) + coordinates_little[0]
y_now1 = int(coordinates_big[1]) + coordinates_little[1]
x_now2 = int(coordinates_big[0]) + coordinates_little[2]
y_now2 = int(coordinates_big[1]) + coordinates_little[3]
xyxy_new = (x_now1, y_now1, x_now2, y_now2)
annotator = Annotator(image_true, line_width=line_thickness, example=str(names))
annotator.box_label(xyxy_new, color=colors(c, True)) # 对选定区域进行框选
f1.write(('%g ' * len(xyxy_new)).rstrip() % xyxy_new + '\n')#将车框的坐标存入coordinates_new.txt
效果展示:(左下两个是自己前面测试别的内容,手动涂掉的,右下未被识别的是因为本程序逻辑是车识别——>车辆识别,右下本身就不是车,不是处理的部分)