欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据压缩·作业三(读取RGB文件)

程序员文章站 2022-07-14 21:58:29
...

题目:读入一个24bitRGB文件(以down.rgb为例,其分辨率为256256),输出该数据文件中R、G、B三个分量(各8bit表示)的概率分布示意图(类似下图)和熵。
数据压缩·作业三(读取RGB文件)
提示:(用C或C++实现时),程序的流程为
开辟3个width
height的unsigned char型数组;打开要读出的RGB文件(以“rb”方式打开),打开3个要输出的数据统计文件(以“w”方式打开,可命名为R_sat.txt等);将RGB数据从RGB文件中读出,并分别保存到3个数组中,期间计算数据的概率分布和熵,并将这些数据写入3个数据统计txt文件中。Txt文件的写入方式如下所示(每行的两个数据用tab分开)。在Excel里将这3个txt文件打开即可生成统计图。
数据压缩·作业三(读取RGB文件)

思路:

1、一个24bit的RGB文件,每个像素点可分为R、G、B三个分量,则这个文件可分为3个8bit的文件。
2、分辨率为256 * 256,则一个R/G/B文件数据量为256 * 256,设为常量SIZE;而一个24bit的RGB文件数据量为256 * 256 * 3,设为常量buffSIZE。
3、根据不同文件的数据量可以开辟出不同长度的数组用来存放读取和写入的数据。
用 buff[buffSIZE] 存放读取24bit的RGB文件得到的数据;
用 B[SIZE],G[SIZE],R[SIZE] 存放从 buff 数组里分出来的对应的数据。
4、经过计算后即可得到数据的概率分布并将它们写入txt文件中。
5、计算熵。

代码:(用C实现)

//
//  main.c
//  readRGB
//
//  Created by 阿华甜 on 2020/3/9.
//  Copyright © 2020 阿华甜. All rights reserved.
//

#include <stdio.h>
#include "math.h"
#define SIZE 256*256
#define buffSIZE 256*256*3
int main()
{
//打开down.rgb文件;打开分别存放r,g,b分量的文件
    FILE *fp=NULL,*r=NULL,*g=NULL,*b=NULL;
    fp = fopen("/Users/xena/Desktop/codeForSjys/down.rgb","rb");
    r=fopen("/Users/xena/Desktop/codeForSjys/readRGB/color_txt/r.txt", "w");
    fputs("symbol\tfreq\n", r);
    g=fopen("/Users/xena/Desktop/codeForSjys/readRGB/color_txt/g.txt", "w");
    fputs("symbol\tfreq\n", g);
    b=fopen("/Users/xena/Desktop/codeForSjys/readRGB/color_txt/b.txt", "w");
    fputs("symbol\tfreq\n", b);
//读取down.rgb文件
    unsigned char buff[buffSIZE];
    fread(buff,1,buffSIZE, fp);
//构建B、G、R三个数组用来存放数据
    unsigned char B[SIZE],G[SIZE],R[SIZE];
//把对应数据放入三个数组里
    for(int i=0;i<SIZE;i++)
    {
        B[i]=buff[3*i];
        G[i]=buff[3*i+1];
        R[i]=buff[3*i+2];
    }
//构建b_freq、b_freq、b_freq三个数组来存放频次
    double b_freq[256]={0};
    double g_freq[256]={0};
    double r_freq[256]={0};
//得到像素点对应取值的频数
    for(int i=0;i<SIZE;i++)
    {
        for(int j=0;j<256;j++)
        {
            if(B[i]==j){b_freq[j]++;}
            if(G[i]==j){g_freq[j]++;}
            if(R[i]==j){r_freq[j]++;}
        }
    }
//计算频率,并写入rgb的txt文件中
    for(int i=0;i<256;i++)
    {
        b_freq[i]=b_freq[i]/(SIZE);
        g_freq[i]=g_freq[i]/(SIZE);
        r_freq[i]=r_freq[i]/(SIZE);
        fprintf(b, "%d\t%lf\n",i,b_freq[i]);
        fprintf(g, "%d\t%lf\n",i,g_freq[i]);
        fprintf(r, "%d\t%lf\n",i,r_freq[i]);
    }
//关闭文件
    fclose(b);
    fclose(g);
    fclose(r);
    fclose(fp);
//计算熵
    double Hr=0,Hb=0,Hg=0;
    for(int i=0;i<256;i++)
    {
            if(r_freq[i]!=0){Hr+=r_freq[i]*(log(r_freq[i])/log(2));}
            if(g_freq[i]!=0){Hg+=g_freq[i]*(log(g_freq[i])/log(2));}
            if(b_freq[i]!=0){Hb+=b_freq[i]*(log(b_freq[i])/log(2));}
    }
    printf("Hr=%lf\n",-Hr);
    printf("Hg=%lf\n",-Hg);
    printf("Hb=%lf\n",-Hb);
    return 0;
}

结果:

数据压缩·作业三(读取RGB文件)
数据压缩·作业三(读取RGB文件)
数据压缩·作业三(读取RGB文件)
数据压缩·作业三(读取RGB文件)
数据压缩·作业三(读取RGB文件)

熵:
Hr=7.229553
Hg=7.178462
Hb=6.856861

分析:

1、由r_freq、g_freq、b_freq三根曲线叠加出来的折线图我们可以看出b_freq的折线是最往右的,其次是g_freq的曲线,说明这个RGB文件对应的图像应该是偏蓝偏绿的;
2、在取值偏小处(0~11)r_freq明显是有值的,而g_freq、b_freq无值或值很小,也说明了这张图片红色调是很少的;
3、从r_freq、g_freq、b_freq三根曲线叠加出来的折线图可以看出RGB三个分量都是在值小的地方概率较大,而在值大的地方概率较小,说明整张图片是偏暗的;
4、从r_freq、g_freq、b_freq三根曲线叠加出来的折线图还可以看出,r_freq、g_freq的概率峰值都差不多,而且两根曲线除了开头处r_freq稍大于g_freq,其他地方两根曲线的走势差不多,说明R、G分量的熵是差不多的,且R的熵会稍大于G的熵;而b_freq的峰值非常突出,说明B的熵是最小的,最后计算出的结果也验证了这点。

原图可验证分析的1、2、3点。

数据压缩·作业三(读取RGB文件)