Respostas:
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'>
$ pip install opencv-python
para instalar o opencv
TypeError: 'mode' is an invalid keyword argument for imread()
mode
argumento. Veja minha resposta abaixo para um método atualizado.
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" )
TypeError: long() argument must be a string or a number, not 'PixelAccess'
e , examinando a documentação da PixelAccess
classe PIL , não parece oferecer métodos que permitiriam np.array
converter seus dados subjacentes em um ndarray
formato. Você precisa omitir o uso de img.load()
e lidar apenas com o resultado de Image.open(...)
.
Você também pode usar matplotlib para isso.
from matplotlib.image import imread
img = imread('abc.tiff')
print(type(img))
resultado:
<class 'numpy.ndarray'>
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á img
que será uma matriz numpy do tipo:
<class 'numpy.ndarray'>
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)
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.
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
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.
Você pode obter uma matriz numpy de imagem rgb facilmente usando numpy
eImage 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
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
cv
for o módulo OpenCV, você deve marcá-lo como tal. Este link pode ajudar: opencv.willowgarage.com/documentation/python/…