问题描述
我有一个代码,用于通过调整图像大小并将其划分为 RGB 通道来查找图像的熵信息。
import os
from PIL import Image
import numpy as np
from scipy.misc import imread
import cv2
import imageio
#读取RGB图像
def openRGB(image_path):
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)
return data
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
def getEntropy(image_path):
data =openRGB(image_path)
data_B = data[:,0]
data_G = data[:,1]
data_R = data[:,2]
B = entropy(data_B)
G = entropy(data_G)
R = entropy(data_R)
return (R+B+G)/2;
但是,每当我在给定图像上运行 getentropy() 函数时,它都会返回此错误
ValueError: 无法将大小为 37048 的数组重塑为形状 (65536,3)
知道如何重新格式化图像以适合该数组形状吗?
解决方法
有一个简单的解释:image_path
字节长度仅为 37048
。
使用 np.array(data).reshape((256*256,3))
时,data
的长度必须为 256*256*3
= 196608
字节。
由于长度不匹配,您收到异常。
重现问题很简单。
- 创建一个大小为
196608
字节的输入示例文件,也不例外。 - 创建一个大小为
37048
字节的输入示例文件,得到一个异常。
这是重现问题的代码示例:
import os
#from PIL import Image
import numpy as np
#from scipy.misc import imread
#import cv2
#import imageio
def openRGB(image_path):
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)
return data
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
def getEntropy(image_path):
data = openRGB(image_path)
data_B = data[:,0]
data_G = data[:,1]
data_R = data[:,2]
B = entropy(data_B)
G = entropy(data_G)
R = entropy(data_R)
return (R+B+G)/2
# Create a binary file with random bytes
image_path = 'tmp.bin'
# When n_bytes=196608,there is no exception.
################################################################################
n_bytes = 256*256*3
tmp = np.random.randint(0,255,n_bytes,np.uint8) # Build random array of n_bytes bytes
with open(image_path,'wb') as f:
f.write(tmp) # Write tmp to a binary file
file_size_in_bytes = os.path.getsize(image_path)
print('file_size_in_bytes = ' + str(file_size_in_bytes))
res = getEntropy(image_path)
print(res)
################################################################################
# When n_bytes=37048,an exception is raised: ValueError: cannot reshape array of size 37048 into shape (65536,3)
################################################################################
n_bytes = 37048
tmp = np.random.randint(0,'wb') as f:
f.write(tmp) # Write tmp to a binary file
file_size_in_bytes = os.path.getsize(image_path)
print('file_size_in_bytes = ' + str(file_size_in_bytes))
res = getEntropy(image_path)
print(res)
################################################################################
为什么要读取 37048
字节而不是 196608
字节?
image_path
是一个 JPEG 图像文件,您正在使用 f = open(image_path,"rb")
和 data = f.read()
读取图像。
您可以按如下方式阅读和重塑图像:
import cv2
def openRGB(image_path):
# For example: image_path = 'img.jpg'
img = cv2.imread(image_path) # Read image in BGR color format.
data = np.array(img).reshape(img.shape[0]*img.shape[1],3) # Reshape to rows x cols x 3 (Blue in data[:,0],green in data[:,1],red in data[:,2]).
return data
在上面的例子中我使用了img.shape[0]*img.shape[1]
,图像分辨率是:
height = img.shape[0]
width = img.shape[1]