แปลงภาพจาก PIL เป็นรูปแบบ openCV


101

ฉันกำลังพยายามแปลงภาพจากPILเป็นOpenCVรูปแบบ ฉันกำลังใช้OpenCV 2.4.3. นี่คือสิ่งที่ฉันพยายามจนถึงตอนนี้

>>> from PIL import Image
>>> import cv2 as cv
>>> pimg = Image.open('D:\\traffic.jpg')                           #PIL Image
>>> cimg = cv.cv.CreateImageHeader(pimg.size,cv.IPL_DEPTH_8U,3)    #CV Image
>>> cv.cv.SetData(cimg,pimg.tostring())
>>> cv.cv.NamedWindow('cimg')
>>> cv.cv.ShowImage('cimg',cimg)
>>> cv.cv.WaitKey()

แต่ฉันคิดว่ารูปภาพไม่ได้รับการแปลงเป็นรูปแบบ CV หน้าต่างแสดงภาพสีน้ำตาลขนาดใหญ่ ฉันผิดพลาดตรงไหนในการแปลงรูปภาพPILเป็นCVรูปแบบ

นอกจากนี้ทำไมฉันต้องพิมพ์cv.cvเพื่อเข้าถึงฟังก์ชัน


อาจซ้ำกันได้: stackoverflow.com/questions/1650568/…
ทิม

ฉันอ้างถึงคำถามที่คุณพูดถึง แต่วิธีแก้ปัญหาที่ได้รับดูเหมือนจะไม่ได้ผลสำหรับฉัน
md1hunox

ฉันคิดว่าคุณต้องแปลงภาพจาก RGB เป็น BGR ตรวจสอบว่าใช้งานได้หรือไม่
Froyo

คำตอบ:


172

ใช้สิ่งนี้:

pil_image = PIL.Image.open('Image.jpg').convert('RGB') 
open_cv_image = numpy.array(pil_image) 
# Convert RGB to BGR 
open_cv_image = open_cv_image[:, :, ::-1].copy() 

2
ขอบคุณโปรดอธิบายรายละเอียดว่าบรรทัดสุดท้ายเป็นอย่างไร
md1hunox

17
คุณมีภาพ RGB ที่แสดงโดยอาร์เรย์ 3 มิติเช่นเดียวกับในex = numpy.array([ [ [1, 2, 3], [4, 5, 6] ], [ [7, 8, 9], [0, 1, 2] ] ])ไฟล์. ดังนั้นex[0]เป็นบรรทัดแรกของภาพของคุณex[0][0]เป็นคอลัมน์แรกของบรรทัดแรกex[0][0][0]เป็นองค์ประกอบสีแดงของพิกเซลแรกex[0][0][1]เป็นองค์ประกอบสีเขียวและex[0][0][2]เป็นองค์ประกอบสีฟ้า เนื่องจากคุณต้องการภาพ BGR (ลำดับผกผันของ RGB) คุณจึงสลับองค์ประกอบแต่ละส่วนที่อธิบายพิกเซลในรูปแบบex[0][0][::-1]. บรรทัดสุดท้าย (ยกเว้นแบบไร้ประโยชน์.copy) เท่ากับการดำเนินการนี้สำหรับภาพทั้งหมด
mmgp

16
อาจเป็นเพียงการปรับปรุงประสิทธิภาพเล็กน้อย แต่ cv2.cvtColor(open_cv_image, cv2.cv.CV_BGR2RGB) มีประสิทธิภาพมากขึ้นเล็กน้อย
GuillaumeDufay

อะไรคือจุดประสงค์ของ. แปลง ('RGB') ในคำตอบของคุณ? ฉันกำลังทำงานกับภาพสีเทา 16 บิต (โหมดภาพ = I; 16) .. จนถึงตอนนี้ nparray ยังคงรักษาภาพไว้เป็นวัตถุ PIL.Image เดียว (เช่นอาร์เรย์ที่มีเพียงรายการเดียวคือ PIL.Image ดั้งเดิม)
user391339

3
หากรูปภาพเป็นไบนารี (ตัวอย่างเช่นไบนารีที่สแกนTIF) อาร์เรย์ตัวเลขจะเป็นboolดังนั้นคุณจะไม่สามารถใช้กับ OpenCV ได้ ในกรณีนี้คุณต้องแปลงเป็น OpenCV mask:if image.dtype == bool: image = image.astype(np.uint8) * 255
Maksym Ganenko

99

นี่เป็นเวอร์ชันที่สั้นที่สุดที่ฉันสามารถหาได้โดยบันทึก / ซ่อนการแปลงเพิ่มเติม:

pil_image = PIL.Image.open('image.jpg')
opencvImage = cv2.cvtColor(numpy.array(pil_image), cv2.COLOR_RGB2BGR)

หากอ่านไฟล์จาก URL:

import cStringIO
import urllib
file = cStringIO.StringIO(urllib.urlopen(r'http://stackoverflow.com/a_nice_image.jpg').read())
pil_image = PIL.Image.open(file)
opencvImage = cv2.cvtColor(numpy.array(pil_image), cv2.COLOR_RGB2BGR)

2
หากดาวน์โหลดจาก url ฉันจะไปกับ:import requests response = requests.get(url) opencvImage = imdecode(np.asarray(bytearray(response.content)), 1)
Lior

4
ฉันจะแปลงรูปภาพพิลเป็นเสื่ออีกครั้งได้อย่างไร

คำตอบของคุณส่งกลับข้อผิดพลาดนี้: OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor
Färid Alijani

ได้ผล เหตุใดทุกคนในโลกงูหลามจึงไม่ระบุการนำเข้า
pscheit

0

โค้ดที่แสดงความคิดเห็นใช้งานได้เช่นกันเพียงแค่เลือกที่คุณต้องการ

import numpy as np
from PIL import Image


def convert_from_cv2_to_image(img: np.ndarray) -> Image:
    # return Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    return Image.fromarray(img)


def convert_from_image_to_cv2(img: Image) -> np.ndarray:
    # return cv2.cvtColor(numpy.array(img), cv2.COLOR_RGB2BGR)
    return np.asarray(img)

วิธีที่สองทำเช่นนั้นแปลงรูปภาพจาก PIL เป็น cv2 ฉันโพสต์สองวิธีในการทำเช่นนั้นวิธีหนึ่งอยู่ในความคิดเห็น เพียงแค่เลือกสิ่งที่คุณต้องการ ฉันยังโพสต์วิธีการทำตรงกันข้ามแม่มดเป็นวิธีแรกซึ่งแสดงให้เห็นสองวิธีในการทำวิธีหนึ่งแสดงความคิดเห็นเพียงแค่เลือกสิ่งที่คุณต้องการ
Pedro Nunes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.