目标
使用rapidjson库在c++环境中读取json文件信息并按RLE格式解码
一、RLE是什么?
coco数据集格式详解原文
COCO数据集的RLE都是uncompressed RLE格式(与之相对的是compact RLE)。 RLE所占字节的大小和边界上的像素数量是正相关的。RLE格式带来的好处就是当基于RLE去计算目标区域的面积以及两个目标之间的unoin和intersection时会非常有效率。 上面的segmentation中的counts数组和size数组共同组成了这幅图片中的分割 mask。其中size是这幅图片的宽高,然后在这幅图像中,每一个像素点要么在被分割(标注)的目标区域中,要么在背景中。很明显这是一个bool量:如果该像素在目标区域中为true那么在背景中就是False;如果该像素在目标区域中为1那么在背景中就是0。对于一个240x320的图片来说,一共有76800个像素点,根据每一个像素点在不在目标区域中,我们就有了76800个bit,比如像这样(随便写的例子,和上文的数组没关系):00000111100111110…;但是这样写很明显浪费空间,我们直接写上0或者1的个数不就行了嘛(Run-length encoding),于是就成了54251…,这就是上文中的counts数组。
二、rapidjson库
gihub链接
(这是腾讯开发的开源库,23333)
技术文档
RapidJSON 是一个 C++ 的 JSON 解析器及生成器。
无需编译,即插即用(雾)
RapidJSON 是只有头文件的 C++ 库。只需把 include/rapidjson 目录复制至系统或项目的 include 目录中。
三、代码实现
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
#include <iostream>
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include <fstream>
using namespace rapidjson;
int main() {
// 1. 把 JSON 解析至 DOM。
const char* json = "{\"project\":\"rapidjson\",\"stars\":10}";
Document d;
d.Parse(json);
// 2. 利用 DOM 作出修改。
Value& s = d["stars"];
s.SetInt(s.GetInt() + 1);
// 3. 把 DOM 转换(stringify)成 JSON。
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
d.Accept(writer);
// Output {"project":"rapidjson","stars":11}
std::cout << buffer.GetString() << std::endl;
//以上是一个简单测试,看你的库引用的对不对
//下面开始读取名为4.json文件中的内容,并把mask0counts中的数据反向RLE解码
FILE* fp = fopen("4.json", "r"); // 非 Windows 平台使用 "r"
//数据长度非通用,需要自己考虑一下,目前预设480*640=307200
char readBuffer[307200];
int toline01[307200];
FileReadStream is(fp, readBuffer, sizeof(readBuffer));
// printf(readBuffer[0]);
// StringStream s(readBuffer);
Document dx;
dx.ParseStream(is);
//dx.Parse(readBuffer);
fclose(fp);
assert(dx.IsObject());
// const Value& a = dx["image_id"];
// assert(a.IsArray());
// printf("image_id = %s\n", d["project"].GetString());
printf("image_id = %s\n", dx["image_id"].GetString());
printf("image_mask_num = %d\n", dx["mask_number"].GetInt());
const Value& a = dx["mask0counts"];
assert(a.IsArray());
bool val=true;
long n=0;
//RLE解码实现部分
for (SizeType i = 0; i < a.Size(); i++) // 使用 SizeType 而不是 size_t
{ //printf("a[%d] = %d\n", i, a[i].GetInt());
}
for (SizeType i = 0; i < a.Size(); i++)
{
val=! val;
for (int j = 0; j< a[i].GetInt(); j++)
{
if (val)
{
toline01[n]=1;
n=n+1;
}
else
{
toline01[n]=0;
n=n+1;
}
}
}
//把结果写入一个txt文档,仅供测试输出是否正确
std::fstream file("out.txt",std::ios::out);
for (int i = 0; i < 307200; i++) // 使用 SizeType 而不是 size_t
{ //printf("a[%d] = %d\n", i, toline01[i]);
file <<toline01[i];
//printf(" %d", toline01[i]);
}
file.close();
// std::fstream file("out.txt",std::ios::out);
// file <<
// std::cout <<toline01;
return 0;
}