【问题标题】:how to convert an RGB image to numpy array?如何将 RGB 图像转换为 numpy 数组?
【发布时间】:2011-12-07 10:57:23
【问题描述】:

我有一个 RGB 图像。我想将其转换为 numpy 数组。我做了以下

im = cv.LoadImage("abc.tiff")
a = numpy.asarray(im)

它创建一个没有形状的数组。我假设它是一个 iplimage 对象。

【问题讨论】:

标签: python image opencv numpy


【解决方案1】:

您可以使用更新的 OpenCV python 接口(如果我没记错的话,它自 OpenCV 2.2 起就可用)。它本机使用 numpy 数组:

import cv2
im = cv2.imread("abc.tiff",mode='RGB')
print type(im)

结果:

<type 'numpy.ndarray'>

【讨论】:

  • 注意 cv2.imread() 在 BGR 而不是 RGB 中返回一个 numpy 数组。
  • @pnd 你的评论是神圣的!
  • 供以后参考:$ pip install opencv-python 安装opencv
  • TypeError: 'mode' is an invalid keyword argument for imread()
  • OpenCV 似乎已经放弃了 mode 参数。请参阅下面的答案以获取更新的方法。
【解决方案2】:

PIL(Python 图像库)和 Numpy 可以很好地协同工作。

我使用以下函数。

from PIL import Image
import numpy as np

def load_image( infilename ) :
    img = Image.open( infilename )
    img.load()
    data = np.asarray( img, dtype="int32" )
    return data

def save_image( npdata, outfilename ) :
    img = Image.fromarray( np.asarray( np.clip(npdata,0,255), dtype="uint8"), "L" )
    img.save( outfilename )

“Image.fromarray”有点难看,因为我将传入的数据剪辑到 [0,255],转换为字节,然后创建灰度图像。我大部分时间都是灰色的。

RGB 图像类似于:

 outimg = Image.fromarray( ycc_uint8, "RGB" )
 outimg.save( "ycc.tif" )

【讨论】:

  • 这失败并出现错误 TypeError: long() argument must be a string or a number, not 'PixelAccess' 并查看 PIL 的 PixelAccess 类的文档,它似乎没有提供使 np.array 能够将其基础数据转换为 @ 987654326@ 格式。需要省略img.load()的使用,只处理Image.open(...)的结果。
  • img.load() 解决了 PIL 中一个奇怪的缓存问题。在明确需要之前不会加载数据。除了在使用 Pillow(PIL fork)时将“import Image”更改为“from PIL import Image”之外,该示例仍然适用于我。
  • 赞成只使用 PIL 而不是 OpenCV。不过我并不反对 OpenCV。
【解决方案3】:

您也可以为此使用matplotlib

from matplotlib.image import imread

img = imread('abc.tiff')
print(type(img))

输出: &lt;class 'numpy.ndarray'&gt;

【讨论】:

  • 这很简单。我喜欢它:)
  • @Mrinal 是的,确实如此。
  • 这应该是公认的答案吧? Matplotlib 几乎总是与 numpy 一起安装,这是一种单行解决方案。所有这些使用 PIL/CV 的其他答案都不必要地复杂,并且与实际问题的相关性较低。当实际上内置了一条线解决方案时,为什么还要安装额外的软件包并增加复杂性?
  • 它在内部使用,PIL 所以我猜它是和 matplotlib 一起安装的
【解决方案4】:

从今天开始,您最好的选择是使用:

img = cv2.imread(image_path)   # reads an image in the BGR format
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)   # BGR -> RGB

你会看到 img 将是一个类型为 numpy 的数组:

<class 'numpy.ndarray'>

【讨论】:

  • 对不起,我需要知道这条线的优点img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # BGR -&gt; RGB
  • @Maf cv2 读取 BGR 格式的图像,因此第二个函数将其转换为 RGB 格式,这就是我们人类看到颜色的方式。格式比较见this image
  • 谢谢@belvederef
  • 这与将图像转换为灰度有什么关系?
  • @user1767754 如果要转换为灰度,可以使用函数参数cv2.COLOR_BGR2GRAY
【解决方案5】:

迟到的答案,但我开始更喜欢 imageio 模块而不是其他替代方案

import imageio
im = imageio.imread('abc.tiff')

类似于cv2.imread(),默认生成一个numpy数组,但是是RGB形式的。

【讨论】:

    【解决方案6】:

    你需要使用 cv.LoadImageM 而不是 cv.LoadImage:

    In [1]: import cv
    In [2]: import numpy as np
    In [3]: x = cv.LoadImageM('im.tif')
    In [4]: im = np.asarray(x)
    In [5]: im.shape
    Out[5]: (487, 650, 3)
    

    【讨论】:

    • 非常感谢...您能否帮我找出如果我使用 'cv.CreateImage(width,height,channels)' 创建图像...如何转换到 numpy 数组?
    • 我认为您需要改用 cv.CreateMat 或使用 cv.CreateMat 并使用 cv.CvtColor 或类似的东西从图像复制到垫子。看看 Paul 在上面发布的链接。
    【解决方案7】:

    当使用 David Poole 的答案时,我得到一个带有灰度 PNG 和其他文件的 SystemError。我的解决方案是:

    import numpy as np
    from PIL import Image
    
    img = Image.open( filename )
    try:
        data = np.asarray( img, dtype='uint8' )
    except SystemError:
        data = np.asarray( img.getdata(), dtype='uint8' )
    

    实际上 img.getdata() 对所有文件都有效,但速度较慢,所以我只在其他方法失败时使用它。

    【讨论】:

      【解决方案8】:

      使用以下语法加载图像:-

      from keras.preprocessing import image
      
      X_test=image.load_img('four.png',target_size=(28,28),color_mode="grayscale"); #loading image and then convert it into grayscale and with it's target size 
      X_test=image.img_to_array(X_test); #convert image into array
      

      【讨论】:

        【解决方案9】:

        您可以使用numpyImage from PIL 轻松获取 rgb 图像的 numpy 数组

        import numpy as np
        from PIL import Image
        import matplotlib.pyplot as plt
        
        im = Image.open('*image_name*') #These two lines
        im_arr = np.array(im) #are all you need
        plt.imshow(im_arr) #Just to verify that image array has been constructed properly
        

        【讨论】:

          【解决方案10】:

          OpenCV 图像格式支持 numpy 数组接口。可以使用辅助函数来支持灰度或彩色图像。这意味着 BGR -> RGB 转换可以方便地使用 numpy 切片完成,而不是图像数据的完整副本。

          注意:这是一个跨步技巧,因此修改输出数组也会改变 OpenCV 图像数据。如果你想要一个副本,请在数组上使用.copy() 方法!

          import numpy as np
          
          def img_as_array(im):
              """OpenCV's native format to a numpy array view"""
              w, h, n = im.width, im.height, im.channels
              modes = {1: "L", 3: "RGB", 4: "RGBA"}
              if n not in modes:
                  raise Exception('unsupported number of channels: {0}'.format(n))
              out = np.asarray(im)
              if n != 1:
                  out = out[:, :, ::-1]  # BGR -> RGB conversion
              return out
          

          【讨论】:

            【解决方案11】:

            我也采用了 imageio,但我发现以下机器对预处理和后处理很有用:

            import imageio
            import numpy as np
            
            def imload(*a, **k):
                i = imageio.imread(*a, **k)
                i = i.transpose((1, 0, 2))  # x and y are mixed up for some reason...
                i = np.flip(i, 1)  # make coordinate system right-handed!!!!!!
                return i/255
            
            
            def imsave(i, url, *a, **k):
                # Original order of arguments was counterintuitive. It should
                # read verbally "Save the image to the URL" — not "Save to the
                # URL the image."
            
                i = np.flip(i, 1)
                i = i.transpose((1, 0, 2))
                i *= 255
            
                i = i.round()
                i = np.maximum(i, 0)
                i = np.minimum(i, 255)
            
                i = np.asarray(i, dtype=np.uint8)
            
                imageio.imwrite(url, i, *a, **k)
            

            理由是我使用 numpy 进行图像处理,而不仅仅是图像显示。为此,uint8s 很尴尬,所以我转换为 0 到 1 范围内的浮点值。

            保存图像时,我注意到我必须自己剪切超出范围的值,否则我最终会得到一个非常灰色的输出。 (灰度输出是 imageio 将 [0, 256) 之外的整个范围压缩为范围内的值的结果。)

            还有其他一些奇怪的东西,我在 cmets 中提到过。

            【讨论】:

              【解决方案12】:

              使用 Keras:

              from keras.preprocessing import image
                
              img = image.load_img('path_to_image', target_size=(300, 300))
              x = image.img_to_array(img)
              x = np.expand_dims(x, axis=0)
              images = np.vstack([x])
              

              【讨论】:

                【解决方案13】:

                尝试定时将图像加载到 numpy 数组的选项,它们非常相似。使用plt.imread 是为了简单和快速。

                def time_this(function, times=100):
                    cum_time = 0
                    for t in range(times):
                        st = time.time()
                        function()
                        cum_time += time.time() - st
                    return cum_time / times
                
                import matplotlib.pyplot as plt
                def load_img_matplotlib(img_path):
                    return plt.imread(img_path)
                
                import cv2
                def load_img_cv2(img_path):
                    return cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2RGB)
                
                from PIL import Image
                import numpy as np
                def load_img_pil(img_path):
                    img = Image.open(img_path)
                    img.load()
                    return np.asarray( img, dtype="int32" )
                
                if __name__=='__main__':
                    img_path = 'your_image_path'
                    for load_fn in [load_img_pil, load_img_cv2, load_img_matplotlib]:
                        print('-'*20)
                        print(time_this(lambda: load_fn(img_path)), 10000)
                

                结果:

                --------------------
                0.0065201687812805175 10000  PIL, as in [the second answer][1]https://stackoverflow.com/a/7769424/16083419)
                --------------------
                0.0053211402893066405 10000  CV2
                --------------------
                0.005320906639099121 10000  matplotlib
                

                【讨论】:

                  【解决方案14】:

                  您可以尝试以下方法。这是docs的链接。

                  tf.keras.preprocessing.image.img_to_array(img, data_format=None, dtype=None)
                  from PIL import Image
                  img_data = np.random.random(size=(100, 100, 3))
                  img = tf.keras.preprocessing.image.array_to_img(img_data)
                  array = tf.keras.preprocessing.image.img_to_array(img)
                  

                  【讨论】:

                    猜你喜欢
                    • 2018-08-22
                    • 1970-01-01
                    • 2021-04-02
                    • 2018-09-28
                    • 2014-12-28
                    • 1970-01-01
                    • 2018-07-21
                    • 2023-03-17
                    相关资源
                    最近更新 更多