labelme标注工具标注的文件是json格式的文件,在yolo检测的框架下需要txt格式的标注,但是没有关系,转换也很简单。
没有labelme的话直接,pip install labelme即可。
(注:labelme默认是保存图片数据的,一般来说用不到,菜单-Save With Image Data取消即可)
这里我标注了4类数据,分别用0 1 2 3表示,由于图片数据涉及到其他公司秘密不方便展示,所以随便找了个图片做标注示范。
json格式标签内容如下
{
"version": "4.5.6",
"flags": {},
"shapes": [
{
"label": "0",
"points": [
[
1966.75,
1436.375
],
[
2088.625,
1567.625
]
],
"group_id": null,
"shape_type": "rectangle",
"flags": {}
},
{
"label": "1",
"points": [
[
666.75,
895.75
],
[
935.5,
1186.375
]
],
"group_id": null,
"shape_type": "rectangle",
"flags": {}
},
],
"imagePath": "..\\FOV_0000.bmp",
"imageData": null,
"imageHeight": 2984,
"imageWidth": 4080
}
yolo的txt标签格式
由于图片可能有尺度缩放所以YOLO里边的位置用的是图片的百分比坐标
python转换代码如下
import json
import os
import cv2
img_folder_path=r'F:\imagedata\FOV\FOV'
folder_path=r"F:\imagedata\FOV\FOV\annotation"#标注数据的文件地址
txt_folder_path = r"F:\imagedata\FOV\FOV\txt"
def create_txt(img_name,json_d,img_path):
src_img=cv2.imread(img_path)
h,w = src_img.shape[:2]
#txt文件名和图片名保持一致
txt_name = img_name.split(".")[0]+".txt"
txt_path = os.path.join(txt_folder_path,txt_name)
print(txt_path)
with open(txt_path,'a+') as f:
for item in json_d["shapes"]:
print(item['points'])
print(item['label'])
point=item['points']
x_center = (point[0][0]+point[1][0])/2
y_center = (point[0][1]+point[1][1])/2
width = point[1][0]-point[0][0]
hight = point[1][1]-point[0][1]
print(x_center)
f.write(" {} ".format(item['label']))
f.write(" {} ".format(x_center/w))
f.write(" {} ".format(y_center/h))
f.write(" {} ".format(width/w))
f.write(" {} ".format(hight/h))
f.write(" \n")
for jsonfile in os.listdir(folder_path):
temp_path=os.path.join(folder_path,jsonfile)
#如果是一个子目录就继续
if os.path.isdir(temp_path):
continue
print("json_path:\t",temp_path)
jsonfile_path=temp_path
with open(jsonfile_path, "r", encoding='utf-8') as f:
json_d = json.load(f)
#读取图片名
img_name=json_d['imagePath'].split("\\")[1]
img_path=os.path.join(img_folder_path,img_name)
print("img_path:\t",img_path)
create_txt(img_name,json_d,img_path)
生成的txt标签文件
0 0.4969822303921569 0.5033512064343163 0.029871323529411766 0.043984584450402146
1 0.19635416666666666 0.3488815348525469 0.06587009803921569 0.09739443699731903
1 0.2717984068627451 0.3488815348525469 0.07123161764705882 0.09739443699731903
1 0.19673713235294119 0.24677446380697052 0.0666360294117647 0.09425268096514745
1 0.2714154411764706 0.2483453418230563 0.0628063725490196 0.09111092493297587
最后把图片和标签数据放到darknet\build\darknet\x64\data\obj目录下,标签和图片在同一个目录下,且标签名和图片名一样,如图
在darknet\build\darknet\x64\cfg目录下修改yolov4-tiny-obj.cfg文件(记得备份原文件),修改bath,width,height,max_batches(下面的steps= max_batches0.8,max_batches0.9),官网的要求width height需要能被32整除,max_batches=classes*2000.
# Training
batch=4
subdivisions=4
width=2048
height=1024
............
learning_rate=0.00261
burn_in=1000
max_batches = 8000
policy=steps
steps=6400,7200
scales=.1,.1
修改classes为你训练数据的种类数,有两处,另外一个很重要的参数每一个[yolo]层前面的filters=(种类数+5)*3,有两处,例如如果有4类,则filters=(4+5)*3=27,5类:filters=(5+5)*3=30
[convolutional]
size=1
stride=1
pad=1
filters=27
activation=linear
[yolo]
mask = 3,4,5
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
classes=4
num=6
...........
[convolutional]
size=1
stride=1
pad=1
filters=27
activation=linear
[yolo]
mask = 0,1,2
anchors = 10,14, 23,27, 37,58, 81,82, 135,169, 344,319
classes=4
num=6
............
在darknet\build\darknet\x64\data目录下创建FOV_obj.data文件(文件名随便取),写入内容
classes= 4
train = data/train.txt
valid = data/test.txt
names = data/FOV_obj.names
backup = backup/
创建FOV_obj.name文件写入以下内容
0
1
2
3
创建train.txt文件写入你想要训练的图片
data/obj/FOV_0000.jpg
data/obj/FOV_0001.jpg
data/obj/FOV_0002.jpg
data/obj/FOV_0003.jpg
data/obj/FOV_0004.jpg
..............
创建test.txt文件写入
data/obj/FOV_0065.jpg
data/obj/FOV_0066.jpg
data/obj/FOV_0067.jpg
data/obj/FOV_0068.jpg
.............
python代码
#train.txt
txt_ = r"D:\mydoc\ML\yolo\darknet\build\darknet\x64\data\train.txt"
with open(txt_,'a+') as f:
for i in range(60):
item = "data/obj/"+"FOV_{}.jpg".format(str(i).zfill(4))
f.write(item)
f.write("\n")
#test.txt
txt_ = r"D:\mydoc\ML\yolo\darknet\build\darknet\x64\data\test.txt"
with open(txt_,'a+') as f:
for i in range(60,69):
item = "data/obj/"+"FOV_{}.jpg".format(str(i).zfill(4))
f.write(item)
f.write("\n")
https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.conv.29
放入darknet\build\darknet\x64目录下
打开cmd进入darknet.exe所在目录
输入
darknet.exe detector train data/FOV_obj.data cfg/yolov4-tiny-obj.cfg yolov4-tiny.conv.29 29
可以看到训练损失开始很大,在训练200-300个batch时下降到3点几,并在此处震荡,另外每训练1000个batch会保存一次模型。模型权值保存在darknet\build\darknet\x64\backup目录下,某次训练中断了,想要接着上一次的训练过程继续的话也很方便,输入:
darknet.exe detector train data/FOV_obj.data cfg/yolov4-tiny-obj.cfg backup\yolov4-tiny-obj_last.weights
使用刚刚训练的模型权重做测试
darknet.exe detector test data/FOV_obj.data cfg/yolov4-tiny-obj.cfg backup\yolov4-tiny-obj_1000.weights
在Enter Image path:处填入图片路径(eg:data/test.jpg)
######OK,至此基本训练流程走完,剩下的就是提升网络性能了。
训练过程的一点总结