bagaimana cara mengubah gambar RGB ke array numpy?

113

Saya memiliki gambar RGB. Saya ingin mengubahnya menjadi array numpy. Saya melakukan hal berikut

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

Ini membuat array tanpa bentuk. Saya menganggap itu adalah objek iplimage.

Shan
sumber
2
Jika cvadalah modul OpenCV, maka Anda harus menandainya seperti itu. Tautan ini mungkin membantu: opencv.willowgarage.com/documentation/python/…
Paul

Jawaban:

142

Anda dapat menggunakan antarmuka python OpenCV yang lebih baru (jika saya tidak salah itu tersedia sejak OpenCV 2.2). Ini secara native menggunakan array numpy:

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

hasil:

<type 'numpy.ndarray'>
Andrey Kamaev
sumber
95
Berhati-hatilah bahwa cv2.imread () mengembalikan array numpy di BGR bukan RGB.
pnd
6
@pnd komentar Anda sakral!
Eduardo Pignatelli
4
Untuk referensi di masa mendatang: $ pip install opencv-pythonuntuk menginstal opencv
Kyle C
2
TypeError: 'mode' is an invalid keyword argument for imread()
Rishabh Agrahari
8
OpenCV tampaknya telah menjatuhkan modeargumen. Lihat jawaban saya di bawah untuk metode yang diperbarui.
belvederef
73

PIL (Python Imaging Library) dan Numpy bekerja sama dengan baik.

Saya menggunakan fungsi berikut.

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' sedikit jelek karena saya memotong data yang masuk ke [0,255], mengonversinya ke byte, lalu membuat gambar grayscale. Saya kebanyakan bekerja dengan warna abu-abu.

Gambar RGB akan menjadi seperti ini:

 outimg = Image.fromarray( ycc_uint8, "RGB" )
 outimg.save( "ycc.tif" )
David Poole
sumber
1
Ini gagal karena kesalahan, TypeError: long() argument must be a string or a number, not 'PixelAccess'dan melihat dokumentasi untuk PixelAccesskelas PIL , tampaknya tidak menawarkan metode yang akan memungkinkan np.arrayuntuk mengubah data yang mendasarinya ke dalam ndarrayformat. Anda perlu menghilangkan penggunaan img.load()dan hanya menangani hasil dari Image.open(...).
ely
Img.load () mengatasi masalah caching yang aneh di PIL. Data tidak akan dimuat sampai dibutuhkan secara eksplisit. Contoh ini masih berfungsi untuk saya dengan pengecualian mengubah "import Image" menjadi "from PIL import Image" saat bekerja dengan Pillow (garpu PIL).
David Poole
Beri suara positif untuk menggunakan PIL saja dan bukan OpenCV. Saya tidak menentang OpenCV.
progyammer
54

Anda juga dapat menggunakan matplotlib untuk ini.

from matplotlib.image import imread

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

keluaran: <class 'numpy.ndarray'>

Rishabh Agrahari
sumber
2
Ini sangat sederhana. Saya menyukainya :)
jeongmin.cha
@Mrinal Ya, benar.
Rishabh Agrahari
19

Mulai hari ini, taruhan terbaik Anda adalah menggunakan:

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

Anda akan melihat imgakan menjadi jenis array numpy:

<class 'numpy.ndarray'>
belvederef
sumber
12

Jawaban terlambat, tapi saya datang untuk lebih memilih imageiomodul daripada alternatif lain

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

Mirip dengan cv2.imread(), ini menghasilkan array numpy secara default, tetapi dalam bentuk RGB.

slizb
sumber
7

Anda perlu menggunakan cv.LoadImageM, bukan 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)
Justin Peel
sumber
Terima kasih banyak ... Bisakah Anda juga membantu saya untuk mengetahui bahwa jika saya membuat gambar menggunakan 'cv.CreateImage (lebar, tinggi, saluran)' ... Bagaimana cara mengubahnya menjadi numpy array?
Shan
Saya pikir Anda perlu menggunakan cv.CreateMat sebagai gantinya atau menggunakan cv.CreateMat dan menyalin dari gambar ke tikar menggunakan cv.CvtColor atau yang serupa. Lihat link yang diposting Paul di atas.
Justin Peel
3

Saat menggunakan jawaban dari David Poole, saya mendapatkan SystemError dengan PNG skala abu-abu dan mungkin file lainnya. Solusi saya adalah:

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

Sebenarnya img.getdata () akan berfungsi untuk semua file, tetapi lebih lambat, jadi saya menggunakannya hanya ketika metode lain gagal.

daign
sumber
2

Format gambar OpenCV mendukung antarmuka numpy array. Fungsi pembantu dapat dibuat untuk mendukung gambar grayscale atau berwarna. Ini berarti konversi BGR -> RGB dapat dengan mudah dilakukan dengan potongan numpy, bukan salinan lengkap data gambar.

Catatan: ini adalah trik langkah, jadi memodifikasi larik keluaran juga akan mengubah data gambar OpenCV. Jika Anda ingin menyalin, gunakan .copy()metode pada 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
wim
sumber
1

Saya juga mengadopsi imageio, tetapi saya menemukan mesin berikut berguna untuk pra-dan pasca-pemrosesan:

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)

Alasannya adalah saya menggunakan numpy untuk pemrosesan gambar, bukan hanya menampilkan gambar. Untuk tujuan ini, uint8 terasa canggung, jadi saya mengonversi ke nilai floating point mulai dari 0 hingga 1.

Saat menyimpan gambar, saya perhatikan saya harus memotong sendiri nilai di luar kisaran, atau saya akan mendapatkan keluaran yang benar-benar abu-abu. (Keluaran abu-abu adalah hasil dari imageio yang mengompresi rentang penuh, yang berada di luar [0, 256), ke nilai yang berada di dalam rentang.)

Ada beberapa keanehan lain juga, yang saya sebutkan di komentar.

enigmaticPhysicist
sumber
1

Anda bisa mendapatkan berbagai gambar rgb dengan mudah dengan menggunakan numpydanImage 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
joker007
sumber
0

memuat gambar dengan menggunakan sintaks berikut: -

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
Disha Doshi
sumber