给定两图片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的去相关性反而更好。