在进行深度学习过程中,数据标注是一个繁琐的工作。我们可以借鉴半监督学习的思路,将数据划分为两部分,对少量数据进行人工标注,然后基于此训练模型。有预训练模型后,可以对剩余的未标注图像进行预测。预训练模型的性能可能不是很准,部分结果需要进行调整。
1、应用背景
具体如下所示,我们有190个图像,只对其中的40个进行标注,然后训练出模型对剩余的150个图进行预测,可以发现只有部分图结果是正确的,对大部分图需要进行调整。
对此有两种操作思路,一是基于ps等专业处理图像的软件,将原图与预测图叠加在一起进行显示,然后对错误预测的区域进行修复(抹除误检区域、补充漏检区域);二是将预测结果转换为json文件,然后使用labelme、anylabeling等软件调整json文件的标注。
2、预测结果转json
2.1 json文件格式分析
labelme、anylabeling等软件都是采用json格式来描述标签,更多软件信息可以参考 目标检测数据标注格式及工具软件简介。
json文件的格式如下所示,最外层存储了数据的基本结构信息,有version、flags、shapes、imagePath、imageData、imageHeight、imageWidth等,其中最为重要的信息有imagePath、shapes、imageHeight、imageWidth。
shapes为数组,其中每一个元素都是字典对象(键值对、key和value),也就是我们在labelme、anylabeling等软件中标注的标签。标签的具体格式如下所示,其中label是指该标签的名称类别,points中存储着标签的关键点信息(为Nx2个二维数组),shape_type表示了该标签对应的图形类别,具体有矩形、多边形、圆、关键点
{
"label": "txqy",
"text": "",
"points": [ [
384.8211009174312,
39.61926605504587
],
[
429.3165137614679,
59.80275229357798
],],
"group_id": None,
"shape_type": "polygon",
"flags": {
}
}
2.2 具体思路
具体实现思路如下所示,先创建json模版数据,然后从模型结果图中获取轮廓信息(使用cv2.findContours函数实现),将轮廓信息转换为符合格式的标签信息存入json模版中(shapes字段),最后将json对象保存为json文件即可。
2.3 具体代码
完整代码如下所示,使用img2json函数将一个预测结果转换json对象并保存。
img2json函数先构建json_data用于存储结构信息,在构建label_data用于存储每一个标注信息(每一次存储前都将label_data进行了一次copy操作
)。这里需要注意的是shape_type通常应为polygon(多边形标注),因为不管原来训练的标注的是圆形、矩形在绘图训练中都是多边形。
import json,cv2,os
def img2json(dir_name,img_name):
#json标注的模板
json_data={
"version": "0.2.24",
"flags": {
},
"shapes":[],
"imagePath": " ",
"imageData": None,
"imageHeight": 0,
"imageWidth":0,
}
#一个label标注的模板
label_data={
"label": "txqy",
"text": "",
"points": [ ],
"group_id": None,
"shape_type": "polygon",
"flags": {
}
}
#label_data=json.dumps(label_data) #将json对象(dict)转换为字符串
print(label_data)
print(label_data["points"])
img=cv2.imread(dir_name+img_name,0)
#获取图形的轮廓
contours, hierarchy = cv2.findContours(img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#遍历图廓点,并存入数组中
for cont in contours:
cont=cont.reshape((-1,2)) #cont.shape n,1,2=>n,2
label_data_d=label_data.copy()
label_data_d["points"]=cont.tolist()
json_data["shapes"].append(label_data_d)
json_data['imagePath']=img_name.replace('.bmp','.jpeg')
json_data['imageHeight']=img.shape[0]
json_data['imageWidth']=img.shape[1]
#将json转换为txt
json_str=json.dumps(json_data,indent=4)
file_name=img_name.replace('.bmp','.json')
fh = open(dir_name+file_name, 'w')
fh.write(json_str)
fh.close()
dir_name="./1020img/"
img_names=os.listdir(dir_name)
img_names=[x for x in img_names if ".bmp" in x]
print(img_names)
for img_name in img_names:
img2json(dir_name,img_name)
3、执行效果
执行效果如下所示,json文件为以上代码所生成的。其中有部分是错误的,我们将jpeg与json文件归档到同一个目录下,即可使用anylabeling与labelme等标注软件对其进行调整。