як конвертувати RGB-зображення в масивний масив?


113

У мене є зображення RGB. Я хочу перетворити його на numpy масив. Я зробив наступне

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

Він створює масив без форми. Я припускаю, що це об’єкт iplimage.


2
Якщо cvце модуль OpenCV, то слід позначити його як такий. Це посилання може допомогти: opencv.willowgarage.com/documentation/python/…
Павло

Відповіді:


142

Ви можете використовувати новіший інтерфейс python OpenCV (якщо я не помиляюся, він доступний з OpenCV 2.2). Він споконвічно використовує масивні масиви:

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

результат:

<type 'numpy.ndarray'>

95
Не забудьте, що cv2.imread () повертає нумерований масив у BGR, а не RGB.
пд

6
@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) та 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

Img.load () працює навколо дивної проблеми кешування в PIL. Дані не завантажуватимуться до явної необхідності. Приклад все ще працює для мене за винятком зміни "імпорту зображення" на "з зображення імпорту PIL" під час роботи з Подушкою (виделкою PIL).
Девід Пул

Оновлення для використання лише PIL, а не OpenCV. Я не проти OpenCV, хоча.
прогіаммер


19

На сьогоднішній день найкраще використовувати:

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'>

12

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

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

Подібно до цього cv2.imread(), він створює масивний масив за замовчуванням, але у формі RGB.


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 (ширина, висота, канали)" ... Як це можна було перетворити на 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 підтримує інтерфейс масивного масиву. Допоміжна функція може бути підтримана або в кольорах сірого, або в кольоровому зображенні. Це означає, що перетворення 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 для обробки зображень, а не лише для зображення. З цією метою uint8s незручно, тому я перетворюю на значення з плаваючою комою від 0 до 1.

Зберігаючи зображення, я помітив, що мені довелося самостійно вирізати значення поза межами діапазону, інакше я отримав справді сірий вихід. (Вихід сірого кольору був результатом стиснення зображення, яке було за межами [0, 256) до значень, що знаходяться в межах діапазону.)

Було ще пару дивацтв, про які я згадував у коментарях.


1

Ви можете легко отримати nummy масив 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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.