数值错误:无法将形状为(224,224,3)的输入数组广播到形状为(224,224)的数组。

114

我有一个列表,称为temp_list,具有以下属性:

len(temp_list) = 9260  
temp_list[0].shape = (224,224,3)  

现在,当我将其转换为numpy数组时,

x = np.array(temp_list)  

我收到了错误信息:

ValueError: could not broadcast input array from shape (224,224,3) into shape (224,224)  

有人能帮我吗?


3
我想我们需要使用 np.flatten()。 - Aditya
4
压扁会扭曲数组的形状。 - neel
1
你想让它成什么形状? 你正在尝试从3D数组列表中创建一个新数组,因此最终数组可以是3D或4D。使用np.dstack(或np.hstacknp.vstack)可能会有所帮助。 - user707650
我已经检查过了,所有元素都是3D的,具有形状(224,224,3)。 - neel
你能告诉我们 sum([item.size for item in temp_list]) 的输出结果吗? - user707650
你是对的,一个元素的形状为(224,224,360)。 - neel
10个回答

115

您的列表中至少有一个项目不是三维的,或者它的第二或第三维与其他元素不匹配。如果只有第一维不匹配,则数组仍然匹配,但作为单独的对象,不会尝试将它们调和成一个新的(四维)数组。以下是一些示例:

也就是说,有问题的元素的 shape != (?, 224, 3)
或者 ndim != 3(其中 ? 是非负整数)。
这就是导致错误的原因。

您需要修复它,才能将您的列表转换为四维(或三维)数组。没有上下文,无法确定您是想从三维项目中减少一个维度还是在二维项目中增加一个维度(在第一种情况下),或更改第二或第三维度(在第二种情况下)。


这是一个错误的示例:
>>> a = [np.zeros((224,224,3)), np.zeros((224,224,3)), np.zeros((224,224))]
>>> np.array(a)
ValueError: could not broadcast input array from shape (224,224,3) into shape (224,224)

或者,不同类型的输入,但是相同的错误:

>>> a = [np.zeros((224,224,3)), np.zeros((224,224,3)), np.zeros((224,224,13))]
>>> np.array(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not broadcast input array from shape (224,224,3) into shape (224,224)

或者,类似但带有不同的错误信息:

>>> a = [np.zeros((224,224,3)), np.zeros((224,224,3)), np.zeros((224,100,3))]
>>> np.array(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: could not broadcast input array from shape (224,224,3) into shape (224)

但是以下代码将会运行,尽管结果可能与预期有所不同:
>>> a = [np.zeros((224,224,3)), np.zeros((224,224,3)), np.zeros((10,224,3))]
>>> np.array(a)
# long output omitted
>>> newa = np.array(a)
>>> newa.shape
3  # oops
>>> newa.dtype
dtype('O')
>>> newa[0].shape
(224, 224, 3)
>>> newa[1].shape
(224, 224, 3)
>>> newa[2].shape
(10, 224, 3)
>>> 

6
好的,这里回答了错误的原因,但如何解决它呢。我遇到了相同的问题,但在我的情况下,我正在使用img_to_array()函数将原始图像直接转换为np.array,使用的是tensorflow。因此,我没有特权将其转换为.astype(object),如@YinJie Gao所提到的那样。谢谢您的帮助。 - Shashank Shukla

14

是的,@Evert 的回答完全正确。此外,我想再添加一种可能会遇到这种错误的情况。

>>> np.array([np.zeros((20,200)),np.zeros((20,200)),np.zeros((20,200))])

这样做是完全没有问题的。然而,这会导致ValueError

>>> np.array([np.zeros((20,200)),np.zeros((20,200)),np.zeros((20,201))])

ValueError: could not broadcast input array from shape (20,200) into shape (20)

列表中的numpy数组也必须具有相同的大小。


1
感谢您提供的额外信息。我的问题正如您所提到的那样,内部ndarrays的形状是不同的。 - Aaron Shen
2
谢谢你的补充,我正好遇到了这个问题。有趣的是,如果在第二种情况下交换20和200/201,它就可以工作,这让我感到非常困惑。在这种情况下,Numpy不会创建一个3D数组,而是创建一个包含2D数组的1D数组。所以,从一个看似无害的变化中得到了完全不同的行为。有点令人沮丧。 - Cerno

12
你可以使用 astype(object)numpy.ndarray 转换为 object
这将有效:
>>> a = [np.zeros((224,224,3)).astype(object), np.zeros((224,224,3)).astype(object), np.zeros((224,224,13)).astype(object)]

7

我也遇到了同样的问题,因为我的数据集中有一些灰度图像,所以我通过以下方式解决了这个问题。

    from PIL import Image
    img = Image.open('my_image.jpg').convert('RGB')
    # a line from my program
    positive_images_array = np.array([np.array(Image.open(img).convert('RGB').resize((150, 150), Image.ANTIALIAS)) for img in images_in_yes_directory])

我遇到过类似的问题,但我决定在我的函数中添加一个 if img.shape == (width, height, 3): 条件,以排除任何灰度图像。这对其他新手可能会有所帮助。 - undefined

3
在我的情况下,问题出在我的数据集上,基本上在进一步处理之前需要对我的数据进行预处理,因为在我的数据集中,图像以随机格式(如RGB和灰度)呈现,因此尺寸不匹配。我只是按照Mudasir Habib的答案操作。
from PIL import Image
img = Image.open('my_image.jpg').convert('RGB')

3

@aravk33的答案是完全正确的。

我也遇到了同样的问题。我的数据集中有2450张图片,我就是弄不清楚为什么会出现这个问题。

检查你训练数据中所有图像的尺寸。

将以下代码片段添加到将图像附加到列表中的代码中:

if image.shape==(1,512,512):
    trainx.append(image)

3

这种方法不需要修改numpy数组的dtype或ravel。

核心思想是: 1.初始化一个额外的行。 2.将具有一个额外行的列表更改为数组。 3.在结果数组中删除额外的行。 例如:

>>> a = [np.zeros((10,224)), np.zeros((10,))]
>>> np.array(a)
# this will raise error,
ValueError: could not broadcast input array from shape (10,224) into shape (10)

# but below method works
>>> a = [np.zeros((11,224)), np.zeros((10,))]
>>> b = np.array(a)
>>> b[0] = np.delete(b[0],0,0)
>>> print(b.shape,b[0].shape,b[1].shape)
# print result:(2,) (10,224) (10,)

实际上,并不一定需要添加一行,只要你能够避免 @aravk33 和 @user707650 的答案中提到的间隙,并稍后删除多余的项目,就可以了。


1

已解决 - 我遇到了同样的错误: X_test = np.array(X_test, ) ValueError:无法将形状为(50,50,3)的输入数组广播成形状为(50,50)

打印出每个图像的形状,得到如下结果:

~

1708: (50, 50, 3)

1709: (50, 50)

1710: (50, 50)

1711: (50, 50, 3)

1712: (50, 50, 3)

1713: (50, 50, 3)

~

这意味着读取两个不同的图像文件夹并将它们洗牌后混合1D和3D数据。 img:第一个是灰度图像,第二个是彩色图像 添加了cv2.IMREAD_GRAYSCALE,问题得到解决。
总结: 我想将图像数据转换为np数组,其中包含不同维度的图像。
-> 检查图像数据
-> 发现有1D和3D图像
-> 使3D图像变成灰度(1D)
-> 问题已解决

这也解决了我的问题。谢谢。 - Lyrk

0
我完全同意@mudassir的答案。如果您已经增加了数据集,那么很可能会出现这个错误。在大多数增强中,它自动应用灰度效果,这实际上是二维的,而原始图片(RGB)是三维的。
我自己使用的是roboflow的数据集,已经进行了增强,并且也遇到了类似的问题。然后我删除了“灰度处理步骤”,但仍然出现了错误。但是,当我删除灰度、色调和饱和度时,它就像魔术一样运行了。我建议您也尝试一下。

0
Numpy会自动统一数组,如果发现只有小于等于1个维度不同的话。 如果您不想要一个统一的数组(所有元素形状相同),您可以尝试这个解决方法:
x = np.emtpy(len(temp_list), dtype=object)
for i, arr in enumerate(temp_list):
    x[i] = arr

希望能对你有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接