tensorflow1.8 c++ロードトレーニング済みモデルピット
6142 ワード
tensorflow c++の下で訓練した図とcheckpointをロードするコードは:
tensorflow 1.2上記のコードは正常に動作していますが、動作の必要性からtensorflowを最近1.8.0にアップグレードし、lib、dllを再コンパイルした後、上記のコードを実行すると、次の2つのリンクバグが発生しました.
error LNK 2001:解析できない外部シンボル「class tensorflow::GraphDefaultTypeInternal tensorflow:_GraphDef_default_instance_」(?_GraphDef_default_instance_@tensorflow@@3VGraphDefDefaultTypeInternal@1@A)
main.obj:error LNK 2001:解析できない外部シンボル「class tensorflow::S a v e r D e f D e f A r t y peInternal tensorflow:_SaverDef_default_instance_」(?_SaverDef_default_instance_@tensorflow@@3VSaverDefDefaultTypeInternal@1@A)
いろいろな方法で振り回した後、解決策を見つけました.修正したコードは:
別の変換方法の階調図:
別の変換方式のRGB画像:
残された問題:
metaとckptを凍結する得ることができる.pbファイルですが、自分で凍結したモデルの実行結果と元のmeta、ckptの実行結果が一致しません.図面を凍結したときにパラメータの設定が不合理な可能性があります.この問題は後で解決します.
しばらく記録して、後で詳しく整理する時間があって、もし間違いがあれば、批判の指摘を歓迎します.
const std::string pathToGraph = "./model/model.ckpt-29520.meta";
const std::string checkpointPath = "./model/model.ckpt-29520";
//gpu option
tf::SessionOptions session_options;
session_options.config.mutable_gpu_options()->set_allow_growth(true);
tf::Session* m_sessionFaceNet = NewSession(session_options);
// Read in the protobuf graph we exported
tf::MetaGraphDef graph_def;
tf::Status m_statusFaceNet = ReadBinaryProto(tf::Env::Default(), pathToGraph, &graph_def);
if (!m_statusFaceNet.ok())
{
//throw std::runtime_error("Error reading graph definition from " + pathToGraph + ": " + m_statusFaceNet.ToString());
return 0;
}
// Add the graph to the session
m_statusFaceNet = m_sessionFaceNet->Create(graph_def.graph_def());
// Read weights from the saved checkpoint
tf::Tensor checkpointPathTensor(tf::DT_STRING, tf::TensorShape());
checkpointPathTensor.scalar<:string>()() = checkpointPath;
m_statusFaceNet = m_sessionFaceNet->Run(
{ { graph_def.saver_def().filename_tensor_name(), checkpointPathTensor }, },
{},
{ graph_def.saver_def().restore_op_name() },
nullptr);
tensorflow 1.2上記のコードは正常に動作していますが、動作の必要性からtensorflowを最近1.8.0にアップグレードし、lib、dllを再コンパイルした後、上記のコードを実行すると、次の2つのリンクバグが発生しました.
error LNK 2001:解析できない外部シンボル「class tensorflow::GraphDefaultTypeInternal tensorflow:_GraphDef_default_instance_」(?_GraphDef_default_instance_@tensorflow@@3VGraphDefDefaultTypeInternal@1@A)
main.obj:error LNK 2001:解析できない外部シンボル「class tensorflow::S a v e r D e f D e f A r t y peInternal tensorflow:_SaverDef_default_instance_」(?_SaverDef_default_instance_@tensorflow@@3VSaverDefDefaultTypeInternal@1@A)
いろいろな方法で振り回した後、解決策を見つけました.修正したコードは:
const std::string pathToGraph = "./model/model.ckpt-29520.meta";
const std::string checkpointPath = "./model/model.ckpt-29520";
//gpu option
tf::SessionOptions session_options;
session_options.config.mutable_gpu_options()->set_allow_growth(true);
/*std::unique_ptr<:session> m_sessionFaceNet;
Status load_graph_status = LoadGraph(pathToFrozen, &m_sessionFaceNet);
tf::Status m_statusFaceNet;*/
tf::Session* m_sessionFaceNet = NewSession(session_options);
// Read in the protobuf graph we exported
tf::MetaGraphDef graph_def;
tf::Status m_statusFaceNet = ReadBinaryProto(tf::Env::Default(), pathToGraph, &graph_def);
if (!m_statusFaceNet.ok())
{
//throw std::runtime_error("Error reading graph definition from " + pathToGraph + ": " + m_statusFaceNet.ToString());
return 0;
}
// Add the graph to the session
m_statusFaceNet = m_sessionFaceNet->Create(*(graph_def.mutable_graph_def()));
// Read weights from the saved checkpoint
tf::Tensor checkpointPathTensor(tf::DT_STRING, tf::TensorShape());
checkpointPathTensor.scalar<:string>()() = checkpointPath;
m_statusFaceNet = m_sessionFaceNet->Run(
{ { graph_def.mutable_saver_def()->filename_tensor_name(), checkpointPathTensor }, },
{},
{ graph_def.mutable_saver_def()->restore_op_name() },
nullptr);
{ graph_def.mutable_saver_def()->filename_tensor_name(), checkpointPathTensor }, },
{},
{ graph_def.mutable_saver_def()->restore_op_name() },
nullptr);
主要的修改是修改了graph_def函数为mutable_graph_def(),修改saver_def()为mutable_saver_def()。误打误撞解决了问题,原理不理解,后续有时间还要分析tensorflow底层函数。
另一个要注意的问题是:
cv::Mat转换为tensorflow::Tensor时,要注意转换的数据格式和模型要求的数据格式一致。
两种转换方式:
tf::Tensor input_tensor(tf::DT_FLOAT, tf::TensorShape({ nPersonNum,112,112,1}));
cv::Mat flaotMat;
resizeImg.convertTo(flaotMat, CV_32FC1);
tf::StringPiece tmp_data = input_tensor.tensor_data();
memcpy(const_cast(tmp_data.data()), (flaotMat.data), flaotMat.rows * flaotMat.cols * sizeof(tf::DT_FLOAT));
別の変換方法の階調図:
// , 32F
resizeImg.convertTo(flaotMat, CV_32FC1);
for (int nTensor = 0; nTensor < nPersonNum; nTensor++)
{
const float * source_data = (float*)tmpVecWhitenImages[nTensor].data;
for (int y = 0; y < tmpVecWhitenImages[nTensor].rows; ++y)
{
const float* source_row = source_data + (y * tmpVecWhitenImages[nTensor].cols);
for (int x = 0; x < tmpVecWhitenImages[nTensor].cols; ++x)
{
const float* source_pixel = source_row + x;
for (int c = 0; c < 1; ++c)
{
const float* source_value = source_pixel;
input_tensor_mapped(nTensor, y, x, c) = *source_value;
}
}
}
}
別の変換方式のRGB画像:
// , 64F
matImgByTF.convertTo(Image2, CV_64FC3);
tf::Tensor input_tensor(tf::DT_FLOAT, tf::TensorShape({ nPersonNum,m_pFaceDescriber->m_nFaceImgWidth,m_pFaceDescriber->m_nFaceImgHeight,m_pFaceDescriber->m_nFaceImgDepth }));
auto input_tensor_mapped = input_tensor.tensor();
//double*
for (int nTensor = 0; nTensor < nPersonNum; nTensor++)
{
const double * source_data = (double*)tmpVecWhitenImages[nTensor].data;
for (int y = 0; y < tmpVecWhitenImages[nTensor].rows; ++y)
{
const double* source_row = source_data + (y * tmpVecWhitenImages[nTensor].cols * m_pFaceDescriber->m_nFaceImgDepth);
for (int x = 0; x < tmpVecWhitenImages[nTensor].cols; ++x)
{
const double* source_pixel = source_row + (x * m_pFaceDescriber->m_nFaceImgDepth);
for (int c = 0; c < m_pFaceDescriber->m_nFaceImgDepth; ++c)
{
const double* source_value = source_pixel + (2 - c);//RGB->BGR
input_tensor_mapped(nTensor, y, x, c) = *source_value;
}
}
}
}
残された問題:
metaとckptを凍結する得ることができる.pbファイルですが、自分で凍結したモデルの実行結果と元のmeta、ckptの実行結果が一致しません.図面を凍結したときにパラメータの設定が不合理な可能性があります.この問題は後で解決します.
しばらく記録して、後で詳しく整理する時間があって、もし間違いがあれば、批判の指摘を歓迎します.