วิธีการแปลงภาพ RGB เป็นอาร์เรย์ numpy?


114

ฉันมีภาพ RGB ฉันต้องการแปลงเป็นอาร์เรย์ numpy ฉันทำสิ่งต่อไปนี้

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

มันสร้างอาร์เรย์ที่ไม่มีรูปร่าง ฉันคิดว่ามันเป็นวัตถุ iplimage


2
หากcvเป็นโมดูล OpenCV คุณควรติดแท็กดังกล่าว ลิงค์นี้อาจช่วยได้: opencv.willowgarage.com/documentation/python/…
พอล

คำตอบ:


143

คุณสามารถใช้อินเทอร์เฟซ Python OpenCV ที่ใหม่กว่าได้ (ถ้าฉันจำไม่ผิดมันมีให้ตั้งแต่ OpenCV 2.2) มันใช้อาร์เรย์ numpy โดยกำเนิด:

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

ผลลัพธ์:

<type 'numpy.ndarray'>

97
ระวังว่า cv2.imread () ส่งคืนอาร์เรย์ numpy ใน BGR ไม่ใช่ RGB
pnd

7
@pnd ความคิดเห็นของคุณศักดิ์สิทธิ์!
Eduardo Pignatelli

5
สำหรับการอ้างอิงในอนาคต: $ pip install opencv-pythonเพื่อติดตั้ง opencv
Kyle C

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

8
ดูเหมือนว่า OpenCV จะเลิกmodeโต้แย้ง ดูคำตอบของฉันด้านล่างสำหรับวิธีการที่อัปเดต
belvederef

73

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

1
สิ่งนี้ล้มเหลวด้วยข้อผิดพลาดTypeError: long() argument must be a string or a number, not 'PixelAccess'และเมื่อดูเอกสารสำหรับPixelAccessคลาสของ PIL ดูเหมือนว่าจะไม่มีวิธีการที่จะช่วยให้np.arrayสามารถแปลงข้อมูลพื้นฐานเป็นndarrayรูปแบบได้ คุณต้องละเว้นการใช้img.load()และจัดการกับผลลัพธ์ของImage.open(...).
ely

img.load () แก้ไขปัญหาการแคชแปลก ๆ ใน PIL ข้อมูลจะไม่ถูกโหลดจนกว่าจำเป็นอย่างชัดเจน ตัวอย่างนี้ยังคงใช้ได้สำหรับฉันยกเว้นการเปลี่ยน "import Image" เป็น "from PIL import Image" เมื่อทำงานกับ Pillow (ที่ส้อม PIL)
David Poole

โหวตขึ้นสำหรับการใช้ PIL เท่านั้นไม่ใช่ OpenCV ฉันไม่ได้ต่อต้าน OpenCV
progyammer


20

ณ วันนี้ทางออกที่ดีที่สุดของคุณคือใช้:

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

คุณจะเห็นimgว่าเป็นอาร์เรย์ numpy ประเภท:

<class 'numpy.ndarray'>

12

คำตอบช้า แต่ฉันชอบimageioโมดูลมากกว่าทางเลือกอื่น

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

คล้ายกับcv2.imread()จะสร้างอาร์เรย์ numpy ตามค่าเริ่มต้น แต่อยู่ในรูปแบบ RGB


7

คุณต้องใช้ 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)

ขอบคุณมาก ... โปรดช่วยฉันด้วยในการค้นหาว่าถ้าฉันสร้างภาพโดยใช้ 'cv.CreateImage (ความกว้างความสูงช่อง)' ... จะแปลงเป็นอาร์เรย์จำนวนนับได้อย่างไร
ฉาน

ฉันคิดว่าคุณต้องใช้ cv.CreateMat แทนหรือใช้ cv.CreateMat และคัดลอกจากภาพไปยังเสื่อโดยใช้ cv.CvtColor หรือสิ่งที่คล้ายกัน ลองดูลิงค์ที่ Paul โพสต์ไว้ด้านบน
Justin Peel

3

เมื่อใช้คำตอบจาก David Poole ฉันได้รับ SystemError พร้อม 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 () ใช้ได้กับทุกไฟล์ แต่ช้ากว่าดังนั้นฉันจึงใช้มันก็ต่อเมื่อวิธีอื่นล้มเหลว


2

รูปแบบภาพ OpenCV รองรับอินเทอร์เฟซอาร์เรย์ numpy ฟังก์ชันตัวช่วยสามารถรองรับได้ทั้งภาพระดับสีเทาหรือสี ซึ่งหมายความว่าการแปลง BGR -> RGB สามารถทำได้อย่างสะดวกด้วยชิ้นส่วนที่เป็นตัวเลขไม่ใช่สำเนาข้อมูลภาพทั้งหมด

หมายเหตุ: นี่เป็นเคล็ดลับการก้าวดังนั้นการแก้ไขอาร์เรย์เอาต์พุตจะเปลี่ยนข้อมูลรูปภาพ OpenCV ด้วย หากคุณต้องการสำเนาให้ใช้.copy()วิธีการในอาร์เรย์!

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

ฉันใช้ 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

เมื่อบันทึกภาพฉันสังเกตเห็นว่าฉันต้องตัดค่านอกช่วงด้วยตัวเองไม่เช่นนั้นฉันก็ได้ผลลัพธ์ที่เป็นสีเทาจริงๆ (เอาต์พุตสีเทาเป็นผลมาจากการบีบอัด imageio เต็มช่วงซึ่งอยู่นอก [0, 256) ไปยังค่าที่อยู่ภายในช่วง)

มีสิ่งแปลกประหลาดอีกสองสามอย่างเช่นกันซึ่งฉันพูดถึงในความคิดเห็น


1

คุณสามารถรับอาร์เรย์ของภาพ rgb ได้อย่างง่ายดายโดยใช้numpyและImage 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

โหลดภาพโดยใช้ไวยากรณ์ต่อไปนี้: -

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.