MXNet Forum

C++ predict out data show -nan(ind)


#1

code:
https://pan.baidu.com/s/1Kdc50UKj9Aq10I-HGQkUCQ
pictrue:


I use C++ to load the python training model,and predict result. This file is modified by me through official documents.The arrow is show out result is -nan(ind). I checked the data of the input image.This image data is in the range of 0 to 255. So I don’t know what’s wrong.


#2

// ConsoleApplicationMxnet.cpp : 此文件包含 “main” 函数。程序执行将在此处开始并结束。
#include “pch.h”

#include “mxnet-cpp/MxNetCpp.h”
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include <opencv2/opencv.hpp>
#include"mxnet/c_predict_api.h"

using namespace cv;

// Read file to buffer
class BufferFile {
public:
std::string file_path_;
std::size_t length_ = 0;
std::unique_ptr<char> buffer_;

//explicit 防止隐式转换 :小范围类型数据转大范围数据
explicit BufferFile(const std::string& file_path)
	: file_path_(file_path) {

	std::ifstream ifs(file_path.c_str(), std::ios::in | std::ios::binary);

	if (!ifs) {
		std::cerr << "Can't open the file. Please check " << file_path << ". \n";
		return;
	}

	ifs.seekg(0, std::ios::end);
	length_ = static_cast<std::size_t>(ifs.tellg());
	ifs.seekg(0, std::ios::beg);
	std::cout << file_path.c_str() << " ... " << length_ << " bytes\n";

	buffer_.reset(new char[length_]);
	ifs.read(buffer_.get(), length_);
	ifs.close();
}

std::size_t GetLength() {
	return length_;
}

char* GetBuffer() {
	return buffer_.get();
}

};

enum NET_RET_CODE//返回码
{
NET_RET_CODE_INIT = 0,//初始化
NET_RET_CODE_READ_PARAMS_FAILD,//读取网络结构以及参数失败
NET_RET_CODE_CREATE_PREDICTOR_FAILD,//创建预测器失败
NET_RET_CODE_CV_READ_EMPTY,//读取空图像
NET_RET_CODE_MXNET_IMPORT_DATA_FAILD,//将图像信息导入MXNET中预测
NET_RET_CODE_NET_FORWARD_FAILD,//网络前向传播失败
NET_RET_CODE_NET_OUT_RESULT_FAILD,//网络输出节点的形状失败
NET_RET_CODE_NET_PRED_OUT_FAILD,//网络预测结果失败
NET_RET_CODE_NET_PRED_REALSE,//是否预测器失败
NET_RET_CODE_TOTAL
};

void GetImageFile(const std::string& image_file,
mx_float* image_data, int channels)
{
// Read all kinds of file into a BGR color 3 channels image
Mat p_mSrcImage = imread(image_file, IMREAD_COLOR);

if (p_mSrcImage.empty()) {
	std::cerr << "Can't open the image. Please check " << image_file << ". \n";
	assert(false);
}

int size = p_mSrcImage.rows * p_mSrcImage.cols * channels;

mx_float* ptr_image_r = image_data;
mx_float* ptr_image_g = image_data + size / 3;
mx_float* ptr_image_b = image_data + size / 3 * 2;

for (int i = 0; i < p_mSrcImage.rows; i++) 
{
	auto data = p_mSrcImage.ptr<uchar>(i);
	for (int j = 0; j < p_mSrcImage.cols; j++) 
	{
		if (channels > 1) {
			*ptr_image_b++ = static_cast<mx_float>(*data++);
			*ptr_image_g++ = static_cast<mx_float>(*data++);
		}
		*ptr_image_r++ = static_cast<mx_float>(*data++);
	}
}

}
int main(int argc, char *argv)
{

// model file path
std::string json_file = "model/save-symbol.json";
std::string param_file = "model/save-0010.params";

// read model file
BufferFile json_data(json_file);
BufferFile param_data(param_file);

// Parameters
int dev_type = 1;  // 1: cpu, 2: gpu
int dev_id = 0;  // arbitrary.
mx_uint num_input_nodes = 1;  // 1 for feedforward
const char* input_key[1] = { "data" };
const char** input_keys = input_key;

//输入网络的图像尺寸以及通道
int width = 273;
int height = 273;
int channels = 3;

const mx_uint input_shape_indptr[2] = { 0, 4 };
const mx_uint input_shape_data[4] = { 1,
									  static_cast<mx_uint>(channels),
									  static_cast<mx_uint>(height),
									  static_cast<mx_uint>(width) };

if (json_data.GetLength() == 0 || param_data.GetLength() == 0)
{
	return NET_RET_CODE_READ_PARAMS_FAILD;
}

//预测器句柄
PredictorHandle pred_hnd = nullptr;

//创建预测器
if (MXPredCreate(static_cast<const char*>(json_data.GetBuffer()),
	static_cast<const char*>(param_data.GetBuffer()),
	static_cast<int>(param_data.GetLength()),
	dev_type,
	dev_id,
	num_input_nodes,
	input_keys,
	input_shape_indptr,
	input_shape_data,
	&pred_hnd) != 0)
{
	return NET_RET_CODE_CREATE_PREDICTOR_FAILD;
}

if (!pred_hnd)
{
	std::cerr << "Failed to create predict handler" << std::endl;
	return NET_RET_CODE_CREATE_PREDICTOR_FAILD;
}
//读取一张图像
Mat p_mSrcImage = imread("img1.png", IMREAD_COLOR);
//判断图像是否为空
if (p_mSrcImage.empty())
	return NET_RET_CODE_CV_READ_EMPTY;
//显示图像
//imshow("原图", p_mSrcImage);
//waitKey让图像显示
//waitKey(0);
//创建变更图像大小的mat
Mat p_mChangeSizeImage;
//调整图像大小
resize(p_mSrcImage, p_mChangeSizeImage, cv::Size(width, height));
//获取一共的size
int p_iSize = p_mChangeSizeImage.rows*p_mChangeSizeImage.cols*channels;
// Read Image Data
auto image_size = static_cast<std::size_t>(width * height * channels);
std::vector<mx_float> image_data(image_size);
//获取图像RGB三个通道的地址
mx_float* p_mfpImageR = image_data.data();
mx_float* p_mfpImageG = image_data.data() + p_iSize / 3;
mx_float* p_mfpImageB = image_data.data() + p_iSize / 3 * 2;
//三个通道均值
float p_fMeanR, p_fMeanG, p_fMeanB;
p_fMeanR = p_fMeanG = p_fMeanB = 0.0;

//opencv存储图像格式为 BGR
//获取调整大小后的图像数据
int iRDex = 0;
int iGDex = p_iSize / 3;
int iBDex = p_iSize / 3 * 2;
for (int i = 0; i < p_mSrcImage.rows; i++)
{
	auto data = p_mSrcImage.ptr<uchar>(i);
	for (int j = 0; j < p_mSrcImage.cols; j++)
	{
		//将三个通道数据存储起来 static_cast < type-id > ( expression )
		//expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性
		image_data[iBDex] = static_cast<mx_float>(*data++) -p_fMeanB;
		image_data[iGDex] = static_cast<mx_float>(*data++) -p_fMeanG;
		image_data[iRDex] = static_cast<mx_float>(*data++) -p_fMeanR;
		image_data[iBDex] = image_data[iBDex]/255;
		image_data[iGDex] = image_data[iGDex] / 255;
		image_data[iRDex] = image_data[iRDex] / 255;
		/*
		if (image_data[iBDex] > 30)
			image_data[iBDex] = 1;
		else 
			image_data[iBDex] = 0;
		if (image_data[iGDex] > 30)
			image_data[iGDex] = 1;
		else
			image_data[iGDex] = 0;
		if (image_data[iRDex] > 30)
			image_data[iRDex] = 1;
		else
			image_data[iRDex] = 0;
		*/
		iRDex++;
		iGDex++;
		iBDex++;
	}
}


std::cout << "Start" << std::endl;
for(int i=0;i< image_data.size();i++)
	if(image_data[i]<0 || image_data[i] > 255)
		std::cout << "image_data[0]: " << image_data[i] << std::endl;


//将图像导入到MXNET中
if (MXPredSetInput(pred_hnd, "data", image_data.data(), image_data.size()) != 0)
{
	return NET_RET_CODE_MXNET_IMPORT_DATA_FAILD;
}

//网络向前传播
if (MXPredForward(pred_hnd) != 0)
{
	return NET_RET_CODE_NET_FORWARD_FAILD;
}

mx_uint output_index = 0;
mx_uint* shape = nullptr;
mx_uint shape_len;

//获取网络输出节点的形状
if (MXPredGetOutputShape(pred_hnd, output_index, &shape, &shape_len) != 0)
{
	return NET_RET_CODE_NET_OUT_RESULT_FAILD;
}

std::size_t size = 1;
for (mx_uint i = 0; i < shape_len; ++i) 
{
	size *= shape[i]; 
}
//根据尺寸重构输出 2*273*273
std::vector<float> output_data(size);
if (MXPredGetOutput(pred_hnd, output_index, &(output_data[0]), static_cast<mx_uint>(size)) != 0)
{
	return NET_RET_CODE_NET_PRED_OUT_FAILD;//网络预测结果失败
}
//释放预测器资源
if (MXPredFree(pred_hnd) != 0)
{
	return NET_RET_CODE_NET_PRED_REALSE;//是否预测器失败
}
// print output data
std::cout << "Out Net Data: " << std::endl;
for (int i = 0; i < output_data.size(); i++)
{
	std::cout << output_data[i] << std::endl;
}

}


#3

The problem was solved,mxnet export model file and params file exist bug.I very want to cry:sob:.


#4

Thanks for following up @DarkWings, what was the bug with the model file and params?


#5

json file has a lot of duplicate names, so just change them and make them unique