检查深度学习xml文件

问题描述

这几天在利用tensorlfow训练目标检测时候经常出现下面两种问题:

1、训练faster rcnn过程中出现

RuntimeWarning: invalid value encountered in log targets_dw = np.log(gt_widths / ex_widths)

2、出现:

InvalidArgumentError (see above for traceback): ValueError: a must be non-empty
	 [[Node: vgg_16/rpn_rois/PyFunc = PyFunc[Tin=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_INT32], Tout=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT], token="pyfunc_3", _device="/job:localhost/replica:0/task:0/device:CPU:0"](vgg_16/rois/PyFunc, vgg_16/rois/PyFunc:1, _arg_Placeholder_2_0_2, vgg_16/rpn_rois/PyFunc/input_3)]]
	 [[Node: Momentum/update_vgg_16/cls_score/weights/ApplyMomentum/_440 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/device:GPU:0", send_device="/job:localhost/replica:0/task:0/device:CPU:0", send_device_incarnation=1, tensor_name="edge_1470_Momentum/update_vgg_16/cls_score/weights/ApplyMomentum", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:GPU:0"]()]]

或者

Python int too large to convert to C long

解决

1.针对第一种问题原因是我制作的标签文件中xmin,ymin有为0的情况,而faster rcnn默认在读取annotation的代码如下:

for ix, obj in enumerate(objs):  # 对于该图片上每一个object
            bbox = obj.find('bndbox')    # 找到XML文件中给用于存放gt坐标的模块
            # Make pixel indexes 0-based
            x1 = float(bbox.find('xmin').text) - 1    
            y1 = float(bbox.find('ymin').text) - 1
            x2 = float(bbox.find('xmax').text) - 1
            y2 = float(bbox.find('ymax').text) - 1

也就是对于每一个值都-1,如果是0的话-1就变为负值了,所以会报错。

我在网上还找到有人把上面的-1去掉了,就不会报错,但是我的试了一下还是会报错。因此最终是修改了xml文件,将为0的xmin和ymin都改为了1.

2.至于第二个问题,解决的的过程还是很玄学的。原本我训练的数据太少了只有几百个,所以就做了旋转什么的数据扩增。然而数据扩增后就出现了该问题,我百度谷歌许久也没找到问题的所在。我就在想为什么原来较少的数据能训练,反而扩增后就不行了呢,因此我断定应该是我扩增的数据有一些不同。果然最后发现原数据中目标标注的xmin,ymin,xmax,ymax是保留一位小数的,而我自己数据扩增的代码直接进行了int,坑啊!

另外如果出现Python int too large to convert to C long还有一种可能是因为python2和python3的运算机制不一样,emmmm,反正我也搞不清楚了,我的保留一位小数后就没报错了。

检查xml文件的代码

import os
import xml.dom.minidom
from xml.dom.minidom import Document


def custombasename(fullname):
    return os.path.basename(os.path.splitext(fullname)[0])

def GetFileFromThisRootDir(dir,ext = None):
  allfiles = []
  needExtFilter = (ext != None)
  for root,dirs,files in os.walk(dir):   #files是文件夹下所有文件的名称
    for filespath in files:            #依次取文件名
      filepath = os.path.join(root, filespath)    #构成绝对路径
      extension = os.path.splitext(filepath)[1][1:]  #os.path.splitext(path)  #分割路径,返回路径名和文件后缀 其中[1]为后缀.png,再取[1:]得到png
      if needExtFilter and extension in ext:
        allfiles.append(filepath)
      elif not needExtFilter:
        allfiles.append(filepath)
  return allfiles   #返回dir中所有文件的绝对路径


def move_file(xmlpath):
    rootdir = ''
    img_dir = os.path.join(rootdir, 'images')
    move_image_dir = os.path.join(rootdir,'blank','images')
    move_xml_dir = os.path.join(rootdir,'blank','xml')
    if not os.path.isdir(move_image_dir):
        os.makedirs(move_image_dir )
    if not os.path.isdir(move_xml_dir ):
        os.makedirs(move_xml_dir )
    name = custombasename(xmlpath)
    oldxmlpath = xmlpath
    newxmloath = os.path.join(move_xml_dir +'.xml')

    oldimgpath = os.path.join(img_dir +'.tiff')
    newimgpath = os.path.join(move_image_dir +'.tiff')

    shutil.move(oldimgpath, newimgpath)
    shutil.move(oldxmlpath , newxmloath )
    

def readXml(xmlfile):
    DomTree = xml.dom.minidom.parse(xmlfile)  
    annotation = DomTree.documentElement  
    sizelist = annotation.getElementsByTagName('size') #[]  
    heights = sizelist[0].getElementsByTagName('height')
    img_height = int(heights[0].childNodes[0].data)
    widths =sizelist[0].getElementsByTagName('width')
    img_width = int(widths[0].childNodes[0].data)
    depths = sizelist[0].getElementsByTagName('depth')
    depth = int(depths[0].childNodes[0].data)
    if width != height:
        print('width ~= height %s'%xmlfile)
    objectlist = annotation.getElementsByTagName('object')        
    bboxes = []
    for objects in objectlist:  
        namelist = objects.getElementsByTagName('name')  
        class_label = namelist[0].childNodes[0].data  
        bndbox = objects.getElementsByTagName('bndbox')[0]     
        x1_list = bndbox.getElementsByTagName('xmin')  
        x1 = float(x1_list[0].childNodes[0].data)  
        y1_list = bndbox.getElementsByTagName('ymin') 
        y1 = float(y1_list[0].childNodes[0].data) 
        x2_list = bndbox.getElementsByTagName('xmax')  
        x2 = float(x2_list[0].childNodes[0].data) 
        y2_list = bndbox.getElementsByTagName('ymax')  
        y2 = float(y2_list[0].childNodes[0].data)
        #这里我box的格式【xmin,ymin,xmax,ymax,classname】
        bbox = [x1,y1,x2,y2,class_label]
        bboxes.append(bbox)
        minvalue = min(x1,y1,x2,y2)  #最小值
        max_x_value = max(x1,x2)   #x的最大值
        max_y_value = max(y1,y2)   #y的最大值
        if x1>x2:
            print('Xmin>Xmax %s'%xmlfile)
        if y1>y2:
            print('Ymin>Ymax %s'%xmlfile)

        if minvalue<=0:           
            print('最小值有异常%s'%xmlfile)
        if max_x_value >img_width:
            print('x最大值有异常%s'%xmlfile)
        if max_y_value >img_height:
            print('y最大值有异常%s'%xmlfile)
        
        width = x2 - x1
        height = y2 - y1
        if width == 0:
            print('width=0,图片路径为%s'%xmlfile)
        elif height == 0:
            print('height=0,图片路径为%s'%xmlfile)
        else:
            scale = float(height)/width
            if scale > 4:
                print('scale > 4,图片路径为%s'%xmlfile)
            elif scale <0.25
                print('scale <0.25,图片路径为%s'%xmlfile)
    
    if bboxes == []: #xml中无目标
        print('%s不存在目标'%xmlfile)
        move_file(xmlfile)


if __name__ == '__main__':
     xmldir = 'H:\\FPN_Tensorflow-master\\data\\VOCdevkit\\VOCdevkit_train\\Annotations'  
     xmlpath = GetFileFromThisRootDir(xmldir)
     for xmldir in xmlpath:
         readXml(xmldir)

 

你可能感兴趣的:(检查深度学习xml文件)