google protobuf使用记录

C++版本

参考链接protobuf repeated类型的使用
repeated类型设置值的方法是add
optional,required类型设置值得方法是set,下面用开源的目标检测框架SSD里的数据层代码举例,注意最后添加plate_valid成员变量的方式。

message PlateValid {
	repeated int32 valid = 1;
	optional int32 length = 2;
}

message Annotation {
	optional int32 instance_id = 1 [default = 0];
	optional NormalizedBBox bbox = 2;
	optional PlateValid plate_valid = 3;
}

// Parse MSCOCO detection annotation.
bool ReadJSONToAnnotatedDatum(const string& labelfile, const int img_height,
    const int img_width, const std::map& name_to_label,
    AnnotatedDatum* anno_datum) {
  ptree pt;
  read_json(labelfile, pt);

  // Get image info.
  int width = 0, height = 0;
  try {
    height = pt.get("image.height");
    width = pt.get("image.width");
  } catch (const ptree_error &e) {
    LOG(WARNING) << "When parsing " << labelfile << ": " << e.what();
    height = img_height;
    width = img_width;
  }
  LOG_IF(WARNING, height != img_height) << labelfile <<
      " inconsistent image height.";
  LOG_IF(WARNING, width != img_width) << labelfile <<
      " inconsistent image width.";
  CHECK(width != 0 && height != 0) << labelfile <<
      " no valid image width/height.";

  // Get annotation info.
  int instance_id = 0;
  BOOST_FOREACH(ptree::value_type& v1, pt.get_child("annotation")) {
    Annotation* anno = NULL;
    bool iscrowd = false;
    ptree object = v1.second;
    // Get category_id.
    string name = object.get("category_id");
    if (name_to_label.find(name) == name_to_label.end()) {
      LOG(FATAL) << "Unknown name: " << name;
    }
    int label = name_to_label.find(name)->second;
    bool found_group = false;
    for (int g = 0; g < anno_datum->annotation_group_size(); ++g) {
      AnnotationGroup* anno_group =
          anno_datum->mutable_annotation_group(g);
      if (label == anno_group->group_label()) {
        if (anno_group->annotation_size() == 0) {
          instance_id = 0;
        } else {
          instance_id = anno_group->annotation(
              anno_group->annotation_size() - 1).instance_id() + 1;
        }
        anno = anno_group->add_annotation();
        found_group = true;
      }
    }
    if (!found_group) {
      // If there is no such annotation_group, create a new one.
      AnnotationGroup* anno_group = anno_datum->add_annotation_group();
      anno_group->set_group_label(label);
      anno = anno_group->add_annotation();
      instance_id = 0;
    }
    anno->set_instance_id(instance_id++);

    // Get iscrowd.
    iscrowd = object.get("iscrowd", 0);

    // Get bbox.
    vector bbox_items;
    BOOST_FOREACH(ptree::value_type& v2, object.get_child("bbox")) {
      bbox_items.push_back(v2.second.get_value());
    }
    CHECK_EQ(bbox_items.size(), 4);
    float xmin = bbox_items[0];
    float ymin = bbox_items[1];
    float xmax = bbox_items[0] + bbox_items[2];
    float ymax = bbox_items[1] + bbox_items[3];
    CHECK_NOTNULL(anno);
    LOG_IF(WARNING, xmin > width) << labelfile <<
        " bounding box exceeds image boundary.";
    LOG_IF(WARNING, ymin > height) << labelfile <<
        " bounding box exceeds image boundary.";
    LOG_IF(WARNING, xmax > width) << labelfile <<
        " bounding box exceeds image boundary.";
    LOG_IF(WARNING, ymax > height) << labelfile <<
        " bounding box exceeds image boundary.";
    LOG_IF(WARNING, xmin < 0) << labelfile <<
        " bounding box exceeds image boundary.";
    LOG_IF(WARNING, ymin < 0) << labelfile <<
        " bounding box exceeds image boundary.";
    LOG_IF(WARNING, xmax < 0) << labelfile <<
        " bounding box exceeds image boundary.";
    LOG_IF(WARNING, ymax < 0) << labelfile <<
        " bounding box exceeds image boundary.";
    LOG_IF(WARNING, xmin > xmax) << labelfile <<
        " bounding box irregular.";
    LOG_IF(WARNING, ymin > ymax) << labelfile <<
        " bounding box irregular.";
    // Store the normalized bounding box.
    NormalizedBBox* bbox = anno->mutable_bbox();
    bbox->set_xmin(xmin / width);
    bbox->set_ymin(ymin / height);
    bbox->set_xmax(xmax / width);
    bbox->set_ymax(ymax / height);
    bbox->set_difficult(iscrowd);
    
    // valid是从json文件里读取的标注字符串string类型
    // std::string valid = object.get("valid");
    PlateValid *plate_valid = anno->mutable_plate_valid();
    int plate_length = 0;
    for (int j = 0; j < valid.size(); j++) {
    	std::sring valid_elem(1, valid[j]);
    	int chrlabel = name_to_chrlabel.find(valid_elem)->second;
    	plate_valid->add_valid(chrlabel);
    	plate_valid->set_length(++plate_length);
  }
  return true;
}

Python版本

python protobuf repeated类型的使用方法参考Python序列化protobuf中的repeated数据。自定义类型和基本类型添加实例的方法不一样,一个用add(),一个用append()。

ValueError: ‘\xe5\x94\x90\xe6\x9e\x9c‘ has type bytes, but isn‘t in 7-bit ASCII encoding. Non-ASCII strings must be converted to unicode objects before being added.

原因分析,参考这里在Python中使用protobuf2.6.1 string format utf-8 and unicode error
解决方法:message中赋值时 都带上 decode(“utf-8”)

其他

proto中的数据类型和c++,Python中的数据类型对应规则如下:

.proto C++ Python 介绍
double double float
float float float
int32 int32 int 可变长编码,对负数效率不高
int64 int64 int/long
uint32 uint32 int/long
uint64 uint64 int/long
sint32 int32 int 可变长编码,对负数效率较高
sint64 int64 int/long
fixed32 uint32 int/long 32位定长编码
fixed64 uint64 int/long
sfixed32 int32 int
sfixed64 int64 int/long
bool bool bool
string string str/unicode UTF-8编码或者7-ASCII编码
bytes string str

你可能感兴趣的:(工具)