如何将RGB图像转换为NumPy数组?

160

我有一张 RGB 图像,想将其转换为 numpy 数组。我尝试了以下操作:

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

它创建了一个没有形状的数组。我猜它是一个IplImage对象。


2
如果cv是OpenCV模块,那么你应该将其标记为这样。这个链接可能会有所帮助:http://opencv.willowgarage.com/documentation/python/cookbook.html#numpy-and-opencv - Paul
15个回答

195

您可以使用更新的OpenCV Python接口(如果我没有记错,它自OpenCV 2.2版本起可用)。 它本地使用NumPy数组:

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

结果:

<type 'numpy.ndarray'>

146
注意,cv2.imread()返回的是BGR格式而不是RGB格式的numpy数组。 - pnd
15
@pnd,你的评论是神圣的! - Eduardo Pignatelli
11
供日后参考:使用 $ pip install opencv-python 命令来安装OpenCV。 - krc
12
类型错误:'mode'是imread()函数的无效关键字参数。 - Rishabh Agrahari
16
OpenCV似乎已经删除了mode参数。请看下面的答案以获取更新后的方法。 - belvederef
显示剩余5条评论

102

PIL(Python Imaging Library)和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图像可能如下所示:
out_img = Image.fromarray( ycc_uint8, "RGB" )
out_img.save( "ycc.tif" )

1
这会出现一个错误:TypeError: long() argument must be a string or a number, not 'PixelAccess',查看PIL的PixelAccess类文档,似乎没有提供能够使np.array将其底层数据转换为ndarray格式的方法。您需要省略使用img.load(),只处理Image.open(...)的结果。 - ely
1
img.load() 解决了 PIL 中一个奇怪的缓存问题。数据只有在明确需要时才会被加载。当使用 Pillow(PIL 的分支)时,除了将 "import Image" 更改为 "from PIL import Image" 之外,示例仍然可以正常工作。 - David Poole
1
点赞使用PIL而不是OpenCV。虽然我不反对OpenCV。 - progyammer

91
您也可以使用 matplotlib 来完成此操作。
from matplotlib.image import imread

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

输出结果:<class 'numpy.ndarray'>


3
这很简单。我喜欢它 :) - jeongmin.cha
1
@Mrinal 是的,它有这个功能。 - Rishabh Agrahari
4
这个答案应该被采纳吧?Matplotlib 几乎总是与 numpy 一起安装的,这是一个一行解决方案。所有其他使用 PIL/CV 的答案都是不必要的复杂,并且与实际问题不太相关。当一个一行的解决方案已经几乎内置时,为什么要安装额外的包并增加复杂性呢? - MRule
2
内部使用PIL,所以我猜测它会随着matplotlib一起安装。 - Rahul A Ranger

46

截至今天,你最好的选择是使用:

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 -> RGB 的优点。 - Maf
1
@Maf cv2以BGR格式读取图像,因此第二个函数将其转换为RGB格式,这是人类看到颜色的方式。请参见此图像进行格式比较。 - belvederef
如果你想要转换为灰度图像,你应该使用函数参数 cv2.COLOR_BGR2GRAY - belvederef
@user1767754 刚刚看到这个问题。为什么要这样做?问题是如何将RGB图像转换为numpy数组,你从哪里得到这个灰度的东西啊??? - belvederef
@belvederef 哈哈,我一定是在评论错误的帖子...我的评论根本没有意义。 - user1767754
显示剩余3条评论

17

虽然回答晚了,但我现在更喜欢imageio模块而不是其他替代品。

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

cv2.imread()类似,它默认生成一个numpy数组,但是以RGB形式呈现。


9

您需要使用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数组? - Shan
我认为你需要使用cv.CreateMat,或者使用cv.CreateMat并使用cv.CvtColor或类似的方法从图像复制到mat中。请查看保罗在上面发布的链接。 - Justin Peel

9
你可以通过使用numpyPIL中的Image轻松地获取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

6
使用以下语法加载图像:
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

5

使用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() 可以用于所有文件,但它的速度较慢,因此我只在其他方法失败时使用它。


4

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

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