1 实验目的
给定两图片down.rgb
和down.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
- Y所占字节数为65536,可算出U至数据起点的偏移量为
图源:书本《数字电视广播原理与应用》
4 对图片的各分量值频次进行统计
4.1 代码结构:
- main.cpp包含主函数,执行文件I/O读写整个流程
- pmf_RGB.cpp和pmf_RGB.h实现RGB图像的分量值频次统计
- pmf_YUV.cpp和pmf_YUV.h实现YUV图像的分量值频次统计
4.2 代码
main.cpp
#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;
}
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 <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]++;
}
}
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 概率分布
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)=−i∑Np(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 巨人的肩膀(大腿)
- 刘宗鑫的实验报告
- CSV (逗号分隔值文件格式)
- 实验结果与
黄湘杰
比对修改后一致,感谢交流!\salute