mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Allow protobuffer message to be compiled with LITE_RUNTIME
When adding "option optimize_for = LITE_RUNTIME;" to proto messages, they are compiled as lighter MessageLite (the base class of Message). Those lighter messages do not allow for reflection though: https://developers.google.com/protocol-buffers/docs/reference/cpp-generated This fixes https://github.com/opencv/opencv/issues/20275
This commit is contained in:
@@ -46,6 +46,7 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <google/protobuf/message.h>
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <google/protobuf/io/zero_copy_stream_impl.h>
|
||||
@@ -203,7 +204,9 @@ public:
|
||||
return (str.size() >= _param.size()) && str.compare(str.size() - _param.size(), _param.size(), _param) == 0;
|
||||
}
|
||||
|
||||
void extractLayerParams(const Message &msg, cv::dnn::LayerParams ¶ms, bool isInternal = false)
|
||||
template<class MSG>
|
||||
typename std::enable_if<std::is_base_of<Message, MSG>::value, void>::type
|
||||
extractLayerParams(const MSG &msg, cv::dnn::LayerParams ¶ms, bool isInternal = false)
|
||||
{
|
||||
const Descriptor *msgDesc = msg.GetDescriptor();
|
||||
const Reflection *msgRefl = msg.GetReflection();
|
||||
@@ -238,6 +241,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template<class MSG>
|
||||
typename std::enable_if<!std::is_base_of<Message, MSG>::value, void>::type
|
||||
extractLayerParams(const MSG &msg, cv::dnn::LayerParams ¶ms, bool isInternal = false)
|
||||
{
|
||||
CV_Error(Error::StsError, "DNN/CAFFE: do not have your message be a MessageLite");
|
||||
}
|
||||
|
||||
void blobShapeFromProto(const caffe::BlobProto &pbBlob, MatShape& shape)
|
||||
{
|
||||
shape.clear();
|
||||
@@ -256,6 +266,18 @@ public:
|
||||
shape.resize(1, 1); // Is a scalar.
|
||||
}
|
||||
|
||||
template<class BLOB_PROTO>
|
||||
typename std::enable_if<std::is_base_of<Message, BLOB_PROTO>::value, void>::type
|
||||
AssertBlobProtoIsFloat(const BLOB_PROTO &pbBlob) {
|
||||
CV_DbgAssert(pbBlob.GetDescriptor()->FindFieldByLowercaseName("data")->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT);
|
||||
}
|
||||
|
||||
template<class BLOB_PROTO>
|
||||
typename std::enable_if<!std::is_base_of<Message, BLOB_PROTO>::value, void>::type
|
||||
AssertBlobProtoIsFloat(const BLOB_PROTO &pbBlob) {
|
||||
CV_Error(Error::StsError, "DNN/CAFFE: do not have your message be a MessageLite");
|
||||
}
|
||||
|
||||
void blobFromProto(const caffe::BlobProto &pbBlob, cv::Mat &dstBlob)
|
||||
{
|
||||
MatShape shape;
|
||||
@@ -267,7 +289,7 @@ public:
|
||||
// Single precision floats.
|
||||
CV_Assert(pbBlob.data_size() == (int)dstBlob.total());
|
||||
|
||||
CV_DbgAssert(pbBlob.GetDescriptor()->FindFieldByLowercaseName("data")->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT);
|
||||
AssertBlobProtoIsFloat(pbBlob);
|
||||
Mat(dstBlob.dims, &dstBlob.size[0], CV_32F, (void*)pbBlob.data().data()).copyTo(dstBlob);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <type_traits>
|
||||
|
||||
#include "caffe_io.hpp"
|
||||
#include "glog_emulator.hpp"
|
||||
@@ -1110,7 +1111,7 @@ const char* UpgradeV1LayerType(const V1LayerParameter_LayerType type) {
|
||||
|
||||
static const int kProtoReadBytesLimit = INT_MAX; // Max size of 2 GB minus 1 byte.
|
||||
|
||||
bool ReadProtoFromBinary(ZeroCopyInputStream* input, Message *proto) {
|
||||
bool ReadProtoFromBinary(ZeroCopyInputStream* input, MessageLite *proto) {
|
||||
CodedInputStream coded_input(input);
|
||||
#if GOOGLE_PROTOBUF_VERSION >= 3006000
|
||||
coded_input.SetTotalBytesLimit(kProtoReadBytesLimit);
|
||||
@@ -1133,7 +1134,12 @@ bool ReadProtoFromTextFile(const char* filename, Message* proto) {
|
||||
return parser.Parse(&input, proto);
|
||||
}
|
||||
|
||||
bool ReadProtoFromBinaryFile(const char* filename, Message* proto) {
|
||||
bool ReadProtoFromTextFile(const char* filename, MessageLite* proto) {
|
||||
CV_Error(Error::StsError, "DNN/CAFFE: do not have your message be a MessageLite");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadProtoFromBinaryFile(const char* filename, MessageLite* proto) {
|
||||
std::ifstream fs(filename, std::ifstream::in | std::ifstream::binary);
|
||||
CHECK(fs.is_open()) << "Can't open \"" << filename << "\"";
|
||||
IstreamInputStream raw_input(&fs);
|
||||
@@ -1151,26 +1157,52 @@ bool ReadProtoFromTextBuffer(const char* data, size_t len, Message* proto) {
|
||||
return parser.Parse(&input, proto);
|
||||
}
|
||||
|
||||
bool ReadProtoFromTextBuffer(const char* data, size_t len, MessageLite* proto) {
|
||||
CV_Error(Error::StsError, "DNN/CAFFE: do not have your message be a MessageLite");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadProtoFromBinaryBuffer(const char* data, size_t len, Message* proto) {
|
||||
bool ReadProtoFromBinaryBuffer(const char* data, size_t len, MessageLite* proto) {
|
||||
ArrayInputStream raw_input(data, len);
|
||||
return ReadProtoFromBinary(&raw_input, proto);
|
||||
}
|
||||
|
||||
void ReadNetParamsFromTextFileOrDie(const char* param_file,
|
||||
NetParameter* param) {
|
||||
template<class MESSAGE>
|
||||
typename std::enable_if<std::is_base_of<Message, MESSAGE>::value, void>::type
|
||||
ReadNetParamsFromTextFileOrDieImpl(const char* param_file, MESSAGE* param) {
|
||||
CHECK(ReadProtoFromTextFile(param_file, param))
|
||||
<< "Failed to parse NetParameter file: " << param_file;
|
||||
UpgradeNetAsNeeded(param_file, param);
|
||||
}
|
||||
|
||||
void ReadNetParamsFromTextBufferOrDie(const char* data, size_t len,
|
||||
NetParameter* param) {
|
||||
template<class MESSAGE>
|
||||
typename std::enable_if<!std::is_base_of<Message, MESSAGE>::value, void>::type
|
||||
ReadNetParamsFromTextFileOrDieImpl(const char* param_file, MESSAGE* param) {
|
||||
CV_Error(Error::StsError, "DNN/CAFFE: do not have your message be a MessageLite");
|
||||
}
|
||||
|
||||
void ReadNetParamsFromTextFileOrDie(const char* param_file, NetParameter* param) {
|
||||
ReadNetParamsFromTextFileOrDieImpl(param_file, param);
|
||||
}
|
||||
|
||||
template<class MESSAGE>
|
||||
typename std::enable_if<std::is_base_of<Message, MESSAGE>::value, void>::type
|
||||
ReadNetParamsFromTextBufferOrDieImpl(const char* data, size_t len, MESSAGE* param) {
|
||||
CHECK(ReadProtoFromTextBuffer(data, len, param))
|
||||
<< "Failed to parse NetParameter buffer";
|
||||
UpgradeNetAsNeeded("memory buffer", param);
|
||||
}
|
||||
|
||||
template<class MESSAGE>
|
||||
typename std::enable_if<!std::is_base_of<Message, MESSAGE>::value, void>::type
|
||||
ReadNetParamsFromTextBufferOrDieImpl(const char* data, size_t len, MESSAGE* param) {
|
||||
CV_Error(Error::StsError, "DNN/CAFFE: do not have your message be a MessageLite");
|
||||
}
|
||||
|
||||
void ReadNetParamsFromTextBufferOrDie(const char* data, size_t len, NetParameter* param) {
|
||||
ReadNetParamsFromTextBufferOrDieImpl(data, len, param);
|
||||
}
|
||||
|
||||
void ReadNetParamsFromBinaryFileOrDie(const char* param_file,
|
||||
NetParameter* param) {
|
||||
CHECK(ReadProtoFromBinaryFile(param_file, param))
|
||||
|
||||
@@ -119,9 +119,11 @@ void ReadNetParamsFromTextBufferOrDie(const char* data, size_t len,
|
||||
|
||||
// Utility functions used internally by Caffe and TensorFlow loaders
|
||||
bool ReadProtoFromTextFile(const char* filename, ::google::protobuf::Message* proto);
|
||||
bool ReadProtoFromBinaryFile(const char* filename, ::google::protobuf::Message* proto);
|
||||
bool ReadProtoFromTextFile(const char* filename, ::google::protobuf::MessageLite* proto);
|
||||
bool ReadProtoFromBinaryFile(const char* filename, ::google::protobuf::MessageLite* proto);
|
||||
bool ReadProtoFromTextBuffer(const char* data, size_t len, ::google::protobuf::Message* proto);
|
||||
bool ReadProtoFromBinaryBuffer(const char* data, size_t len, ::google::protobuf::Message* proto);
|
||||
bool ReadProtoFromTextBuffer(const char* data, size_t len, ::google::protobuf::MessageLite* proto);
|
||||
bool ReadProtoFromBinaryBuffer(const char* data, size_t len, ::google::protobuf::MessageLite* proto);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ Implementation of Tensorflow models parser
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <type_traits>
|
||||
#include "tf_graph_simplifier.hpp"
|
||||
#endif
|
||||
|
||||
@@ -3290,6 +3291,19 @@ Net readNetFromTensorflow(const std::vector<uchar>& bufferModel, const std::vect
|
||||
bufferConfigPtr, bufferConfig.size());
|
||||
}
|
||||
|
||||
|
||||
template<class GRAPH_DEF>
|
||||
typename std::enable_if<std::is_base_of<Message, GRAPH_DEF>::value, void>::type
|
||||
PrintToStringImpl(const GRAPH_DEF& net, std::string* content) {
|
||||
google::protobuf::TextFormat::PrintToString(net, content);
|
||||
}
|
||||
|
||||
template<class GRAPH_DEF>
|
||||
typename std::enable_if<!std::is_base_of<Message, GRAPH_DEF>::value, void>::type
|
||||
PrintToStringImpl(const GRAPH_DEF& net, std::string* content) {
|
||||
CV_Error(Error::StsError, "DNN/TF: do not have your message be a MessageLite");
|
||||
}
|
||||
|
||||
void writeTextGraph(const String& _model, const String& output)
|
||||
{
|
||||
String model = _model;
|
||||
@@ -3312,7 +3326,7 @@ void writeTextGraph(const String& _model, const String& output)
|
||||
}
|
||||
|
||||
std::string content;
|
||||
google::protobuf::TextFormat::PrintToString(net, &content);
|
||||
PrintToStringImpl(net, &content);
|
||||
|
||||
std::ofstream ofs(output.c_str());
|
||||
ofs << content;
|
||||
|
||||
Reference in New Issue
Block a user