如何转换一个 RGB 图像数组?

我有一个 RGB 图像。我想把它转换成数字数组

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

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

433649 次浏览

你需要使用 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)

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

注意: 这是一个跨步技巧,因此修改输出数组也将改变 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

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 )

Frmarray 有点难看,因为我将传入数据剪切为[0,255] ,转换为字节,然后创建一个灰度图像。我大多穿灰色。

RGB 图像应该是这样的:

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

您可以使用更新的 OpenCV python 接口(如果我没记错的话,它是自 OpenCV 2.2以来提供的)。它本身使用 numpy 数组:

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

结果:

<type 'numpy.ndarray'>

当使用答案从大卫普尔我得到一个灰度 PNG 和可能其他文件的系统错误。我的解决办法是:

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

也可以使用 Matplotlib进行此操作。

from matplotlib.image import imread


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

产出: <class 'numpy.ndarray'>

回答晚了,但我已经开始喜欢 imageio模块的其他选择

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

cv2.imread()类似,默认情况下它会生成一个数字数组,但是是 RGB 形式的。

我也采用了 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 进行图像处理,而不仅仅是图像显示。为此,uint8非常笨拙,因此我将它转换为0到1之间的浮点值。

在保存图像时,我注意到我必须自己剪切超出范围的值,否则我会得到一个真正的灰色输出。(灰度输出是图像压缩全范围的结果,全范围在[0,256)之外,而值在范围之内。)

还有一些其他的怪事,我在评论中提到过。

从今天开始,你最好的选择是:

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

您将看到 img将是一个类型为:

<class 'numpy.ndarray'>

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

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

使用 numpyImage from PIL可以方便地得到 rgb 图像的数字数组

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

使用克拉:

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])

尝试计时选项加载一个图像到数组,他们是非常相似的。为了简单和速度,选择 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

您可以尝试以下方法。

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)

我们可以使用以下功能的开放式 CV2转换 BGR 2 RGB 格式。

RBG_Image = cv2.cvtColor(Image, cv.COLOR_BGR2RGB)