目标检测中Bounding Box的详细解读与XML文件解析

 

一、bounding box的形式1---xml文件

 

xml

  • xml文件中矩形框坐标的获取比较简单
    1.xml文件可采用标注软件labelImg进行生成
    2.xml中记录了被标注图像信息和标注的信息

(1)labelImg的安装

一行命令,十分简单。(Ubuntu下的安装方法,别的版本可参照我的博客教程)
  •  
pip install labelImg

 

现在就可以Terminal下打开看看了,点击Open打开一张带标记图片,如图

 

目标检测—Bounding Box的详细解读与XML文件解析_经验分享

图片来自网络

 

根据上面的英文,也都该知道怎么用,其中有些省事省力的工作,就是:
  1. 先给待标注图片做好命名,放在同一文件夹;

  2. 然后设定OpenDir和待保存.xml文件夹下ChangeSaveDir;

  3. 如果是一个类别,可使用Use Default label,这样提高标注效率。

目标检测—Bounding Box的详细解读与XML文件解析_经验分享_02

 

从图片中来,再到图片中去,我们来找一下对应关系

 

目标检测—Bounding Box的详细解读与XML文件解析_经验分享_03

 

二、bounding box的形式1---txt文件

 

内容按行存储,依次是label,x_center,y_center,x_relative,y_relative

 

目标检测—Bounding Box的详细解读与XML文件解析_经验分享_04

 

直观换算后是这样的矩形框

 

目标检测—Bounding Box的详细解读与XML文件解析_经验分享_05

 

三、实现对XML文件bounding box矩形框坐标的获取

 

  •  
# -*- coding:utf8 -*-import osimport xml.etree.ElementTree as ETimport cv2import numpy as np def main(input_path):    Sum_Bndbox_Area = 0    all_N=0    xml_N=0    bndbox_N = 0     for f_1 in os.listdir(input_path):        target_path=os.path.join(input_path, f_1)         for f_2 in os.listdir(target_path):            if f_2 == "label":                doc_path = os.path.join(target_path, f_2)                #print(doc_path)                 for (path, dirs, files) in os.walk(doc_path):                    for filename in files:                        all_N += 1                         # if filename.split('_')[1]=="classes.txt":                        #     print(filename)                            # classestxt_file_path = os.path.join(doc_path, filename)                            # os.remove(classestxt_file_path)                         xmin_list = []                        ymin_list = []                        xmax_list = []                        ymax_list = []                         suffix_name = filename.split('.')[1]                        # print(suffix_name)                        if suffix_name == 'xml':                            xml_file_path = os.path.join(doc_path, filename)                            xml_N += 1                            #print(xml_file_path)                            # 处理对应的xml文件                            tree = ET.parse(xml_file_path)                            root = tree.getroot()                             # for name in root.iter('object'):                            #     label_name = name.find('name').text                            for size in root.iter('size'):                                width = int(size.find('width').text)                                height = int(size.find('height').text)                                #print("width:%.f  height:%.f" % (width, height))                             for box in root.iter('bndbox'):                                xmin = int(box.find('xmin').text)                                xmin_list.append(xmin)                                ymin = int(box.find('ymin').text)                                ymin_list.append(ymin)                                xmax = int(box.find('xmax').text)                                xmax_list.append(xmax)                                ymax = int(box.find('ymax').text)                                ymax_list.append(ymax)                                #print("xmin:%.f  ymin:%.f xmax:%.f  ymax:%.f"%(xmin,ymin,xmax,ymax))                                 #one_bndbox_area = (ymax-ymin)*(xmax-xmin)                                 bndbox_N += 1                                #Sum_Bndbox_Area += one_bndbox_area                            #creat_label_image(xmin_list, ymin_list, xmax_list, ymax_list, 512, 512, filename)                        else:                            xml_file_path = os.path.join(doc_path, filename)                            #print(xml_file_path)                             xmin_list = []                            ymin_list = []                            xmax_list = []                            ymax_list = []                            with open(xml_file_path, "r") as f:                                for line in f.readlines():                                    line = line.strip('\n')  # 去掉列表中每一个元素的换行符                                    #print(line.split(" ")[0])                                     x_center = int(float(line.split(" ")[1])*512)                                    y_center = int(float(line.split(" ")[2])*512)                                    x_shift = int(float(line.split(" ")[3])*256)                                    y_shift = int(float(line.split(" ")[4])*256)                                     xmin=x_center-x_shift                                    xmax=x_center+x_shift                                    ymin=y_center-y_shift                                    ymax=y_center+y_shift                                    xmin_list.append(xmin)                                    ymin_list.append(ymin)                                    xmax_list.append(xmax)                                    ymax_list.append(ymax)                            print("xmin_list[0]=",xmin_list[0])                             creat_label_image( xmin_list, ymin_list, xmax_list, ymax_list,512, 512,filename)                            #draw_rectangle_test(xmin_list, ymin_list, xmax_list, ymax_list, filename, xml_file_path)     Average_Bndbox_Area = Sum_Bndbox_Area/bndbox_N     print("all_N=",all_N)    print("xml_N=",xml_N)    print("bndbox_N=",bndbox_N)    print("Average_Bndbox_Area=",Average_Bndbox_Area)

四、两Bounding_Box的IOU的计算

 

目标检测—Bounding Box的详细解读与XML文件解析_经验分享_06

 

目标检测—Bounding Box的详细解读与XML文件解析_经验分享_07

 

代码:

  •  
 import numpy as np# ############################################################# # IOU# ############################################################def two_Box_iou(list_a, list_b):    """Compute the iou of two boxes.    """    # 获取矩形框交集对应的顶点坐标(intersection)    xmin1, ymin1, xmax1, ymax1 = int(list_a[0]),int(list_a[1]), int(list_a[2]), int(list_a[3])    xmin2, ymin2, xmax2, ymax2 = int(list_b[0]),int(list_b[1]), int(list_b[2]), int(list_b[3])     xx1 = np.max([xmin1, xmin2])    yy1 = np.max([ymin1, ymin2])    xx2 = np.min([xmax1, xmax2])    yy2 = np.min([ymax1, ymax2])     # 计算两个矩形框面积    area1 = (xmax1 - xmin1 + 1) * (ymax1 - ymin1 + 1)    area2 = (xmax2 - xmin2 + 1) * (ymax2 - ymin2 + 1)     # 计算交集面积    inter_area = (np.max([0, xx2 - xx1])) * (np.max([0, yy2 - yy1]))    # 计算交并比    iou = inter_area / (area1 + area2 - inter_area + 1e-6)    return iou#list_a = [321,296,387,342]list_b = [328,313,359,332]rst_IOU = two_Box_iou(list_a, list_b)print(rst_IOU)

 

 

 

初闻不识曲中意,再闻已是曲中人~

 

祝你深度学习快乐~~