como converter uma imagem RGB para numpy array?


Respostas:


142

Você pode usar a interface python OpenCV mais recente (se não me engano, ela está disponível desde o OpenCV 2.2). Ele usa matrizes numpy nativamente:

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

resultado:

<type 'numpy.ndarray'>

94
Esteja ciente de que cv2.imread () retorna um array numpy em BGR e não em RGB.
— PND

6
@pnd seu comentário é sagrado!
— Eduardo Pignatelli

4
Para referência futura: $ pip install opencv-pythonpara instalar o opencv
— Kyle C

2
TypeError: 'mode' is an invalid keyword argument for imread()
— Rishabh Agrahari

8
OpenCV parece ter abandonado o modeargumento. Veja minha resposta abaixo para um método atualizado.
— belvederef

73

PIL (Python Imaging Library) e Numpy funcionam bem juntos.

Eu uso as seguintes funções.

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 )

O 'Image.fromarray' é um pouco feio porque recortei os dados recebidos para [0,255], converti em bytes e, em seguida, crio uma imagem em tons de cinza. Eu trabalho principalmente em cinza.

Uma imagem RGB seria algo como:

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

1
Isso falha com um erro TypeError: long() argument must be a string or a number, not 'PixelAccess'e , examinando a documentação da PixelAccessclasse PIL , não parece oferecer métodos que permitiriam np.arrayconverter seus dados subjacentes em um ndarrayformato. Você precisa omitir o uso de img.load()e lidar apenas com o resultado de Image.open(...).
— ely

O img.load () contorna um problema estranho de cache no PIL. Os dados não seriam carregados até que fossem explicitamente necessários. O exemplo ainda funciona para mim, com exceção de alterar "import Image" para "from PIL import Image" ao trabalhar com Pillow (o fork PIL).
— David Poole

Voto positivo para usar apenas PIL e não OpenCV. Não sou contra o OpenCV.
— progyammer


19

A partir de hoje, sua melhor aposta é usar:

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

Você verá imgque será uma matriz numpy do tipo:

<class 'numpy.ndarray'>

12

Resposta tardia, mas passei a preferir o imageiomódulo às outras alternativas

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

Semelhante a cv2.imread(), ele produz uma matriz numpy por padrão, mas no formato RGB.


7

Você precisa usar cv.LoadImageM em vez de 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)

Muito obrigado ... Você também poderia me ajudar a descobrir que se eu criar uma imagem usando 'cv.CreateImage (largura, altura, canais)' ... Como ela poderia ser convertida em array numpy?
— Shan,

Eu acho que você precisa usar cv.CreateMat em vez disso ou usar cv.CreateMat e copiar da imagem para o tapete usando cv.CvtColor ou algo semelhante. Dê uma olhada no link que Paul postou acima.
— Justin Peel,

3

Ao usar a resposta de David Poole, recebo um SystemError com PNGs em escala de cinza e talvez outros arquivos. Minha solução é:

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

Na verdade, img.getdata () funcionaria para todos os arquivos, mas é mais lento, então eu o uso apenas quando o outro método falha.


2

O formato de imagem OpenCV suporta a interface numpy array. Uma função auxiliar pode ser criada para suportar imagens em tons de cinza ou coloridas. Isso significa que a conversão BGR -> RGB pode ser feita convenientemente com uma fatia numpy, não uma cópia completa dos dados da imagem.

Nota: este é um truque de passos largos, portanto, modificar a matriz de saída também mudará os dados da imagem OpenCV. Se você quiser uma cópia, use o .copy()método no array!

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

Eu também adotei a imageio, mas achei a seguinte máquina útil para pré e pós-processamento:

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)

O raciocínio é que estou usando o numpy para processamento de imagens, não apenas para exibição de imagens. Para este propósito, uint8s são estranhos, então eu converto em valores de ponto flutuante que variam de 0 a 1.

Ao salvar imagens, percebi que eu mesmo tive que cortar os valores fora do intervalo, ou então acabei com uma saída realmente cinza. (A saída cinza foi o resultado da compressão de imageio em toda a faixa, que estava fora de [0, 256), para valores que estavam dentro da faixa.)

Havia algumas outras curiosidades também, que mencionei nos comentários.


1

Você pode obter uma matriz numpy de imagem rgb facilmente usando numpyeImage 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

carregue a imagem usando a seguinte sintaxe: -

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.