在上一篇博客《(更新视频教程)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 文件即可。