分析RGB和YUV二进制格式图像的三通道概率分布及其熵

一. 全彩图像及其RGB三通道

全彩色图像也被称为RGB图像,大部分是24bit的RGB图像。其由三个通道,分别是R-红色通道,G-绿色通道,B-蓝色通道组成。而R(Red),G(Green),B(Green)也被称为光的三基色,三基色是指无法通过其他颜色混合得到的“基本色”,由于人的肉眼由感知RGB三种不同颜色的锥体细胞,因此色彩空间通常可以由RGB三种基本色来表达。

二. 使用Python分析RGB二进制格式的图像

1. 读取RGB二进制格式的图像

我们使用二进制的方式打开并读取.rgb文件,并将列表中的数据均转换成int型以方便后续概率与熵的计算,当然我们要及时的关闭打开的文件以释放其占用的内存,加快处理速度。

#以2进制文件读取"down.rgb"文件
f = open("down.rgb", "rb")
data = f.read()
#关闭打开的文件
f.close()
#将数据转换成int
data = [int(x) for x in data]

2. 分离RGB三通道

因为本次实验采用的文件分辨率为256*256,且该二进制图像文件的存储格式为:rgb文件按照每个像素BGR分量一次储存,即“BGR BGR BGR …”

#RGB通道的分离
bGroup = []
gGroup = []
rGroup = []
for i in range(256*256):#本次实验采用的文件分辨率为256*256
    bGroup.append(data[i*3])
    gGroup.append(data[i*3+1])
    rGroup.append(data[i*3+2])

3. 重现RGB三通道的图像

为了直观的感受图像三个通道与原图的关系,我们将三个通道的图像进行了重现。代码中是将单独的RGB三通道补全成完整的三彩图像(当然其中有两个通道均为零),然后使用data_b = np.array(data_b).reshape((256, 256, 3)).astype(np.uint8)将RGB转换为openCV可以显示的格式,从而重现图像。

data_b = []
for i in range(256*256):
    data_b.append(bGroup[i])
    data_b.append(0)
    data_b.append(0)
data_g = []
for i in range(256*256):
    data_g.append(0)
    data_g.append(gGroup[i])
    data_g.append(0)
data_r = []
for i in range(256*256):
    data_r.append(0)
    data_r.append(0)
    data_r.append(rGroup[i])
#转换格式使用OpenCV显示
#b通道
data_b = np.array(data_b).reshape((256, 256, 3)).astype(np.uint8)
cv.imshow("down_b.rgb", data_b)
#g通道
data_g = np.array(data_g).reshape((256, 256, 3)).astype(np.uint8)
cv.imshow("data_g.rgb", data_g)
#r通道
data_r = np.array(data_r).reshape((256, 256, 3)).astype(np.uint8)
cv.imshow("data_r.rgb", data_r)
#原彩图片
data = np.array(data).reshape((256, 256, 3)).astype(np.uint8)
cv.imshow("down.rgb", data)
cv.waitKey()

重新图像如下:在这里插入图片描述

4. 计算RGB三通道的概率分布并作图

因为图像时8bit的色彩,所以每一个通道都是0-255的256个值。所以我们可以通过代码来计算每一个通道中0-255各值的数量除以整张图像像素总数量计算其概率分布。然后通过matplotlib.pyplot以0-255为横坐标,各值下的概率为纵坐标绘制图像,可以更加显示化的展示三通道的概率分布。

#计算三通道的概率分布
#b通道
b_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
b_gailv = [int(x) for x in b_gailv]
for i in range(256*256):
    for j in range(256):
        if bGroup[i]==j:
            b_gailv[j] = b_gailv[j] + 1
for j in range(256):
    b_gailv[j] = b_gailv[j]/(256*256)
#b通道
g_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
g_gailv = [int(x) for x in g_gailv]
for i in range(256*256):
    for j in range(256):
        if gGroup[i]==j:
            g_gailv[j] = g_gailv[j] + 1
for j in range(256):
    g_gailv[j] = g_gailv[j]/(256*256)
#b通道
r_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
r_gailv = [int(x) for x in r_gailv]
for i in range(256*256):
    for j in range(256):
        if rGroup[i]==j:
            r_gailv[j] = r_gailv[j] + 1
for j in range(256):
    r_gailv[j] = r_gailv[j]/(256*256)
#作图
plt.plot(b_gailv, 'b')
plt.plot(g_gailv, 'g')
plt.plot(r_gailv, 'r')
plt.legend(["b aisle", "g aisle", "r aisle"])
plt.show()

绘制的概率分布图如下:
在这里插入图片描述

5. 计算RGB三通道的熵

我们在第3步中已经得到了三个通道的概率,然后根据熵的计算公式即可计算出对应通道的熵:

H ( x ) = − ∑ i = 0 n P ( x i ) l o g 2 P ( x i ) H(x)=-\sum_{i=0}^{n}P(x_{i})log_{2}P(x_{i}) H(x)=i=0nP(xi)log2P(xi)

#计算各自的熵
#b通道
H_b = 0
for j in range(256):
    if b_gailv[j] != 0:
        H_b = H_b + b_gailv[j]*ma.log2(b_gailv[j])
H_b = -H_b
#g通道
H_g = 0
for j in range(256):
    if g_gailv[j] != 0:
        H_g = H_g + g_gailv[j]*ma.log2(g_gailv[j])
H_g = -H_g
#r通道
H_r = 0
for j in range(256):
    if r_gailv[j] != 0:
        H_r = H_r + r_gailv[j]*ma.log2(r_gailv[j])
H_r = -H_r
print("H(b)=", H_b)
print("H(g)=", H_g)
print("H(r)=", H_r)

各通道熵值结果如下:

H ( b )H ( g )H ( r )
6.8568612108829927.1784624848350987.229552890551846

6. 完整代码

#导入程序所需要的包
import cv2 as cv
import numpy as np
import math as ma
import matplotlib.pyplot as plt

#以2进制文件读取"down.rgb"文件
f = open("down.rgb", "rb")
data = f.read()
#关闭打开的文件
f.close()
#将数据转换成int
data = [int(x) for x in data]
#RGB通道的分离
bGroup = []
gGroup = []
rGroup = []
for i in range(256*256):
    bGroup.append(data[i*3])
    gGroup.append(data[i*3+1])
    rGroup.append(data[i*3+2])
data_b = []
for i in range(256*256):
    data_b.append(bGroup[i])
    data_b.append(0)
    data_b.append(0)
data_g = []
for i in range(256*256):
    data_g.append(0)
    data_g.append(gGroup[i])
    data_g.append(0)
data_r = []
for i in range(256*256):
    data_r.append(0)
    data_r.append(0)
    data_r.append(rGroup[i])
#计算三通道的概率分布
#b通道
b_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
b_gailv = [int(x) for x in b_gailv]
for i in range(256*256):
    for j in range(256):
        if bGroup[i]==j:
            b_gailv[j] = b_gailv[j] + 1
for j in range(256):
    b_gailv[j] = b_gailv[j]/(256*256)
#b通道
g_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
g_gailv = [int(x) for x in g_gailv]
for i in range(256*256):
    for j in range(256):
        if gGroup[i]==j:
            g_gailv[j] = g_gailv[j] + 1
for j in range(256):
    g_gailv[j] = g_gailv[j]/(256*256)
#b通道
r_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
r_gailv = [int(x) for x in r_gailv]
for i in range(256*256):
    for j in range(256):
        if rGroup[i]==j:
            r_gailv[j] = r_gailv[j] + 1
for j in range(256):
    r_gailv[j] = r_gailv[j]/(256*256)
#作图
plt.plot(b_gailv, 'b')
plt.plot(g_gailv, 'g')
plt.plot(r_gailv, 'r')
plt.legend(["b aisle", "g aisle", "r aisle"])
plt.show()
#计算各自的熵
#b通道
H_b = 0
for j in range(256):
    if b_gailv[j] != 0:
        H_b = H_b + b_gailv[j]*ma.log2(b_gailv[j])
H_b = -H_b
#g通道
H_g = 0
for j in range(256):
    if g_gailv[j] != 0:
        H_g = H_g + g_gailv[j]*ma.log2(g_gailv[j])
H_g = -H_g
#r通道
H_r = 0
for j in range(256):
    if r_gailv[j] != 0:
        H_r = H_r + r_gailv[j]*ma.log2(r_gailv[j])
H_r = -H_r
print("H(b)=", H_b)
print("H(g)=", H_g)
print("H(r)=", H_r)
#转换格式使用OpenCV显示
#b通道
data_b = np.array(data_b).reshape((256, 256, 3)).astype(np.uint8)
cv.imshow("down_b.rgb", data_b)
#g通道
data_g = np.array(data_g).reshape((256, 256, 3)).astype(np.uint8)
cv.imshow("data_g.rgb", data_g)
#r通道
data_r = np.array(data_r).reshape((256, 256, 3)).astype(np.uint8)
cv.imshow("data_r.rgb", data_r)
#原彩图片
data = np.array(data).reshape((256, 256, 3)).astype(np.uint8)
cv.imshow("down.rgb", data)
cv.waitKey()

三. 全彩图像及其YUV三通道

同样彩色图像也可以使用yuv来表示,其中y表示明亮度,反应了灰阶值;u和v则表示图像的色度和饱和度。

四. 使用Python分析YUV二进制格式的图像

1. 读取YUV二进制格式的图像

yuv文件的读取与rgb文件的读取相似

#以2进制文件读取"down.yuv"文件
f = open("down.yuv", "rb")
data = f.read()
#关闭打开的文件
f.close()
#将数据转换成int
data = [int(x) for x in data]

2. 分离YUV三通道

因为本次实验采用的文件分辨率为256*256,且该二进制图像文件的存储格式为:yuv格式按照全部像素的y数据块、u数据块、v数据块以此存放,即“YYYY… UUUU… VVVV…”

#YUV通道的分离
yGroup = []
uGroup = []
vGroup = []
for i in range(256*256):
    yGroup.append(data[i])
for i in range(256*256, int(256*256*1.25)):
    uGroup.append(data[i])
for i in range(int(256*256*1.25), int(256*256*1.5)):
    vGroup.append(data[i])

3. 计算YUV三通道的概率分布并作图

yuv文件的三通道的概率分布并作图与rgb文件的三通道的概率分布并作图相似

#计算三通道的概率分布
#y通道
y_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
y_gailv = [int(x) for x in y_gailv]
for i in range(256*256):
    for j in range(256):
        if yGroup[i]==j:
            y_gailv[j] = y_gailv[j] + 1
for j in range(256):
    y_gailv[j] = y_gailv[j]/(256*256)
#u通道
u_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
u_gailv = [int(x) for x in u_gailv]
for i in range(int(256*256/4)):
    for j in range(256):
        if uGroup[i]==j:
            u_gailv[j] = u_gailv[j] + 1
for j in range(256):
    u_gailv[j] = u_gailv[j]/(int(256*256/4))
#v通道
v_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
v_gailv = [int(x) for x in v_gailv]
for i in range(int(256*256/4)):
    for j in range(256):
        if vGroup[i]==j:
            v_gailv[j] = v_gailv[j] + 1
for j in range(256):
    v_gailv[j] = v_gailv[j]/(int(256*256/4))
#作图
plt.plot(y_gailv, 'b')
plt.plot(u_gailv, 'g')
plt.plot(v_gailv, 'r')
plt.legend(["y aisle", "u aisle", "v aisle"])
plt.show()

绘制的概率分布图如下:在这里插入图片描述

4. 计算YUV三通道的熵

yuv文件的三通道的熵与rgb文件的三通道的熵相似

#计算各自的熵
#y通道
H_y = 0
for j in range(256):
    if y_gailv[j] != 0:
        H_y = H_y + y_gailv[j]*ma.log2(y_gailv[j])
H_y = -H_y
#u通道
H_u = 0
for j in range(256):
    if u_gailv[j] != 0:
        H_u = H_u + u_gailv[j]*ma.log2(u_gailv[j])
H_u = -H_u
#b通道
H_v = 0
for j in range(256):
    if v_gailv[j] != 0:
        H_v = H_v + v_gailv[j]*ma.log2(v_gailv[j])
H_v = -H_v
print("H(y)=", H_y)
print("H(u)=", H_u)
print("H(v)=", H_v)

各通道熵值结果如下:

H ( y )H ( u )H ( v )
6.33181854186750755.126401914399724.113143002049819

5. 完整代码

#导入程序所需要的包
import math as ma
import matplotlib.pyplot as plt

#以2进制文件读取"down.rgb"文件
f = open("down.yuv", "rb")
data = f.read()
#关闭打开的文件
f.close()
#将数据转换成int
data = [int(x) for x in data]
#YUV通道的分离
yGroup = []
uGroup = []
vGroup = []
for i in range(256*256):
    yGroup.append(data[i])
for i in range(256*256, int(256*256*1.25)):
    uGroup.append(data[i])
for i in range(int(256*256*1.25), int(256*256*1.5)):
    vGroup.append(data[i])
#计算三通道的概率分布
#y通道
y_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
y_gailv = [int(x) for x in y_gailv]
for i in range(256*256):
    for j in range(256):
        if yGroup[i]==j:
            y_gailv[j] = y_gailv[j] + 1
for j in range(256):
    y_gailv[j] = y_gailv[j]/(256*256)
#u通道
u_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
u_gailv = [int(x) for x in u_gailv]
for i in range(int(256*256/4)):
    for j in range(256):
        if uGroup[i]==j:
            u_gailv[j] = u_gailv[j] + 1
for j in range(256):
    u_gailv[j] = u_gailv[j]/(int(256*256/4))
#v通道
v_gailv = [0 for x in range(0, 256)]#创建一个长度为256的默认值为0的列表
v_gailv = [int(x) for x in v_gailv]
for i in range(int(256*256/4)):
    for j in range(256):
        if vGroup[i]==j:
            v_gailv[j] = v_gailv[j] + 1
for j in range(256):
    v_gailv[j] = v_gailv[j]/(int(256*256/4))
#作图
plt.plot(y_gailv, 'b')
plt.plot(u_gailv, 'g')
plt.plot(v_gailv, 'r')
plt.legend(["y aisle", "u aisle", "v aisle"])
plt.show()
#计算各自的熵
#y通道
H_y = 0
for j in range(256):
    if y_gailv[j] != 0:
        H_y = H_y + y_gailv[j]*ma.log2(y_gailv[j])
H_y = -H_y
#u通道
H_u = 0
for j in range(256):
    if u_gailv[j] != 0:
        H_u = H_u + u_gailv[j]*ma.log2(u_gailv[j])
H_u = -H_u
#b通道
H_v = 0
for j in range(256):
    if v_gailv[j] != 0:
        H_v = H_v + v_gailv[j]*ma.log2(v_gailv[j])
H_v = -H_v
print("H(y)=", H_y)
print("H(u)=", H_u)
print("H(v)=", H_v)

五. RGB文件与YUV文件压缩比较

通过os库可以轻松的获取到“down.rgb”和“down.yuv”两个文件的大小,我们可以轻松地看到这两个相同的图像,yuv文件明显比rgb文件要小,从概率分布的图像中可以看到yuv文件的概率分布要比rgb文件的概率分布更加均衡,yuv图像三通道的熵值也比rgb图像三通道的熵值要小,这些数据迹象均表明yuv文件要比rgb文件的压缩比大,也就是文件占用存储会更小。

import os

size_rgb = os.path.getsize('down.rgb')
size_yuv = os.path.getsize('down.yuv')
print(size_rgb)
print(size_yuv)

文件大小如下:

rgb文件yuv文件
19660898304

六. 归纳总结

使用Python可以比较方便快捷地读取文件,其代码结构和平时学习的c和c++差不多,通过对全彩图像的分析,验证了图像文件的存储格式与采样空间。并且通过对三通道的概率分布,以及三通道的熵值的分析,验证了yuv文件的存储占用要比rgb文件占用小的事实。为后续进一步学习数据压缩打下了基础。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值