这几天在利用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,反正我也搞不清楚了,我的保留一位小数后就没报错了。
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)