HRegion数据结构
region代表一块区域,如果0代表空,1代表有,这里面有很多重复数据需要占用大量内存,这时候可以用run编码来减少内存占用,但是这种方法的缺点运算的时候就需要解码才能方便运算。
run编码
垂直 runlength 编码(Vertical Runlength Encoding)是一种类似于常规 runlength 编码的图像压缩方法,但它主要针对垂直方向上的像素序列进行编码。与常规的 runlength 编码相比,垂直 runlength 编码在处理某些类型的图像数据时可能更加高效。
在一些图像中,特别是在具有连续垂直线或者垂直条纹的图像中,垂直 runlength 编码可能会比常规 runlength 编码更有效。这是因为对于这样的图像,垂直方向上的像素序列可能更容易形成长连续的重复像素值序列,而水平方向上的重复可能相对较少。
垂直 runlength 编码的基本原理与常规 runlength 编码相似,但它是针对垂直方向上的像素序列进行扫描和编码的。编码的结果是一系列垂直方向上的运行,每个运行包含了连续的像素值和其长度。
在某些情况下,使用垂直 runlength 编码可以提供更好的压缩率和更高的压缩效率,特别是在处理垂直方向上具有较多重复像素值的图像时。因此,一些图像处理库和算法提供了垂直 runlength 编码作为一种可选的压缩方式,以便根据实际情况选择最合适的压缩方法。
run编码的实现
#include <vector>
#include <utility>
// 用于表示像素的坐标结构
struct Pixel {
int x;
int y;
};
// 用于表示运行的结构
struct Run {
int length; // 运行的长度
int value; // 运行中的像素值
};
// HRegion 类,用于表示图像区域
class HRegion {
public:
std::vector<Pixel> pixels; // 存储区域中的像素坐标
// 添加像素到区域中
void addPixel(int x, int y) {
pixels.push_back({x, y});
}
};
// 将 HRegion 编码为 Runlength 形式
std::vector<Run> encodeAsRuns(const HRegion& region) {
std::vector<Run> runs;
if (region.pixels.empty()) {
return runs;
}
int currentRunValue = -1;
int currentRunLength = 0;
for (const auto& pixel : region.pixels) {
int pixelValue = pixel.x * pixel.y; // 假设简单地将坐标相乘作为像素值
if (pixelValue != currentRunValue) {
// 如果当前像素值与上一个运行的像素值不同,则开始一个新的运行
if (currentRunLength > 0) {
// 将上一个运行添加到结果中
runs.push_back({currentRunLength, currentRunValue});
}
// 开始新的运行
currentRunValue = pixelValue;
currentRunLength = 1;
} else {
// 如果当前像素值与上一个运行的像素值相同,则增加运行的长度
currentRunLength++;
}
}
// 添加最后一个运行
runs.push_back({currentRunLength, currentRunValue});
return runs;
}
// 将 runlength 编码转换为 HRegion
HRegion decodeRunlength(const std::vector<Run>& runs) {
HRegion region;
for (const auto& run : runs) {
for (int i = 0; i < run.length; ++i) {
// 添加像素到区域中
region.addPixel(run.value, i);
}
}
return region;
}
// 计算两个 HRegion 的交集
HRegion intersection(const HRegion& region1, const HRegion& region2) {
HRegion result;
// 将区域1和区域2中的像素转换为 runlength 编码
std::vector<Run> runs1 = encodeAsRuns(region1);
std::vector<Run> runs2 = encodeAsRuns(region2);
// 解码 runlength 编码,得到包含所有像素的 HRegion
HRegion decodedRegion1 = decodeRunlength(runs1);
HRegion decodedRegion2 = decodeRunlength(runs2);
// 检查区域1中的每个像素是否也在区域2中存在
for (const auto& pixel1 : decodedRegion1.pixels) {
for (const auto& pixel2 : decodedRegion2.pixels) {
if (pixel1.x == pixel2.x && pixel1.y == pixel2.y) {
// 将该像素添加到交集结果中
result.addPixel(pixel1.x, pixel1.y);
break;
}
}
}
return result;
}