Use python to read RGB and YUV format pictures and calculate their entropy
I. Introduction
The content of this task:
Analyze the probability distribution of the three channels on down.rgb and down.yuv, and calculate their respective entropies. The resolution of the two files is 256*256, yuv is 4:2:0 sampling space, and the storage format is: rgb files are stored in sequence according to the BGR component of each pixel; the YUV format is according to the Y data block and U data block of all pixels And V data blocks are stored in sequence.
Although I used c++ to read YUV format files and perform a series of processing in the last semester, in comparison, python is more convenient to perform such operations, with more packages that can be called, and I am more familiar with it. Therefore, python is chosen as the programming language this time.
Second, read the image
1.RGB
#读取RGB图像
f = open(image_path,"rb")
data = f.read()
f.close()
data = [int(x) for x in data]
data = np.array(data).reshape((256*256, 3)).astype(np.uint8)
Originally, for the convenience of viewing the image of each channel, it was reshaped to (256, 256, 3). Later, when calculating the entropy, it was discovered that the np.bincount() function can only pass in one-dimensional data, so it was changed to a two-dimensional matrix.
Picture display
Note: The data storage order isBGRInstead of RGB
After consulting the data, it is found that the default reading method in opencv is also BGR, which needs to be paid attention to in the future
The function converts an input image from one color space to another. In case of a transformation to-from RGB color space, the order of the channels should be specified explicitly (RGB or BGR). Note that the default color format in OpenCV is often referred to as RGB but it is actually BGR (the bytes are reversed). So the first byte in a standard (24-bit) color image will be an 8-bit Blue component, the second byte will be Green, and the third byte will be Red. The fourth, fifth, and sixth bytes would then be the second pixel (Blue, then Green, then Red), and so on.
2.YUV
First, I checked some code written by others to read YUV on csdn, and it felt too complicated. After experimentation, it is found that directly restricting the size of each read by f.read() can read the YUV most quickly, and the read pointer will stay at the end of the last read.
#读取YUV图像
f = open(image_path,"rb")
data_Y = f.read(256*256)
data_U = f.read(128*128)
data_V = f.read(128*128)
data_Y = [int(x) for x in data_Y]
data_U = [int(x) for x in data_U]
data_V = [int(x) for x in data_V]
The picture shows
Y
U
V
Three, calculate entropy
1. Formulas and functions
function
#计算熵函数
def entropy(X):
n = len(X)
counts = np.bincount(X)
probs = counts[np.nonzero(counts)] / n
en = 0
for i in range(len(probs)):
en = en - probs[i] * np.log(probs[i])/np.log(2)
return en
np.bincount() function note:
np.nonzero() function note
2.RGB
#计算熵
data_B = data[:,0]
data_G = data[:,1]
data_R = data[:,2]
B = entropy(data_B)
G = entropy(data_G)
R = entropy(data_R)
print(B)
print(G)
print(R)
result:
R | G | B |
---|---|---|
7.229552890551847 | 7.178462484835099 | 6.856861210882991 |
2.YUV
#计算熵
Y = entropy(data_Y)
U = entropy(data_U)
V = entropy(data_V)
result:
Y | U | V |
---|---|---|
6.3318185418675075 | 5.126401914399721 | 4.113143002049819 |
Four, summary
It can be obtained from the calculation result that storing this image in YUV format can compress it even smaller. Through the file manager, the size of down.rgb is 192kb, while the size of down.yuv is only 96kb, but the knowledge is limited, and it is not clear whether it is related to this (get it back and update).