观察主办单位提供的资料集(约7万张图档),发现图档大致分为下列几种。
1.1 图档内只有1个中文字
1.2 图档内中文字有其他字迹或只有半个字
1.3 图档内含2个以上中文字
1.4 图档内无文字(仅有空白背景)
为了分类上述图档,决定采用one-stage物件侦测演算法-YOLOv4,小量抽样建模後,自动框选中文字。
此次抽样建模的资料集较小(3000张),适合部署到Colab上以免费GPU训练。若资料集过大,不建议以Colab训练模型,曾经遇到VMware硬碟空间不足、上传资料时间过久、模型训练到一半Colab断线或提示GPU用量额满的惨痛经验。
LabelImg
1.1 Windows环境-安装与执行
1.2 操作过程
执行LabelImg後,分别点选Open Dir与Change Save Dir,设定训练集图档路径及标记Annotations(XML档)的储存路径。
勾选选单中View的Auto Save
框选中文字体(Bounding box),并标记为word (快捷键:W拉框框、D下一张、A上一张)
每标记完一张图档 都会产出一个对应的XML档案(切记!档名尽量不要使用中文字)
YOLOv4部署到Colab训练
2.1 在Colab上训练YOLOv4,可以避免Windows+YOlOv4,在呼叫本地端GPU时出现异常。若有Windows+YOlOv4的稳定训练方法,也欢迎大家留言告诉我。
2.2 事前准备
按此下载 train.rar,并解压缩成train资料夹。
将资料集(3000张)放进train下的\VOCdevkit\VOC2021\JPEGImages
将LabelImg标记产生的XML档(3000个),放进train底下\VOCdevkit\VOC2021\Annotations
执行train资料夹中的gen_train_val.py,将资料集以8:2比例分配train与val。
import os, random
from os.path import join, splitext
base = 'VOC2021'
source = join('VOCdevkit',base, 'JPEGImages/')
train_txt = join('VOCdevkit',base, 'ImageSets/Main/train.txt')
val_txt = join('VOCdevkit',base, 'ImageSets/Main/val.txt')
files = os.listdir(source)
random.shuffle(files)
f_train = open(train_txt,'a')
f_val = open(val_txt,'a')
for i, file in enumerate(files):
name = splitext(file)[0]
if (i >=len(files)*0.2):
f_train.write(name+'\n')
else:
f_val.write(name+'\n')
f_train.close()
f_val.close()
执行gen_train_val.py後,得到train.txt与val.txt
train资料夹中voc_label.py,用於YOLOv4训练模型前的datasets预处理(标记Train / Test/Val资料集),将在部署到Colab之後执行。
※注:如果想增加YOLOv4辨识的标签种类(classes),需修改train资料夹中档案的参数设定,请参阅下图。
接下来是将整个train资料夹压缩成train3.zip
2.3 部署到Colab训练:最後一步是将train3.zip上传到Colab训练,完成模型训练後,压缩成train3_finished.tar.gz,再下载到本地端。考量到篇幅过长,详细过程请参阅我的Github
模型成效
3.1 将train3_finished.tar.gz解压缩後,train资料夹中predit.py,执行後可自动框选中文字。
import cv2
import numpy as np
import os
#读取模型与训练权重
def initNet():
CONFIG = 'yolov4-tiny-myobj.cfg'
WEIGHT = 'yolov4-tiny-myobj_last.weights'
net = cv2.dnn.readNet(CONFIG,WEIGHT)
model = cv2.dnn_DetectionModel(net)
model.setInputParams(size=(416, 416), scale=1/255.0)
model.setInputSwapRB(True)
return model
#物件侦测
def nnProcess(image, model):
classes, confs, boxes = model.detect(image, 0.4, 0.1)
return classes, confs, boxes
#框选侦测到的物件
def drawBox(image, classes, confs, boxes):
new_image = image.copy()
for (classid, conf, box) in zip(classes, confs,boxes):
x, y, w, h = box
if x - 2 < 0:
x = 2
if y - 2 < 0:
y = 2
cv2.rectangle(new_image, (x - 2, y - 2), (x + w + 2, y + h + 2), (0, 255, 0), 2)
return new_image
if __name__ == '__main__':
# 主办单位提供的资料集(约7万张)
source = './01_origin/'
files = os.listdir(source)
# 依照正整数排序
files.sort(key=lambda x:int(x[:-6]))
model = initNet()
for file in files:
img = cv2.imdecode(np.fromfile(source+file,dtype=np.uint8), -1)
classes, confs, boxes = nnProcess(img, model)
try:
frame = drawBox(img, classes, confs, boxes)
frame = cv2.resize(frame, (240, 200), interpolation=cv2.INTER_CUBIC)
# 显示框选後的图片
cv2.imshow('img', frame)
cv2.waitKey()
except:
continue
print('程序执行完毕')
3.2 框选中文字效果
图档内只有1个中文字
图档内中文字有其他字迹或只有半个字
图档内含2个以上中文字
图档内无文字(仅有空白背景)
从3.2的结果得知,训练後的YOLOv4模型,可以正确地框选出中文字。唯一美中不足的地方,大概是「体」被模型当成2个字框选。
承上,推测可能是小量抽样(3000张)中,「体」这种情况的样本出现频率较低。增加抽样数量、重新训练模型後,应该可改善框选表现。
考量到:「正式比赛时,每张图档内只会有一个最正确的中文字」。因此,下一章的目标是:「从7万张图档中,取出YOLOv4模型框选为1个中文字的图档,再将物件侦测框(绿色边界框)内的中文字裁切、另存图档,做为新的资料集」。
让我们继续看下去...
>>: [Day3]Rock pi 4「扑街」学到的教训 (°Д°)╯╯︵┴┴
前言 其实 React 众观这几届其实已经有很多大神写过文章,那为何我还要出来写呢?其实就是两个目的...
How - 部属MongoDB 登入以下网址 https://www.mongodb.com/clo...
加工资料泛指各种处理资料的行为,这部分要一篇文章写完真滴难,所以就也只能蜻蜓点水的各介绍一点,让大家...
昨天已经介绍过,透过 grafana 监控 matching 的品质 ,今天来介绍一下,透过 gra...
这篇主要讲GetX所提供, 自己有接触过的额外功能 为大家介绍 多国语系, 萤幕长宽, snackb...