2025年3月18日 星期二 甲辰(龙)年 月十七 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > VC/VC++

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

时间:02-25来源:作者:点击数:46

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图像的分量值频次统计
在这里插入图片描述

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 熵

根据熵的公式

在这里插入图片描述
分量
R 7.229552890551846
G 7.1784624848351
B 6.856861210882991
分量
Y 6.3318185418675075
U 5.12640191439972
V 4.113143002049819

7 实验结果分析

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

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门