// 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;
}
}