Как преобразовать изображение RGB в массив NumPy? - PullRequest
74 голосов
/ 14 октября 2011

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

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

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

Ответы [ 9 ]

102 голосов
/ 15 октября 2011

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

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

результат:

<type 'numpy.ndarray'>
51 голосов
/ 14 октября 2011

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" )
34 голосов
/ 06 октября 2017

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

from matplotlib.image import imread

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

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

9 голосов
/ 24 апреля 2018

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

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

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

6 голосов
/ 14 октября 2011

Вам нужно использовать 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)
4 голосов
/ 10 марта 2019

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

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'>
2 голосов
/ 14 октября 2011
def opencv_image_as_array(im):
  """Interface image from OpenCV's native format to a numpy array.

  note: this is a slicing trick, and modifying the output array will also change
  the OpenCV image data.  if you want a copy, use .copy() method on the array!
  """
  import numpy as np
  w, h, n = im.width, im.height, im.channels
  modes = {1:"L", 3:"RGB"}#, 4:"RGBA"}
  if n not in modes:
    raise StandardError('unsupported number of channels: {0}'.format(n))
  out = np.asarray(im) if n == 1 else np.asarray(im)[:,:,::-1]  ## BGR -> RGB
  return out
1 голос
/ 28 ноября 2016

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

0 голосов
/ 11 мая 2018

Я также принял 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), до значений, которые были внутри диапазона.)

Была еще пара странностей, о которых я упоминал в комментариях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...