给定两图片down.rgb和down.yuv,分辨率为256*256,色度采样格式4:2:0,统计RGB和YUV图像文件各分类的概率分布,并求出熵
本实验先使用C++,根据rgb和yuv文件的数据存储格式编写算法,将图片的各分量值的频次进行统计。由于C++作图、计算比较繁琐,故将统计结果使用CSV(Comma-Separated Values,逗号分隔值)进行导出,交由python进行图片的绘制和熵的计算。
BGRBGRBGRBGR...,按BGR的顺序循环,上至下左至右逐行扫描
图源:书本《数字电视广播原理与应用》
- #include <iostream>
- #include <fstream>
- #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;
- }
-
- #pragma once
- void pmf_YUV(unsigned char * YUV, int yuvsize, int uoffset, int voffset, int* distribution_Y, int* distribution_U, int* distribution_V);
-
- 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]++;
- }
- }
-
- #pragma once
- void pmf_RGB(unsigned char* RGB, int size, int distribution_R[], int distribution_G[], int distribution_B[]);
-
- #include <iostream>
- 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]++;
-
- }
- }
-
- 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)
-
根据熵的公式
分量 | 熵 |
---|---|
R | 7.229552890551846 |
G | 7.1784624848351 |
B | 6.856861210882991 |
分量 | 熵 |
---|---|
Y | 6.3318185418675075 |
U | 5.12640191439972 |
V | 4.113143002049819 |
RGB的三个分量相比YUV的三个分量,熵明显大,说明对于该图片,YUV冗余度更大一些,RGB的去相关性反而更好。