【问题标题】:How to combine dimensions in numpy array?如何组合numpy数组中的维度?
【发布时间】:2016-04-02 08:21:51
【问题描述】:

我正在使用OpenCV 将图像读入numpy.array,它们具有以下形状。

import cv2

def readImages(path):
    imgs = []
    for file in os.listdir(path):
        if file.endswith('.png'):
            img = cv2.imread(file)
            imgs.append(img)
    imgs = numpy.array(imgs)
    return (imgs)

imgs = readImages(...)
print imgs.shape  # (100, 718, 686, 3)

每张图片都有 718x686 像素/尺寸。有 100 张图片。

我不想在 718x686 上工作,我想将像素组合成一个维度。也就是说,形状应该看起来像:(100,492548,3)。无论如何,在 OpenCV(或任何其他库)或 Numpy 中是否有允许我这样做的?

【问题讨论】:

  • 我不明白你从哪里得到最终形状。但是,在将它们全部放入一个阵列之前,您是否尝试过重塑?如果有一个名为 X 的 (718, 686) 数组,您可以将其展平为例如这样的行向量 X.reshape((1, -1))。

标签: python opencv numpy


【解决方案1】:

不修改你的阅读功能:

imgs = readImages(...)
print imgs.shape  # (100, 718, 686, 3)

# flatten axes -2 and -3, using -1 to autocalculate the size
pixel_lists = imgs.reshape(imgs.shape[:-3] + (-1, 3))
print pixel_lists.shape  # (100, 492548, 3)

【讨论】:

    【解决方案2】:
    def combine_dims(a, start=0, count=2):
        """ Reshapes numpy array a by combining count dimensions, 
            starting at dimension index start """
        s = a.shape
        return numpy.reshape(a, s[:start] + (-1,) + s[start+count:])
    

    此函数以更通用的方式满足您的需求。

    imgs = combine_dims(imgs, 1) # combines dimension 1 and 2
    # imgs.shape == (100, 718*686, 3)
    

    它通过使用 numpy.reshape 工作,它将一个形状的数组转换为具有相同数据但被视为另一种形状的数组。目标形状只是初始形状,但要组合的尺寸由 -1 代替。 numpy 使用 -1 作为标志来指示它应该自己计算出该维度应该有多大(基于元素的总数。)

    此代码本质上是 Multihunter 答案的简化版本,但我的编辑被拒绝并暗示它应该是一个单独的答案。就这样吧。

    【讨论】:

    • 这是一个更好的解决方案。不知道我是怎么忘记使用 -1 的……无论如何;你更喜欢哪个?我将“查看@Andrew Kay 的答案以获得更简洁的解决方案”添加到我的答案中,或者自己编辑我的答案以使用此版本。
    【解决方案3】:

    如果有人想要的话。这是执行此操作的一般方法

    import functools
    def combine_dims(a, i=0, n=1):
      """
      Combines dimensions of numpy array `a`, 
      starting at index `i`,
      and combining `n` dimensions
      """
      s = list(a.shape)
      combined = functools.reduce(lambda x,y: x*y, s[i:i+n+1])
      return np.reshape(a, s[:i] + [combined] + s[i+n+1:])
    

    有了这个函数,你可以像这样使用它:

    imgs = combine_dims(imgs, 1) # combines dimension 1 and 2
    # imgs.shape = (100, 718*686, 3)
    

    【讨论】:

    • 请测试速度是否与原始重塑相同——我不确定是否是
    • 这个函数使用np.reshape,所以不能和np.reshape一样速度。在 iPython 中使用%timeit,此解决方案几乎使使用具有固定输入的 np.reshape 的成本翻了一番。然而,几乎没有的两倍,仍然是几乎没有;每次执行大约需要 0.9 微秒。 (重塑是 O(1)。即不依赖于数组大小)。为什么?这是个问题吗?
    • 好的,感谢您的测试,我看错了代码
    【解决方案4】:
    import cv2
    import os
    import numpy as np
    
    def readImages(path):
        imgs = np.empty((0, 492548, 3))
        for file in os.listdir(path):
            if file.endswith('.png'):
                img = cv2.imread(file)
                img = img.reshape((1, 492548, 3))
                imgs = np.append(imgs, img, axis=0)
        return (imgs)
    
    imgs = readImages(...)
    print imgs.shape  # (100, 492548, 3)
    

    诀窍是重塑并附加到一个 numpy 数组。硬编码向量的长度 (492548) 不是一个好习惯,所以如果我是你,我还会添加一行来计算这个数字并将其放入一个变量中,以供脚本的其余部分使用。

    【讨论】:

    • 使用-1会让numpy为你计算492548
    猜你喜欢
    • 2017-09-12
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 2018-04-14
    • 2012-11-12
    • 2019-09-19
    • 2020-07-24
    • 1970-01-01
    相关资源
    最近更新 更多