Tensorflow object detection API 搭建属于自己的物体识别模型——常见问题汇总 Q&A

在上一篇博客《(更新视频教程)Tensorflow object detection API 搭建属于自己的物体识别模型(2)——训练并使用自己的模型》中,有很多读者提出各种问题,也有不少热心读者在评论区进行了讨论,为了方便读者查询及备忘,现把部分问题及解决方案更新到这个博客,不定期更新新的解决方案。

建议 Ctrl + F 在页面内搜索问题。

如果对问题有新的更好的解决方案欢迎留言。

 

Q:Image size must contain 3 elements.

图片大小必须包括3元素

A:图片不是标准的RGB3通道图片,把图片转化成标准的RGB格式或者删除有问题的图片。

如果目录下有很多图片,可以用下面的命令来检查哪些图片不是标准RGB格式:

from PIL import Image     
import os       
path = '/Users/lyz/Desktop/dataset/images/' #图片目录 
for file in os.listdir(path):      
     extension = file.split('.')[-1]
     if extension == 'jpg':
           fileLoc = path+file
           img = Image.open(fileLoc)
           if img.mode != 'RGB':
                 print(file+', '+img.mode)

 

 

 

Q: 提取frozen_inference_graph.pb 这一文件时,出现了数据类型错误

TypeError: x and y must have the same dtype, got tf.float32 != tf.int32

A:在 post_processing_builder.py 文件中,修改下面这个函数:

def _score_converter_fn_with_logit_scale(tf_score_converter_fn, logit_scale):
  """Create a function to scale logits then apply a Tensorflow function."""
  def score_converter_fn(logits):
    cr = logit_scale
    cr = tf.constant([[cr]],tf.float32)
    print(logit_scale)
    print(logits)
    scaled_logits = tf.divide(logits, cr, name='scale_logits') #change logit_scale
    return tf_score_converter_fn(scaled_logits, name='convert_scores')
  score_converter_fn.__name__ = '%s_with_logit_scale' % (
      tf_score_converter_fn.__name__)
  return score_converter_fn

 

 

 

 

 

Q:输出图片失真,偏蓝色

A:opencv的输出imwrite函数参数调整,输出标准RGB格式。

 

保存图片变蓝的请在最后一步的程序里在
plt.imshow(image_np)
前加上
image_np = cv2.cvtColor(image_np, cv2.COLOR_RGB2BGR)

 

 

 

 

 

Q:能否识别中文的标签?

A:没有测试过,可以试试在训练文件里标注中文。

 

 

 

 

Q:训练过程中被打断,报错提示

Invalid GIF data, size 247023

A:GIF 文件过大,不支持格式。(小的GIF是否支持我不清楚,请测试过的读者告知)

 

 

 

 

Q:训练正常,但是效果很差。

A:

1、迭代次数不够,默认设置200000次,在Tensorboard中查看,Loss趋于稳定后差不多可以结束训练;

2、训练数据少,理论上讲,训练、测试数据数量越多、数据质量约好,效果越好;

3、不同模型效果差异,model zoo上训练的模型准确率基于公开数据集,虽然速度快的模型不一定效果差,往往是总体准确率高的模型效果好一些。

4、如果本身你自己的数据集较大,类别数量很多,那么20W次迭代可能还是不够,看整体损失函数的下降情况而定。

 

 

Q: module 'tensorflow.contrib.data' has no attribute 'parallel_interleave'

A: 新旧版本的模块名称不同,升级到最新版Tensorflow可以解决。

 

 

 

Q:csv文件转换为tfrecord文件出错

A:

 

几点需要确认一下:

 

1.      在object_detection.py 程序里,确认 NUM_CLASSES = 你自己的类别数;

2.    确认一下运行时候的路径有没有错(python generate_tfrecord.py --csv_input=data/tv_vehicle_labels.csv  --output_path=train.record)

3.      .config 文件里 num_classes: 你自己的类别数

4.      .pbtxt 文件下 item序号与名称与generate_tfrecord.py 里的序号名称必须一一对应。

 

 

 

 

 

Q: 运行 xml_to_csv.py 时出错,ParseError: not well-formed (invalid token): line 1, column 0

A:

 

 .xml标注文件里含有非法字符,是不是用了一些特殊符号?或者改成英文试试。

 

参考:

https://stackoverflow.com/questions/13046240/parseerror-not-well-formed-invalid-token-using-celementtree/20204635#20204635

 

https://github.com/danifr/rundeck-scripts/issues/5

 

https://stackoverflow.com/questions/13046240/parseerror-not-well-formed-invalid-token-using-celementtree

 

 

Q: 

tensorflow.python.framework.errors_impl.NotFoundError: NewRandomAccessFile failed to Create/Open: /yourpath/....jpg; No such process

A: 各个步骤文件名或者路径的问题,可以先检查一下。

如果不确定,可以把 报错的.jpg 以及对应的 .xml文件打开查看一下,确定.xml里的文件名也是对的,有读者遇到 images6.jpg 无法打开报错,发现images6.xml里的 filename 是 image6 而不是image6.jpg,这可能是标注软件Labellmg的问题。

 

 

Q: can not reshape array of size 345600 into shape (240,360,3)

A: 图片大小或者格式不标准,可以检查一下是不是所有图片都有这个问题

 

 

Q: TypeError: None has type NoneType, but expected one of: int, long

A: 

 

方案1:

class_text_to_int

函数中定义了不同类别返回的数字:

def class_text_to_int(row_label):

    if row_label == 'tv':

        return 1

    else:

        None

 

把else: 后面的 “None” 改成“return 0,即

 

def class_text_to_int(row_label):

    if row_label == 'tv':

        return 1

    else:

        return 0

 

方案2:

部分图片格式问题,转化后再试一试。

 

 

 

Q: TypeError: `pred` must be a Tensor, or a Python bool, or 1 or 0. Found instead: None

A: 

 

change 109 line in ssd_mobilenet_v1_feature_extractor.py:
from

              is_training=None, regularize_depthwise=True)):

to

              is_training=True, regularize_depthwise=True)):

 

 

Q: 开始训练以后显示的loss有两行,

 

INFO tensorflow global step 1 loss=1.1555

INFO tensorflow global step 1 loss=1.1555

INFO tensorflow global step 2 loss=1.1556

INFO tensorflow global step 2 loss=1.1556

 

A: 这个问题不是很清楚,欢迎读者讨论。

 

 

 

Q: 不训练自己的模型,直接调用官方模型,但是只用于识别特定一个或者几个物体可以吗?

A: 

https://github.com/fera0013/TrafficLightDetection/blob/master/Traffic-Light-Detection.ipynb

 

这里有一个只识别交通信号灯的例子,可以看看参考一下。

 

 

 

Q: 按照上述步骤训练后,导出模型测试图片,但输出的图片与原始图片一样,没有进行任何标注,请问可能是哪里出错了?

A:

原因可能又很多: 

1、标签名称是否正确,包括labelimage内部,generate_tfrecord.py 里面 def class_text_to_int(row_label): 这个函数中的设置,以及config文件夹下 .pbtxt 文件。 上述文件中标签的名字及对应序号必须相同。 

2、再次检查文件名称已经文件夹路径是否正确。 

3、Number of classes 是否修改正确。 

4、训练过程是否有异常之处,通过tensorboard可视化查看训练过程。 

5、训练的数据过少也有可能。 

6、试一试其他预先训练好的模型。

 

 

 

Q: 在我进行模型训练的时候出现了以下问题: Instructions for updating: Please switch to tf.train.create_global_step Traceback (most recent call last): 。。。 TypeError: __init__() got an unexpected keyword argument 'dct_method'

A: 

这个应该是由于Tensorflow版本的问题,我的是基于1.4版本,你的应该是1.5版本。 可以在 models/research/object_detection/data_decoders/tf_example_decoder.py 文件的第110行, 删去 “dct_method=dct_method”这一句。 

具体请看下面这个网址: 

https://stackoverflow.com/questions/48920762/tensorflow-error-typeerror-init-got-an-unexpected-keyword-argument-dct

 

 

 

Q: 训练中断,怎样继续进行?

A: 只要training 文件夹下的文件没有动,那么重新输入训练的命令,就会从上次自动保存的断点继续训练。

 

 

 

Q: 运行train.py的时候报错 IndexError: list index out of range 
 

A:直接原因是引用了不存在的编号,可以检查一下训练的文件跟生成的csv表格是不是有不存在的图片名称

 

 

 

Q: 在训练时一直出现ValueError: axis = 0 not in [0, 0),不知道怎么解决,看您视频也出现这个问题,但是没有说解决方案就跳过去了,麻烦您说明一下。
 

A:

在pipeline.config 文件中,找到 loss{}这一类,

loss {
classification_loss {
weighted_sigmoid {
}
}
localization_loss {
weighted_smooth_l1 {
}
}
hard_example_miner {
num_hard_examples: 3000
iou_threshold: 0.99
loss_type: CLASSIFICATION
max_negatives_per_positive: 3
min_negatives_per_image: 0
}
classification_weight: 1.0
localization_weight: 1.0
}

 

改成如下部分:

 

loss {
  classification_loss {
    weighted_sigmoid {
    anchorwise_output: true  #add this
    }
  }
  localization_loss {
    weighted_smooth_l1 {
    anchorwise_output: true  #add this
    }
  }
  hard_example_miner {
    num_hard_examples: 3000
    iou_threshold: 0.99
    loss_type: CLASSIFICATION
    max_negatives_per_positive: 3
    min_negatives_per_image: 0
  }
  classification_weight: 1.0
  localization_weight: 1.0
}

参考:https://github.com/datitran/raccoon_dataset/issues/45

 

 

 

Q: File "C:\ProgramData\anaconda3.1\lib\xml\etree\ElementTree.py", line 597, in parse self._root = parser._parse_whole(source) File "", line unknown ParseError: not well-formed (invalid token): line 1, column 0 请问该如何解决呢

A:

可能在文件中包含了非法字符,可以在检查一下,另外我建议标签用英文。如果还没解决,看一下这个网址的问题:https://stackoverflow.com/questions/13046240/parseerror-not-well-formed-invalid-token-using-celementtree,里面有类似问题的解决方案,把xml_to_csv.py里对应的部分改一下

 

 

 

 

Q: 博主 ssd_mobile这个模型我可以运行的完美 但换成别的模型 如faster_rcnn_inception_resnet_v2_atrous_coco,会出现下面的问题:ValueError: Tried to convert 't' to a tensor and failed. Error: Argument must be a dense tensor: range(0, 3) - got shape [3], but wanted [].有人用别的模型成功过的吗

A:我之前用1.4版本的时候是成功过的。你的问题我谷歌上搜了一下似乎是兼容性的问题,github上有相关的解决方法你可以参考一下:

https://github.com/tensorflow/models/issues/3705#issuecomment-375563179 https://github.com/tensorflow/models/issues/3752

 

 

 

Q: 为什么我的结果没有画框?

 

A: 

来自 @kurumi233

对最后测试没有画框的人,我希望我的回答可以帮到你们,你可以打印一下测试demo代码最后的output_dict,里面有box的坐标还有分数之类的,你看一下分数就知道了,你如果标签之类的没问题的话,肯定分数很低的,可能只有0.0几,然而你可以看下可视化函数,用来画框的那个函数,visualization_utils.py里的visualize_boxes_and_labels_on_image_array,有个参数是min_score_thresh,代表最小的阈值,默认是0.5,也就是分数在50%以上才会画框,你极限一点调成0就可以看到最多20个框了,这个20也是在那边设置的,说了这么多屁话,总结就是,训练样本和次数太少了,导致预测的框的分数低于最低的阈值了,所以不画出来,或者手动降低阈值查看效果,希望我的回答可以帮到你(=・ω・=)(=・ω・=)

 

 

Q: 由于我的图片像素比较高,导致测试时的准确度字体太小,只有20个像素点大小,比如说tv:98%,我应该在哪里修改一下?还有一个问题就是在图片标注的时候,是不是需要尽可能的只把目标物标注出来,其他的干扰尽量避免?
A: 在object_detection/utils文件夹下,找到visualization_utils.py 文件打开, 搜索 font = ImageFont.truetype 这一行,后面的数字“24”就是字体大小,改大一些,保存,关闭所有文件,重新运行程序,应该就可以了,在我的电脑上亲测可行。 

对于第二个问题,我个人认为是的,减少干扰意味这更高质量的训练数据集,应该有利于得到更好的结果

 

 

 

Q: 博主,你好!我做的项目是灰度图(单通道图片)。在最后测试效果时,报错说,要求输入的图片是3通道的,而我输入的是单通道。而且这个参数好像是从训练完后的一个文件中读取的,不知从哪去改,无从下手。博主能指点一下迷途的小白吗。谢谢了!!!!

 

 

A:

你这个问题,直接原因是代码里默认读取的图片是RGB 3通道的,应该把对应的部分改成单通道就可以了。 在object_detection.py 代码里 load_image_into_numpy_array 这个函数作用就是把 image函数转换成numpy矩阵,3通道是3阶,单通道应该就是一阶。你可以上网搜一下numpy怎么读取单通道图片,把这个函数里面的参数改一下应该就可以了,你可以试试!
来自提问者自己的回答:这几天被这个折腾得头疼.... 1.一开始我打算继续用单通道图片一条路走到黑,发现在 export_inferebce_graph.py 这个代码里,我们还可以指定 input_shape 这个命令行参数(博主有空可以了解一下),但在输出 frozen_inference_graph.pb 这个文件时。会报错 左右两个图片的 shape 不一致,查阅网上资料,说是把checkpoints文件删除干净,但我删完了,还是报一样的错,估计是没删完吧,单都不知道这个文件都保存在哪些路径里,头疼..... 2.按照博主提供的思路,我把单通道图片转换成三通道图片,emmmmmm.....一路畅通的做下来,不过结果是瞎**框,损失值有点大.....再瞎**搞一下吧 总之,谢谢博主啦!!!!!

 

 

Q:

如果没改 load_image_into_numpy_array 里的参数,报错是: ValueError: cannot reshape array of size 65536 into shape (256,256,3) 改了之后是: ValueError: Cannot feed value of shape (1, 256, 256, 1) for Tensor 'image_tensor:0', which has shape '(?, ?, ?, 3)' 我找了半天,没找到 image_tensor:0 定义在哪,只找出它是从frozen_inference_graph.pb这个文件里读取,但这个文件我不知道怎么去改里面的参数....

A: 我查了资料,貌似这些 .pb 的model都是适用与RGB格式的,解决方法是把单通道改成3通道。 https://github.com/tensorflow/models/issues/3369 https://github.com/tensorflow/models/issues/2679

 

 

Q: 训练了一些数据后,想额外添加更多数据集,可以吗?

A: 可以的。把添加的数据集另外再生成一个 .record文件,然后修改 .config 文件

 

train_input_reader: {
  tf_record_input_reader {
    input_path: ["path/to/first.record", "path/to/second.record"]
  }
label_map_path: "..."
}

在input_path 里面添加新的 .record 文件即可。

你可能感兴趣的:(深度学习,物体检测,Tensorflow)