- 标题:使用C++预测库对应的Python接口对yolov3物体检测模型预测结果有误,参考接口文档https://paddlepaddle.org.cn/documentation/docs/zh/advanced_usage/deploy/inference/python_infer_cn.html
- 版本、环境信息:
1)PaddlePaddle版本:1.5.2源码编译, -DWITH_GPU=OFF -DON_INFER=ON
2)CPU:Intel(R) Xeon(R) CPU E5-2650 v4 @ 2.20GHz
3)GPU:无
4)系统环境:镜像paddle:1.5.2-gpu-cuda9.0-cudnn7,Python2.7
-预测信息
1)yolov3模型训练方式参考https://github.com/PaddlePaddle/models/tree/develop/PaddleCV/yolov3
2)python API预测代码如下:
import argparse
import numpy as np
import cv2
from paddle.fluid.core import PaddleBuf
from paddle.fluid.core import PaddleDType
from paddle.fluid.core import PaddleTensor
from paddle.fluid.core import AnalysisConfig
from paddle.fluid.core import create_paddle_predictor
def main():
args = parse_args()
# Set config
config = AnalysisConfig(args.prog_file, args.params_file)
config.disable_gpu()
config.set_cpu_math_library_num_threads(10)
config.enable_mkldnn()
# Create PaddlePredictor
predictor = create_paddle_predictor(config)
# Set inputs
inputs = input_gen(args.image_path)
# Infer
outputs = predictor.run(inputs)
# parse outputs
print outputs
output = outputs[0]
print(output.name)
output_data = output.data.float_data()
output = np.array(output_data).reshape((-1, 6))
output = output[np.flip(output[:,1].argsort())]
for box in output[:10, :].tolist():
print box
def input_gen(filename, resize=(800, 800), img_mean=[0.485, 0.456, 0.406], img_std=[0.229, 0.224, 0.225]):
im = cv2.imread(filename).astype('float32')
im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
h, w, _ = im.shape
out_img = cv2.resize(im, resize, interpolation=3)
mean = np.array(img_mean).reshape((1, 1, -1))
std = np.array(img_std).reshape((1, 1, -1))
out_img = (out_img / 255.0 - mean) / std
out_img = out_img.transpose((2, 0, 1))
image = PaddleTensor()
image.name = "image"
image.shape = [1, out_img.shape[0], out_img.shape[1], out_img.shape[2]]
image.dtype = PaddleDType.FLOAT32
image.data = PaddleBuf(
out_img.flatten().astype("float32").tolist())
image_info = PaddleTensor()
image_info.name = "im_shape"
image_info.shape = [1, 2]
image_info.dtype = PaddleDType.INT32
image_info.data = PaddleBuf(
np.array([h, w]).flatten().astype("int32").tolist())
# return [image, ]
return [image, image_info]
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("--model_dir", type=str, help="model dir")
parser.add_argument("--prog_file", type=str, help="program filename")
parser.add_argument("--params_file", type=str, help="parameter filename")
parser.add_argument("--image_path", type=str, help="image path")
return parser.parse_args()
if __name__ == "__main__":
main()
- 问题描述:开始使用fluid.Executor(place).run的方式对训练好的yolov3模型进行预测,时间较长,所以选择使用C预测库对应的Python接口来使用多核进行预测(预测代码如上)。通过可视化和对比两种方式的infer结果,发现第一种方式的结果是正确的,但C预测库的预测结果有些问题(没有错误或者警告日志)。两者的top10结果如下,每行是一个物体检测框[label, score, x1, y1, x2, y2]:
fluid.Executor.run:
C++预测库python API:
对比结果可以发现,两种方式的预测结果中,label, score, y1, y2的结果都是非常接近的,只有x1,x2的结果存在异常。
12条答案
按热度按时间jc3wubiy1#
fluid.io.load_inference_model
加载的该模型吗?r1wp621o2#
问题1. 保存模型是调用的fluid.io.save_inference_model
问题2、fluid.Executor.run是通过fluid.io.load_inference_model加载的模型
l7wslrjt3#
猜测可能是
w
设置的不对,但看代码觉得似乎没啥问题。。。yzuktlbb4#
好像发现问题出在定义im_shape的这段代码
打印结果如下:
在预测的结果中,我也输出了im_shape,得到的结果是[288.0, 0.0]。感觉是预测时截取了image_info.data.int32_data()的前两位,导致width为0,最终预测结果的x1,x2为0和-1。
另外打印image_info.data.int64_data()和image_info.data.float_data()都是 [288L, 384L]。
是我定义的有问题么,还是int32_data()就是这么设计的?
如果预测的输入是int类型的话,貌似也只能这么传,把dtype定义为INT64或者FLOAT32回报错。
s71maibg5#
嗯,应该是这个原因。是Python数据传到C++后端时出了错。这是1.5版本里面的bug,develop里面已经修复,请下载最新的whl:https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/beginners_guide/install/Tables.html#whl-release
测试代码:
image_info.data = PaddleBuf(np.array([h, w]).flatten().astype("int32"))
mqxuamgl6#
用develop分支重新编译paddle以后,确实可以了。
另外,在使用C++预测库对应的Python接口时,遇到两个小问题。
1、之前希望在一个镜像里即支持fluid的GPU和CPU预测,在编译paddle的时候需要把DWITH_GPU设置为ON来支持GPU预测,但是发现这样编的Paddle无法在没有GPU的机器上使用CPU进行预测
2、在一个进程里面,加载完模型可能会占几百兆的内存,然后使用模型预测一张图片时,内存可能会长到几个G,之前跑MaskRCNN时,检测框特别多时甚至占到十几个G,但预测结束后该进程占的内存不会减少,如果把模型封装成服务的话,服务所占的内存可能会占很大,即使是在服务空闲的时候。
kr98yfug7#
可以打开显存或者内存复用试一下:
mzaanser8#
运行时设置
export CUDA_VISIABLE_DEVICES=""
试下?f0brbegy9#
应该是 export CUDA_VISIBLE_DEVICES="" 吧,试了下,是可以的,这个CUDA_VISIABLE_DEVICES不行。谢谢!
eufgjt7s10#
在CPU预测,会报错?
nkkqxpd911#
先确认一下,好像不只是x1、x2有差别。
fluid.Executor.run结果的第2条,是C++预测Python API结果的第3条。后面几条数据都不一样啊?
wgx48brx12#
在fluid.Executor.run的正常结果中,应该是被NMS过滤掉了。可以对比一下C预测的第1条和第2条的y1,y2,数值比较接近,但x1和x2的结果存在问题,所以没有被过滤掉,C预测的第4条和第5条数据,以及后面的结果也是类似的情况