RGB文件的处理与分析

所给rgb文件是按照b,g,r顺序排列的且去掉了包含文件属性的文件头,文件分辨率为 256 × 256 256\times256 256×256

该段代码可以实现如下功能:

  • 计算该文件中r、g、b以及转化成的YUV格式中y、u、v的取值的出现概率。
  • 将频率输出为csv表格形式。
  • 输出4:4:4的cif文件
  • 计算r,g,b和y,u,v各分量的熵

由于c++作图不方便,于是图表均为excel完成。

#include 
#include 
#include 
#include 
using namespace std;
const char* inPath = "D:\\CLionProjects\\algorithm\\cmake-build-debug-mingw\\down.rgb";
const char* outPath = "D:\\CLionProjects\\algorithm\\cmake-build-debug-mingw\\data.csv";
const char* outFile = "D:\\CLionProjects\\algorithm\\cmake-build-debug-mingw\\data.cif";
//这里建议使用绝对路径
//使用相对路径时需要放到IDE默认的路径或手动设置
int num[6][256], len = 0;
double entropy[6];
vector< unsigned char > YUV[3];
int main()
{
	//打开rgb文件
    ifstream in(inPath, ios::binary);
    if (!in.is_open()) { cout << inPath << " can not be opened!" << endl; return 0; }
    while ( !in.eof())
    {
        unsigned char r, g, b, y, u, v, pos = 0;
        //读入r,g,b的值
        for (auto i : { &b,&g,&r }) *i = in.get();
        //计算Y,U,V分量
        y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
        u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
        v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
        //统计数值出现次数
        for (auto i : { r,g,b,y,u,v }) num[pos++][i] ++;
        pos = 0; len++;
        //存储Y,U,V的值
        for (auto i : { y,u,v }) YUV[pos++].push_back(i);
    }
    in.close();

	//创建表格
    ofstream out(outPath, ios::binary);
    if (!out.is_open()) { cout << outPath <<" can not be opened!" << endl; return 0; }
    //输出表格内容
    out << "Value,R,G,B,Y,U,V" << endl;
    for (int j = 0; j < 256; ++j)
    {
        out << j << ",";
        for (int i = 0; i < 6; ++i)
        {
            double p = 1.0 * num[i][j] / len;
            out << p << (i == 5 ? "\n" : ",");
            if (p != 0) entropy[i] -= p * log2f(p);
        }
    }
    out << endl << " ,R,G,B,Y,U,V" << endl << "entropy,";
    for (int i = 0; i < 6; ++i) out << entropy[i] << (i == 5 ? "\n" : ",");;
    out.close();

	//创建CIF文件
    out.open(outFile, ios::binary);
    if (!out.is_open()) { cout << outFile << " can not be opened!" << endl; return 0; }
    //输出内容
    for (auto& i : YUV) for (auto j : i) out << j;
    out.close();
}

生成的表格如下:
RGB文件的处理与分析_第1张图片
各个分量的熵:
熵
R,G,B和Y,U,V取值的频率图:
RGB文件的处理与分析_第2张图片
RGB文件的处理与分析_第3张图片
可见YUV格式中各个分量出现的比较集中。

各个分量的熵:
RGB文件的处理与分析_第4张图片
可见YUV格式各个分量的熵相较于RGB较小,根据香农第一定律可以压缩的比率也更大。

最后用YUV播放器打开cif文件验证一下转化成的YUV文件是否正确:
RGB文件的处理与分析_第5张图片
可以看到和原图一致。

你可能感兴趣的:(数据压缩作业)