14 #include "tensorflow/cc/saved_model/loader.h" 15 #include "tensorflow/cc/saved_model/tag_constants.h" 16 #include "tensorflow/core/platform/env.h" 18 #include "tensorflow/core/public/session_options.h" 22 const std::vector<std::string>& outputs,
35 tensorflow::SessionOptions options;
36 tensorflow::ConfigProto& config = options.config;
37 config.set_inter_op_parallelism_threads(1);
38 config.set_intra_op_parallelism_threads(1);
39 config.set_use_per_session_threads(
false);
41 auto status = tensorflow::NewSession(options, &
fSession);
43 std::cout << status.ToString() << std::endl;
49 fBundle =
new tensorflow::SavedModelBundle();
50 status = tensorflow::LoadSavedModel(tensorflow::SessionOptions(),
51 tensorflow::RunOptions(),
53 {tensorflow::kSavedModelTagServe},
55 std::cout <<
"tf_graph loaded SavedModelBundle with status: " << status.ToString() << std::endl;
56 if (!status.ok())
return;
58 auto sig_map =
fBundle->meta_graph_def.signature_def();
59 std::string sig_def =
"serving_default";
60 bool has_default_key =
false;
61 std::vector<std::string> sig_map_keys;
62 for (
auto const& p : sig_map) {
63 if (p.first == sig_def) has_default_key =
true;
64 sig_map_keys.push_back(p.first);
66 auto model_def = sig_map.at((has_default_key) ? sig_def : sig_map_keys.back());
69 std::cout <<
"tf_graph inputs:" << std::endl;
70 for (
auto const& p : model_def.inputs()) {
72 std::cout <<
"tf_graph InputName: " <<
fInputNames.back() << std::endl;
73 std::cout <<
" key: " << p.first <<
" value: " << p.second.name() << std::endl;
78 if (outputs.empty()) {
79 std::cout <<
"tf_graph using all outputs:" << std::endl;
80 for (
auto const& p : model_def.outputs()) {
82 std::cout <<
" key: " << p.first <<
" value: " << p.second.name() << std::endl;
87 std::cout <<
"tf_graph using selected outputs:" << std::endl;
88 for (
const auto& s : outputs) {
89 for (
auto const& p : model_def.outputs()) {
92 std::cout <<
" key: " << p.first <<
" value: " << p.second.name() << std::endl;
98 std::cout <<
"tf_graph did not find outputs in SaveModelBundle." << std::endl;
104 tensorflow::GraphDef graph_def;
106 std::cout <<
"tf_graph loaded ProtoBuf graph with status: " << status.ToString() << std::endl;
107 if (!status.ok())
return;
109 size_t ng = graph_def.node().size();
110 for (
int i = 0; i <
n_inputs; ++i) {
115 if (outputs.empty()) {
117 fOutputNames.push_back(graph_def.node()[ng - i].name());
122 std::string last, current, basename, name;
123 for (
size_t n = 0;
n < ng; ++
n) {
124 name = graph_def.node()[
n].name();
125 auto pos = name.find(
"/");
126 if (pos != std::string::npos) { basename = name.substr(0, pos); }
132 for (
const auto& s : outputs) {
133 if (name.find(s) != std::string::npos) {
139 if (!last.empty() && (basename != current)) {
fOutputNames.push_back(last); }
147 std::cout <<
"Output nodes not found in the graph." << std::endl;
150 status =
fSession->Create(graph_def);
152 std::cout << status.ToString() << std::endl;
170 if (
x.empty() ||
x.front().empty()) {
return std::vector<std::vector<float>>(); }
172 long long int rows =
x.size(), cols =
x.front().size();
174 std::vector<tensorflow::Tensor> _x;
176 tensorflow::Tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({1, rows, cols, 1})));
177 auto input_map = _x[0].tensor<float, 4>();
179 for (
long long int r = 0;
r < rows; ++
r) {
180 const auto& row =
x[
r];
181 for (
long long int c = 0; c < cols; ++c) {
182 input_map(0,
r, c, 0) = row[c];
186 auto result =
run(_x);
187 if (!result.empty()) {
return result.front(); }
189 return std::vector<std::vector<float>>();
196 long long int samples)
198 if ((samples == 0) ||
x.empty() ||
x.front().empty() ||
x.front().front().empty() ||
199 x.front().front().front().empty())
202 if ((samples == -1) || (samples > (
long long int)
x.size())) { samples =
x.size(); }
204 long long int rows =
x.front().size(), cols =
x.front().front().size(),
205 depth =
x.front().front().front().size();
207 std::vector<tensorflow::Tensor> _x;
211 _x.push_back(tensorflow::Tensor(tensorflow::DT_FLOAT,
212 tensorflow::TensorShape({samples, rows, cols, depth})));
213 auto input_map = _x[0].tensor<float, 4>();
214 for (
long long int s = 0; s < samples; ++s) {
215 const auto& sample =
x[s];
216 for (
long long int r = 0;
r < rows; ++
r) {
217 const auto& row = sample[
r];
218 for (
long long int c = 0; c < cols; ++c) {
219 const auto&
col = row[c];
220 for (
long long int d = 0;
d < depth; ++
d) {
221 input_map(s,
r, c,
d) =
col[
d];
229 for (
int i = 0; i < depth; ++i) {
230 _x.push_back(tensorflow::Tensor(tensorflow::DT_FLOAT,
231 tensorflow::TensorShape({samples, rows, cols, 1})));
234 for (
int view = 0; view < depth; ++view) {
235 auto input_map = _x[view].tensor<float, 4>();
236 for (
long long int s = 0; s < samples; ++s) {
237 const auto& sample =
x[s];
238 for (
long long int r = 0;
r < rows; ++
r) {
239 const auto& row = sample[
r];
240 for (
long long int c = 0; c < cols; ++c) {
241 const auto&
col = row[c];
242 long long int d = view;
243 input_map(s,
r, c, 0) =
col[
d];
256 const std::vector<tensorflow::Tensor>&
x)
258 std::vector<std::pair<std::string, tensorflow::Tensor>> inputs;
259 for (
int i = 0; i <
n_inputs; ++i) {
263 std::vector<tensorflow::Tensor> outputs;
264 std::vector<std::string> outputNames;
272 for (
size_t o = 0; o < outputs.size(); ++o) {
273 if (o == 0) { samples = outputs[o].dim_size(0); }
274 else if ((
int)samples != outputs[o].dim_size(0)) {
275 throw std::string(
"TF outputs size inconsistent.");
279 std::vector<std::vector<std::vector<float>>> result;
280 result.resize(samples,
std::vector<std::vector<float>>(outputs.size()));
282 for (
size_t s = 0; s < samples; ++s) {
283 for (
size_t o = 0; o < outputs.size(); ++o) {
284 size_t n = outputs[o].dim_size(1);
285 auto output_map = outputs[o].tensor<float, 2>();
287 result[s][o].resize(outputs[o].dim_size(1));
289 std::vector<float>& vs = result[s][o];
290 for (
size_t i = 0; i <
n; ++i) {
291 vs[i] = output_map(s, i);
299 std::cout << status.ToString() << std::endl;
300 return std::vector<std::vector<std::vector<float>>>();
307 std::vector<std::pair<std::string, tensorflow::Tensor>> inputs;
308 for (
int i = 0; i <
n_inputs; ++i) {
312 std::vector<tensorflow::Tensor> outputs;
313 std::vector<std::string> outputNames;
319 size_t samples = 0, nouts = 0;
321 for (
size_t o = 0; o < outputs.size(); ++o) {
322 if (o == 0) { samples = outputs[o].dim_size(0); }
323 else if ((
int)samples != outputs[o].dim_size(0)) {
324 throw std::string(
"TF outputs size inconsistent.");
326 nouts += outputs[o].dim_size(1);
329 std::vector<std::vector<float>> result;
330 result.resize(samples, std::vector<float>(nouts));
333 for (
size_t o = 0; o < outputs.size(); ++o) {
334 auto output_map = outputs[o].tensor<float, 2>();
336 size_t n = outputs[o].dim_size(1);
337 for (
size_t s = 0; s < samples; ++s) {
338 std::vector<float>& vs = result[s];
339 for (
size_t i = 0; i <
n; ++i) {
340 vs[idx0 + i] = output_map(s, i);
349 std::cout << status.ToString() << std::endl;
350 return std::vector<std::vector<float>>();
357 std::vector<std::pair<std::string, tensorflow::Tensor>> inputs;
358 for (
int i = 0; i <
n_inputs; ++i) {
362 std::vector<tensorflow::Tensor> outputs;
363 std::vector<std::string> outputNames;
369 size_t samples = 0, npoints = 0;
371 if (outputs.size() > 1) {
throw std::string(
"TF runae: detected more than one output."); }
373 samples = outputs[0].dim_size(0);
374 npoints = outputs[0].dim_size(1);
376 std::vector<std::vector<float>> result;
377 result.resize(samples, std::vector<float>(npoints));
379 auto output_map = outputs[0].tensor<float, 3>();
381 for (
size_t s = 0; s < samples; ++s) {
382 std::vector<float>& vs = result[s];
383 for (
size_t i = 0; i < npoints; ++i) {
384 vs[i] = output_map(s, i, 0);
391 std::cout << status.ToString() << std::endl;
392 return std::vector<std::vector<float>>();
std::vector< std::string > fOutputNames
std::vector< std::vector< float > > runx(const std::vector< tensorflow::Tensor > &x)
Graph(const char *graph_file_name, const std::vector< std::string > &outputs, bool &success, bool use_bundle=false, int ninputs=1, int noutputs=1)
Not-throwing constructor.
tensorflow::SavedModelBundle * fBundle
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
std::vector< std::vector< float > > runae(const std::vector< tensorflow::Tensor > &x)
tensorflow::Session * fSession
std::vector< std::vector< float > > run(const std::vector< std::vector< float >> &x)
std::vector< std::string > fInputNames