现在手中数据标签只有Mask,做检测任务需要将其转化为bbox的pascal格式、coco格式,任务如下:
完整代码稍后更新到github
Step1 : 根据mask生成外围框
########## for test
image = cv2.imread('00080.png')
# 灰度图像
gray = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
# contours记录的是所有的框的信息,
ret, thresh = cv2.threshold(gray, 127, 255,cv2.THRESH_BINARY )
thresh_cont, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 每次输出框的坐标(x,y,w,h),并画出带框图片
for i in range(len(contours)):
x, y, w, h = cv2.boundingRect(contours[i])
cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)
cv2.imwrite('test.png', image)
Step2 : 记录框的坐标并转化为pascal\coco格式
######## 生成xml文件
import xml.etree.cElementTree as ET
import numpy as np
import os
import cv2
def beatau(e,level=0):
if len(e)>0:
e.text='\n'+'\t'*(level+1)
for child in e:
beatau(child,level+1)
child.tail=child.tail[:-1]
e.tail='\n' + '\t'*level
def ToXml(name, contours):
root = ET.Element('annotation')#根节点
erow1 = ET.Element('folder')#节点1
erow1.text= "VOC"
erow2 = ET.Element('filename')#节点2
erow2.text= str(name)
erow3 = ET.Element('size')#节点3
erow31 = ET.Element('width')
erow31.text = "512"
erow32 = ET.Element('height')
erow32.text = "512"
erow33 = ET.Element('depth')
erow33.text = "3"
erow3.append(erow31)
erow3.append(erow32)
erow3.append(erow33)
root.append(erow1)
root.append(erow2)
root.append(erow3)
for i in range(len(contours)):
x, y, w, h = cv2.boundingRect(contours[i])
if w >=3 and h>=3:
erow4 = ET.Element('object')
erow41 = ET.Element('name')
erow41.text = 'lesion'
erow42 = ET.Element('bndbox')
erow4.append(erow41)
erow4.append(erow42)
erow421 = ET.Element('xmin')
erow421.text = str(x)
erow422 = ET.Element('ymin')
erow422.text = str(y)
erow423 = ET.Element('xmax')
erow423.text = str(x + np.round(w).astype(int))
erow424 = ET.Element('ymax')
erow424.text = str(y + np.round(h).astype(int))
erow42.append(erow421)
erow42.append(erow422)
erow42.append(erow423)
erow42.append(erow424)
root.append(erow4)
beatau(root)
return ET.ElementTree(root)
# 记录转化数k
k = 0
for img in os.listdir('./label_color'):
image = cv2.imread('./label_color/'+img)
if img[-1] == 'g':
print(img, k)
k = k+1
gray = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255,cv2.THRESH_BINARY )
thresh_cont, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 每次输出框的坐标(x,y,w,h)
for i in range(len(contours)):
x, y, w, h = cv2.boundingRect(contours[i])
# 对于像素小于3*3的框,忽略,不作为检测框
#if w>=3 and h>=3:
# cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)
cv2.imwrite('./brain_data/label_recolor/test_'+ img, image)
# 生成XML文件
XML = ToXml(img, contours)
XML.write('./brain_data/label_xml/{}.xml'.format(img[:-4]))
2. coco格式(从pasal转成coco)
import xml.etree.ElementTree as ET
import os
import json
coco = dict()
coco['images'] = []
coco['type'] = 'instances'
coco['annotations'] = []
coco['categories'] = []
category_set = dict()
image_set = set()
category_item_id = 0
image_id = 20180000000
annotation_id = 0
def addCatItem(name):
global category_item_id
category_item = dict()
category_item['supercategory'] = 'none'
category_item_id += 1
category_item['id'] = category_item_id
category_item['name'] = name
coco['categories'].append(category_item)
category_set[name] = category_item_id
return category_item_id
def addImgItem(file_name, size):
global image_id
if file_name is None:
raise Exception('Could not find filename tag in xml file.')
if size['width'] is None:
raise Exception('Could not find width tag in xml file.')
if size['height'] is None:
raise Exception('Could not find height tag in xml file.')
image_id += 1
image_item = dict()
image_item['id'] = image_id
image_item['file_name'] = file_name
image_item['width'] = size['width']
image_item['height'] = size['height']
coco['images'].append(image_item)
image_set.add(file_name)
return image_id
def addAnnoItem(object_name, image_id, category_id, bbox):
global annotation_id
annotation_item = dict()
annotation_item['segmentation'] = []
seg = []
#bbox[] is x,y,w,h
#left_top
seg.append(bbox[0])
seg.append(bbox[1])
#left_bottom
seg.append(bbox[0])
seg.append(bbox[1] + bbox[3])
#right_bottom
seg.append(bbox[0] + bbox[2])
seg.append(bbox[1] + bbox[3])
#right_top
seg.append(bbox[0] + bbox[2])
seg.append(bbox[1])
annotation_item['segmentation'].append(seg)
annotation_item['area'] = bbox[2] * bbox[3]
annotation_item['iscrowd'] = 0
annotation_item['ignore'] = 0
annotation_item['image_id'] = image_id
annotation_item['bbox'] = bbox
annotation_item['category_id'] = category_id
annotation_id += 1
annotation_item['id'] = annotation_id
coco['annotations'].append(annotation_item)
def parseXmlFiles(xml_path):
for f in os.listdir(xml_path):
if not f.endswith('.xml'):
continue
bndbox = dict()
size = dict()
current_image_id = None
current_category_id = None
file_name = None
size['width'] = None
size['height'] = None
size['depth'] = None
xml_file = os.path.join(xml_path, f)
print(xml_file)
tree = ET.parse(xml_file)
root = tree.getroot()
if root.tag != 'annotation':
raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))
#elem is , , ,