【数据压缩】第一次作业——音频文件分析与RGB文件熵的计算

音频文件分析与RGB文件熵的计算

写在前面

受数据压缩老师的提示,还是挺想把每次的作业发出来的。
可能作业里面有部分工作借鉴了之前哥姐发的文章里的内容,因此如果哥姐看到有相似内容的话希望可以多多包涵,谢谢哥姐。(手动比个大心心)

音频分析

浊音

  • a

    • 时域:在这里插入图片描述

    • 时域放大后观察:在这里插入图片描述

    • 频谱图:在这里插入图片描述

  • ao

    • 时域:在这里插入图片描述

    • 时域放大后观察:在这里插入图片描述

    • 频谱图:在这里插入图片描述

  • 分析:

    • 一般将发声时声带振动的音称为浊音
    • 观察发现浊音时域呈现周期性,能量较高
    • 频谱中能量主要集中在低频段,具有明显的共振峰特性

清音

  • s

    • 时域:在这里插入图片描述

    • 时域放大后观察:在这里插入图片描述

    • 频谱图:在这里插入图片描述

  • c

    • 时域:在这里插入图片描述

    • 时域放大后观察:在这里插入图片描述

    • 频谱图:在这里插入图片描述

  • 分析

    • 发音时声带不振动的音称为清音
    • 清音时域没有周期性,分布更像随机噪声信号
    • 频域能量分布较为均匀

爆破音

  • t

    • 时域:在这里插入图片描述

    • 时域放大后观察:在这里插入图片描述

    • 频谱图:在这里插入图片描述

  • k

    • 时域:在这里插入图片描述

    • 时域放大后观察:在这里插入图片描述

    • 频谱图:在这里插入图片描述

  • 分析:

    • 爆破音是指发音器官在口腔中形成阻碍,然后气流冲破阻碍而发出的音。
    • 爆破音时域有一个明显的脉冲,之后逐渐减弱
    • 频域能量较为集中,低频处分布较为平均,到高频逐渐减弱

计算RGB文件的熵

分析

  • 计算熵的公式: H ( X ) = − ∑ i = 1 m p i l o g 2 ( p i ) H(X)=-\sum\limits_{i=1}^{m}p_ilog_2(p_i) H(X)=i=1mpilog2(pi)

  • test.rgb文件分辨率为256×256,数据格式为每个像素占用3字节,存储格式为BGRBGR…。

  • 首先打开文件并计算文件的大小

    • //打开文件
       	FILE* fp = fopen("E:\\大学学习\\数据压缩\\预习作业\\2\\test.rgb", "rb");     //读取rgb文件
       	
       	if (fp == NULL) { cout << 0; }
       
       	//查看文件大小
       	//由于之前没有学习过查看文件大小的方法,因此这段代码是从网上借鉴的
       	//链接:https://vegetable-chicken.blog.csdn.net/article/details/105073524?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7EHighlightScore-1.queryctrv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7EHighlightScore-1.queryctrv2&utm_relevant_index=2
       	fseek(fp, 0, SEEK_SET); //指针:移动到文件头部
       	long begin = ftell(fp);
       	fseek(fp, 0, SEEK_END);  //指针:移动到文件尾部
       	long end = ftell(fp);
       	long fileSize = end - begin;
       	cout << fileSize / 256 / 256 << endl;    //=3,即文件大小是256*256的3倍
       	fseek(fp, 0, SEEK_SET); //指针:移动到文件头部
      
    • 需要注意,在vs2019中使用fopen函数需要在程序开始添加:\#pragma warning(disable:4996);

    • 另外,在计算文件大小时,由于将文件的指针移到了文件的最后,因此需要在计算结束后将文件的指针再移动到文件头部,否则在后续计算过程中会出现读入的图片文件值全为0的情况

  • 之后将图片的数据按照BGR的顺序分别存到相应的数组中,并分别计算RGB三个通道每个像素值的个数、出现的概率

    • //数据按照BGRBGR...保存
      	for (int i = 0, j = 0; i < fileSize; i = i + 3, j++)
      	{
      		B[j] = *(image + i);
      		G[j] = *(image + i + 1);
      		R[j] = *(image + i + 2);
      	}
      
      	//计算每个通道各像素的次数
      	for (int i = 0; i < image_size; i++)
      	{
      		int valr = int(*(R + i));
      		pmfr[valr]++;
      		int valg = int(*(G + i));
      		pmfg[valg]++;
      		int valb = int(*(B + i));
      		pmfb[valb]++;
      	}
      
      	//计算每个通道各像素的概率
      	for (int i = 0; i < 256; i++)
      	{
      		pmfr[i] = pmfr[i] / (256 * 256);
      		pmfg[i] = pmfg[i] / (256 * 256);
      		pmfb[i] = pmfb[i] / (256 * 256);
      	}
      
    • 一定要注意在”.rgb“文件中RGB的存储顺序,否则后续计算会出错

  • 接下来分别计算RGB三个通道的熵

    • //计算熵并输出
      	for (int i = 0; i < 256; i++)
      	{
      		if (pmfr[i] != 0) { sr += (-1) * pmfr[i] * log(pmfr[i]) / log(2); };
      		if (pmfg[i] != 0) { sg += (-1) * pmfg[i] * log(pmfg[i]) / log(2); };
      		if (pmfb[i] != 0) { sb += (-1) * pmfb[i] * log(pmfb[i]) / log(2); };
      	}
      
      	cout << "R的熵为" << sr << endl;
      	cout << "G的熵为" << sg << endl;
      	cout << "B的熵为" << sb << endl;
      
  • 最后将每个通道的概率和计算得到的熵的结果存入文件中

完整代码

#include<iostream>
#include <STDIO.H>
#include <STDLIB.H>  //exit(0);
using namespace std;

#pragma warning(disable:4996);    //使得fopen在编译时可以通过

int main()
{
	//打开文件
	FILE* fp = fopen("E:\\大学学习\\数据压缩\\预习作业\\2\\test.rgb", "rb");     //读取rgb文件
	FILE* fr = fopen("E:\\大学学习\\数据压缩\\预习作业\\2\\pmfr.txt", "w");    //存储r的概率和熵
	FILE* fg = fopen("E:\\大学学习\\数据压缩\\预习作业\\2\\pmfg.txt", "w");    //存储g的概率和熵
	FILE* fb = fopen("E:\\大学学习\\数据压缩\\预习作业\\2\\pmfb.txt", "w");    //存储b的概率和熵

	if (fp == NULL) { cout << 0; }

	//查看文件大小
	//由于之前没有学习过查看文件大小的方法,因此这段代码是从网上借鉴的
	//链接:https://vegetable-chicken.blog.csdn.net/article/details/105073524?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7EHighlightScore-1.queryctrv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7EHighlightScore-1.queryctrv2&utm_relevant_index=2
	fseek(fp, 0, SEEK_SET); //指针:移动到文件头部
	long begin = ftell(fp);
	fseek(fp, 0, SEEK_END);  //指针:移动到文件尾部
	long end = ftell(fp);
	long fileSize = end - begin;
	cout << fileSize / 256 / 256 << endl;    //=3,即文件大小是256*256的3倍
	fseek(fp, 0, SEEK_SET); //指针:移动到文件头部
	
	int image_size = 256 * 256;
	unsigned char image[256 * 256 * 3] = { 0 };
	unsigned char R[256 * 256] = { 0 };
	unsigned char G[256 * 256] = { 0 };
	unsigned char B[256 * 256] = { 0 };

	//存放RGB中每个像素值(0~255)的概率
	double pmfr[256] = { 0 }, pmfg[256] = { 0 }, pmfb[256] = { 0 };

	//分别计算RGB的熵
	double sr = 0, sg = 0, sb = 0;

	//读入图像
	fread(image, sizeof(unsigned char), 256 * 256 * 3, fp);

	//数据按照BGRBGR...保存
	for (int i = 0, j = 0; i < fileSize; i = i + 3, j++)
	{
		B[j] = *(image + i);
		G[j] = *(image + i + 1);
		R[j] = *(image + i + 2);
	}

	//计算每个通道各像素的次数
	for (int i = 0; i < image_size; i++)
	{
		int valr = int(*(R + i));
		pmfr[valr]++;
		int valg = int(*(G + i));
		pmfg[valg]++;
		int valb = int(*(B + i));
		pmfb[valb]++;
	}

	//计算每个通道各像素的概率
	for (int i = 0; i < 256; i++)
	{
		pmfr[i] = pmfr[i] / (256 * 256);
		pmfg[i] = pmfg[i] / (256 * 256);
		pmfb[i] = pmfb[i] / (256 * 256);
	}

	//计算熵并输出
	for (int i = 0; i < 256; i++)
	{
		if (pmfr[i] != 0) { sr += (-1) * pmfr[i] * log(pmfr[i]) / log(2); };
		if (pmfg[i] != 0) { sg += (-1) * pmfg[i] * log(pmfg[i]) / log(2); };
		if (pmfb[i] != 0) { sb += (-1) * pmfb[i] * log(pmfb[i]) / log(2); };
	}

	cout << "R的熵为" << sr << endl;
	cout << "G的熵为" << sg << endl;
	cout << "B的熵为" << sb << endl;

	//写入概率和熵
	fprintf(fr, "值\t概率\n");
	fprintf(fg, "值\t概率\n");
	fprintf(fb, "值\t概率\n");
	for (int i = 0; i < 256; i++)
	{
		fprintf(fr, "%d\t%f\n", i, pmfr[i]);
		fprintf(fg, "%d\t%f\n", i, pmfr[i]);
		fprintf(fb, "%d\t%f\n", i, pmfb[i]);
	}
	fprintf(fr, "熵=%f\n", sr);
	fprintf(fg, "熵=%f\n", sg);
	fprintf(fb, "熵=%f\n", sb);

	fclose(fp);
	fclose(fr);
	fclose(fg);
	fclose(fb);

	return 0;

}

实验结果

-在这里插入图片描述

  • r:在这里插入图片描述

  • g:在这里插入图片描述

  • b:在这里插入图片描述

写在后面

文章可能会不定期更新,如有错误还请各位大神批评指正,谢谢大家

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值