将PIL图像转换为numpy数组,结果看起来混乱/剪切

p3rjfoxz  于 2023-01-26  发布在  其他
关注(0)|答案(4)|浏览(198)

我正在尝试编写一个Python函数,该函数获取RGB图像,查看每个像素的RGB值(0-255),然后简单地求出三个值的平均值。

def avgcolors(img_matrix):
    M, N, D = img_matrix.shape
    new_img = np.zeros((M, N))
    for i in range(M):
        for j in range(N):
            pixel_mean = int(np.round(np.mean(img_matrix[i][j])))
            new_img[i][j] = pixel_mean
    return(new_img)

对我来说,这个问题看起来非常简单,用i,j遍历图像矩阵索引像素,找到每个像素的三个值的平均值,并将其写入新的图像矩阵,但是,当我运行以下命令时,奇怪的事情发生了:

pic = Image.open("red.jpg")
img = np.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3)
grayscale = avgcolors(img)
plt.imshow(grayscale, cmap='gray')

“red.jpg”图像和输出如下所示:

我本以为当脚本达到红色像素时,它会将值255,0,0平均,得到一个值为85的灰色像素。而在其他地方,它只会是黑色。相反,我没有得到它,我得到了奇怪的对角线伪像。我做错了什么?我不知道。

k10s72fa

k10s72fa1#

您可以简单地使用img = np.array(pic),因为PIL和numpy就是这样理解对方的。
不应使用.getdata()调用,因为它效率较低。
.reshape * 确实 * 篡改了数据,但不一定 *。
你遇到的问题是你把宽度和高度搞混了。

  • PIL.Image.size是一个(width, height)元组。
  • Numpy要求 * 形状 * 为(height, width, channels)

如果使用(pic.size[1], pic.size[0], 3)形状,则原始代码可以正常工作。

fdx2calv

fdx2calv2#

我找到问题了。问题出在把图像转换成numpy数组的时候。看起来命令

img = np.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3)

以一种奇怪的方式重新排列数组。我只是将这行代码更改为:

img = np.array(pic)
7rtdyuoh

7rtdyuoh3#

我希望我的理解是正确的......如果您试图计算一个三维数组在特定轴上的平均值,您可以使用np.array.mean(axis=2)

import numpy as np
import matplotlib.pyplot as plt

image = np.random.randint(0, 255, size=(10, 10, 3), dtype=np.uint8)
print(image.shape) # (10,10,3)
plt.imshow(image)
plt.show()

mean_rgb = image.mean(axis=2)
print(mean_rgb.shape) # (10,10)
plt.imshow(mean_rgb,cmap="Greys")
plt.show()

第一节第一节第一节第一节第一次

qij5mzcb

qij5mzcb4#

下面是一个使用列表的实现。

image = np.array([
    np.concatenate([[[0,0,0]]*10]),
    np.concatenate([[[0,0,0]]*10]),
    np.concatenate([[[0,0,0]]*10]),
    np.concatenate([[[0,0,0]]*10]),
    np.concatenate([[[0,0,0]]*10]),
    np.concatenate([[[0,0,0]]*4,[[255,0,0]]*2,[[0,0,0]]*4]),
    np.concatenate([[[0,0,0]]*10]),
    np.concatenate([[[0,0,0]]*10]),
    np.concatenate([[[0,0,0]]*10]),
    np.concatenate([[[0,0,0]]*10]),
    np.concatenate([[[0,0,0]]*10])
])

image = image.tolist()

def mean_image_explicit(image):

    rows = []
    
    for i in range(len(image)):
        cols = []
        for j in range(len(image[0])):
            v = sum(image[i][j]) / len(image[i][j])
            cols.append(v)
        rows.append(cols)
            
    return rows

def mean_image(image):

    rows = [[sum(image[i][j]) / len(image[i][j]) for j in range(len(image[0]))] for i in range(len(image))]

    return rows

avg = mean_image(image)

plt.imshow(image)
plt.show()
plt.imshow(avg,cmap='gray')
plt.show()

相关问题