统计RGB和YUV图像文件各分量的概率分布,并求出熵

1 实验目的

给定两图片down.rgbdown.yuv,分辨率为256*256,色度采样格式4:2:0,统计RGB和YUV图像文件各分类的概率分布,并求出熵

2 实验思路

本实验先使用C++,根据rgb和yuv文件的数据存储格式编写算法,将图片的各分量值的频次进行统计。由于C++作图、计算比较繁琐,故将统计结果使用CSV(Comma-Separated Values,逗号分隔值)进行导出,交由python进行图片的绘制和熵的计算。

3 文件的存储格式和图像关键数值的计算

3.1 RGB文件的存储格式

BGRBGRBGRBGR...,按BGR的顺序循环,上至下左至右逐行扫描

  • 由图像分辨率为width*height 256*256可计算出,每个像素占3bytes(B8 G8 R8 bits),故整幅图像像素个数size为196608。

3.2 YUV文件的存储格式:先存所有Y,再存所有U,再存所有V,上至下左至右扫描

  • 由图像分辨率为256*256,和色度取样格式为4:2:0可知:
    • Y所占字节数为65536,可算出U至数据起点的偏移量为uoffset=65536
    • U、V各是Y数量的1/4,即各16384个,可算出V至数据起点的偏移量为voffset 81920
    • 图像所占总字节数为yuvsize=98304

图源:书本《数字电视广播原理与应用》

4 对图片的各分量值频次进行统计

4.1 代码结构:

  • main.cpp包含主函数,执行文件I/O读写整个流程
  • pmf_RGB.cpp和pmf_RGB.h实现RGB图像的分量值频次统计
  • pmf_YUV.cpp和pmf_YUV.h实现YUV图像的分量值频次统计

统计RGB和YUV图像文件各分量的概率分布,并求出熵_第1张图片

4.2 代码

main.cpp

#include 
#include 
#include "pmf_RGB.h"
#include"pmf_YUV.h"
using namespace std;
#define size 196608
#define yuvsize 98304
#define uoffset 65536
#define voffset 81920
#define height 256
#define width 256

int main() {
     
	//读写文件和创建缓存
	ifstream originRGB("down.rgb", ios::binary);
	ifstream originYUV("down.yuv", ios::binary);
	ofstream RGB_out("rgb.csv");
	ofstream YUV_out("yuv.csv");
	if (!originRGB || !RGB_out || !originYUV || !YUV_out) {
     
		cout << "open file failed!" << endl;
		return 0;
	}

	unsigned char* RGB_Buffer = new unsigned char[size];
	unsigned char* YUV_Buffer = new unsigned char[size];
	originRGB.read((char*)RGB_Buffer, size);
	originYUV.read((char*)YUV_Buffer, yuvsize);

	int distribution_R[256] = {
      0 };
	int distribution_G[256] = {
      0 };
	int distribution_B[256] = {
      0 };
	int distribution_Y[256] = {
      0 };
	int distribution_U[256] = {
      0 };
	int distribution_V[256] = {
      0 };

	pmf_RGB(RGB_Buffer,size,distribution_R,distribution_G,distribution_B);
	pmf_YUV(YUV_Buffer, yuvsize, uoffset, voffset, distribution_Y, distribution_U, distribution_V);

	// 导出统计值到csv中,方便后续使用python作图
	RGB_out << "R,G,B" << endl;
	for (int i = 0; i < 256; i++) {
     
		RGB_out << distribution_R[i] << "," << distribution_G[i] << "," << distribution_B[i] << endl;
	}
	YUV_out << "Y,U,V" << endl;
	for (int i = 0; i < 256; i++) {
     
		YUV_out << distribution_Y[i] << "," << distribution_U[i] << "," << distribution_V[i] << endl;
	}

	delete[] RGB_Buffer;
	delete[] YUV_Buffer;
	originRGB.close();
	originYUV.close();
	RGB_out.close();
	YUV_out.close();
	return 0;
}

pmf_YUV.h

#pragma once
void pmf_YUV(unsigned char * YUV, int yuvsize, int uoffset, int voffset, int* distribution_Y, int* distribution_U, int* distribution_V);

pmf_YUV.cpp

void pmf_YUV(unsigned char* YUV, int yuvsize, int uoffset, int voffset, int* distribution_Y, int* distribution_U, int* distribution_V) {
     
	for (int i = 0; i < uoffset; i++) {
     
		int value = *(YUV + i);
		distribution_Y[value]++;
	}
	for (int i = uoffset; i < voffset; i++) {
     
		int value = *(YUV + i);
		distribution_U[value]++;
	}

	for (int i = voffset; i < yuvsize; i++) {
     
		int value = *(YUV + i);
		distribution_V[value]++;
	}
}

pmf_RGB.h

#pragma once
void pmf_RGB(unsigned char* RGB, int size, int distribution_R[], int distribution_G[], int distribution_B[]);

pmf_RGB.cpp

#include 
void pmf_RGB(unsigned char* RGB,int size,int distribution_R[],int distribution_G[],int distribution_B[]) {
     
	for (int i = 0; i < size; i += 3) {
     
		int value =*(RGB + i);
		distribution_B[value]++;
		value = *(RGB + i + 1);
		distribution_G[value]++;
		value = *(RGB + i + 2);
		distribution_R[value]++;
		
	}
}

5 使用Python的NumPy、Pandas、Matplotlib进行绘图和熵的计算

import numpy as np
import matplotlib.pyplot as plt
from pandas import read_csv

RGB=open('rgb.csv')
YUV=open('yuv.csv')
RGB_data=read_csv(RGB)
YUV_data=read_csv(YUV)
plt.rcParams['font.sans-serif'] = ['Songti SC'] # 指定默认字体

x=np.arange(0,256)

# YUV的作图同下
fig,rgb=plt.subplots()
rgb.plot(x,RGB_data['R']/RGB_data['R'].sum(),label='R',color='red')
rgb.plot(x,RGB_data['G']/RGB_data['G'].sum(),label='G',color='green')
rgb.plot(x,RGB_data['B']/RGB_data['B'].sum(),label='B',color='blue')
rgb.set_xlabel('值')
rgb.set_ylabel('出现频率')
rgb.set_title('RGB的概率分布图')
rgb.legend()
plt.show()

# 其他熵的计算同下
result=0
pr=RGB_data['R']/RGB_data['R'].sum()
it = iter(pr)    # 创建迭代器对象
for x in pr:
    if x!=0:
     result += -x*np.log2(x)
print(result)

6 实验结果

6.1 概率分布

统计RGB和YUV图像文件各分量的概率分布,并求出熵_第2张图片
统计RGB和YUV图像文件各分量的概率分布,并求出熵_第3张图片

6.2 熵

根据熵的公式 H ( x ) = − ∑ i N p ( x i ) l o g 2 p ( x i ) H(\bold x) =-\sum_i^N p(x_i)log_2 p(x_i) H(x)=iNp(xi)log2p(xi)

分量
R 7.229552890551846
G 7.1784624848351
B 6.856861210882991
分量
Y 6.3318185418675075
U 5.12640191439972
V 4.113143002049819

7 实验结果分析

RGB的三个分量相比YUV的三个分量,熵明显大,说明对于该图片,YUV冗余度更大一些,RGB的去相关性反而更好。

8 巨人的肩膀(大腿)

  1. 刘宗鑫的实验报告
  2. CSV (逗号分隔值文件格式)
  3. 实验结果与黄湘杰比对修改后一致,感谢交流!\salute

你可能感兴趣的:(数据压缩的那些实验报告,信息压缩)