// Tencent is pleased to support the open source community by making ncnn available. // // Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved. // // Licensed under the BSD 3-Clause License (the "License"); you may not use this file except // in compliance with the License. You may obtain a copy of the License at // // https://opensource.org/licenses/BSD-3-Clause // // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. #include #include #include #include #include #include #include #include #include #include #include #include "graph.pb.h" static bool read_proto_from_binary(const char* filepath, google::protobuf::Message* message) { std::ifstream fs(filepath, std::ifstream::in | std::ifstream::binary); if (!fs.is_open()) { fprintf(stderr, "open failed %s\n", filepath); return false; } google::protobuf::io::IstreamInputStream input(&fs); google::protobuf::io::CodedInputStream codedstr(&input); codedstr.SetTotalBytesLimit(INT_MAX, INT_MAX / 2); bool success = message->ParseFromCodedStream(&codedstr); fs.close(); return success; } static const tensorflow::TensorProto& find_tensor_proto(const std::map& weights, const tensorflow::NodeDef& node) { for (int j=0; j::const_iterator it = weights.find(input_name); if (it != weights.end()) { const tensorflow::TensorProto& tensor = it->second; return tensor; } } static tensorflow::TensorProto null_tensor = tensorflow::TensorProto(); return null_tensor; } int main(int argc, char** argv) { const char* tensorflowpb = argv[1]; const char* ncnn_prototxt = argc >= 4 ? argv[2] : "ncnn.proto"; const char* ncnn_modelbin = argc >= 4 ? argv[3] : "ncnn.bin"; tensorflow::GraphDef graph; // load bool s1 = read_proto_from_binary(tensorflowpb, &graph); if (!s1) { fprintf(stderr, "read_proto_from_binary failed\n"); return -1; } FILE* pp = stderr;//fopen(ncnn_prototxt, "wb"); FILE* bp = stderr;//fopen(ncnn_modelbin, "wb"); int node_count = graph.node_size(); // fprintf(stderr, "node_count = %d\n\n", node_count); // node reference std::map node_reference; // mapping for Const and Const-Identity std::map weights; // global definition line // [layer count] [blob count] std::set blob_names; for (int i=0; i& attr = node.attr(); const google::protobuf::Map::const_iterator it = attr.find("value"); if (it != attr.end()) { const tensorflow::TensorProto& tensor = it->second.tensor(); weights[output_name] = tensor; } continue; } else if (node.op() == "Identity") { const std::string& input_name = node.input(0); weights[output_name] = weights[input_name]; continue; } else if (node.op() == "NoOp") { weights[output_name] = tensorflow::TensorProto(); continue; } // input for (int j=0; j::iterator it = node_reference.begin(); while (it != node_reference.end()) { if (it->second == 1) { node_reference.erase(it++); } else { splitncnn_blob_count += it->second; // fprintf(stderr, "%s %d\n", it->first.c_str(), it->second); ++it; } } fprintf(pp, "%lu %lu\n", node_count + node_reference.size() - weights.size(), blob_names.size() + splitncnn_blob_count); int internal_split = 0; for (int i=0; i(tensor.tensor_content().c_str()); int size = tensor.tensor_content().size() / sizeof(float); fprintf(stderr, " size = %d\n", size); break; } case 3: // int32 { const int *data = reinterpret_cast(tensor.tensor_content().c_str()); int size = tensor.tensor_content().size() / sizeof(int); fprintf(stderr, " size = %d\n", size); break; } default: fprintf(stderr, "Tensor type is not supported\n"); break; } } } else if (node.op() == "Identity") { } else if (node.op() == "MatMul") { // weights const tensorflow::TensorProto& tensor = find_tensor_proto(weights, node); fprintf(stderr, "[ "); const tensorflow::TensorShapeProto& shape = tensor.tensor_shape(); for (int d = 0; d(tensor.tensor_content().c_str()); int size = tensor.tensor_content().size() / sizeof(float); fprintf(stderr, " size = %d\n", size); break; } case 3: // int32 { const int *data = reinterpret_cast(tensor.tensor_content().c_str()); int size = tensor.tensor_content().size() / sizeof(int); fprintf(stderr, " size = %d\n", size); break; } default: fprintf(stderr, "Tensor type is not supported\n"); break; } } } else if (node.op() == "Max") { } else if (node.op() == "MaxPool") { } else if (node.op() == "Mul") { } else if (node.op() == "NoOp") { } else if (node.op() == "Placeholder") { } else if (node.op() == "Relu") { } else { const google::protobuf::Map& attr = node.attr(); google::protobuf::Map::const_iterator it = attr.begin(); for (; it != attr.end(); it++) { std::cerr << it->first << std::endl; std::cerr << it->second.type() << std::endl; } } std::string output_name = node.name(); if (node_reference.find(output_name) != node_reference.end()) { int refcount = node_reference[output_name]; if (refcount > 1) { char splitname[256]; sprintf(splitname, "splitncnn_%d", internal_split); fprintf(pp, "%-16s %-16s %d %d", "Split", splitname, 1, refcount); fprintf(pp, " %s", output_name.c_str()); for (int j=0; j