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.