как преобразовать изображение RGB в массив numpy?

113

У меня есть изображение RGB. Я хочу преобразовать его в массив numpy. Я сделал следующее

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

Он создает массив без формы. Я предполагаю, что это объект iplimage.

Шан
источник
2
Если cvэто модуль OpenCV, вы должны пометить его как таковой. Эта ссылка может помочь: opencv.willowgarage.com/documentation/python/…
Пол,

Ответы:

143

Вы можете использовать более новый интерфейс Python OpenCV (если я не ошибаюсь, он доступен с OpenCV 2.2). Он изначально использует массивы numpy:

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

результат:

<type 'numpy.ndarray'>
Андрей Камаев
источник
95
Помните, что cv2.imread () возвращает массив numpy в BGR, а не в RGB.
pnd
7
@pnd твой комментарий священен!
Эдуардо Пиньятелли
4
Для справки в будущем: $ pip install opencv-pythonдля установки opencv
Kyle C
2
TypeError: 'mode' is an invalid keyword argument for imread()
Ришаб Аграхари
8
OpenCV, похоже, отказался от этого modeаргумента. См. Мой ответ ниже для получения обновленного метода.
belvederef
73

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 будет примерно таким:

 outimg = Image.fromarray( ycc_uint8, "RGB" )
 outimg.save( "ycc.tif" )
Дэвид Пул
источник
1
Это не удается из-за ошибки, TypeError: long() argument must be a string or a number, not 'PixelAccess'и, глядя на документацию для PixelAccessкласса PIL , похоже, что он не предлагает методов, которые позволили np.arrayбы преобразовать его базовые данные в ndarrayформат. Вам нужно отказаться от использования img.load()и иметь дело только с результатом Image.open(...).
ely 05
Img.load () устраняет странную проблему кеширования в PIL. Данные не будут загружены до тех пор, пока они явно не потребуются. Этот пример все еще работает для меня, за исключением того, что при работе с Pillow (вилка PIL) я меняю "import Image" на "from PIL import Image".
Дэвид Пул
Проголосуйте за использование только PIL, а не OpenCV. Но я не против OpenCV.
progyammer
54

Вы также можете использовать для этого matplotlib .

from matplotlib.image import imread

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

вывод: <class 'numpy.ndarray'>

Ришаб Аграхари
источник
2
Это очень просто. Мне это нравится :)
jeongmin.cha
@Mrinal Да, это так.
Ришаб Аграхари
20

На сегодняшний день лучше всего использовать:

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'>
Belvederef
источник
12

Поздний ответ, но я предпочел imageioмодуль другим альтернативам

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

Подобно этому cv2.imread(), он по умолчанию создает массив numpy, но в форме RGB.

Slizb
источник
7

Вам нужно использовать 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 или что-то подобное. Взгляните на ссылку, которую Павел разместил выше.
Джастин Пил,
3

При использовании ответа Дэвида Пула я получаю SystemError с 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 () будет работать для всех файлов, но он медленнее, поэтому я использую его только тогда, когда другой метод не работает.

благоговение
источник
2

Формат изображения OpenCV поддерживает интерфейс массива numpy. Может быть создана вспомогательная функция для поддержки цветных или полутоновых изображений. Это означает, что преобразование 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
слабак
источник
1

Я также использовал 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.

При сохранении изображений я заметил, что мне пришлось самому вырезать значения, выходящие за пределы допустимого диапазона, иначе у меня получился действительно серый результат. (Серый цвет был результатом сжатия imageio всего диапазона, который находился за пределами [0, 256), до значений, которые находились внутри диапазона.)

Также была пара других странностей, о которых я упоминал в комментариях.

загадочныйФизик
источник
1

Вы можете легко получить массив изображений rgb, используя numpyиImage from PIL

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
joker007
источник
0

загрузите изображение, используя следующий синтаксис: -

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
Диша Доши
источник