2009-10-30 85 views
10

我想用OpenCV做一些圖像處理(使用Python),但我必須從一個PIL Image對象開始,所以我不能使用cvLoadImage()調用,因爲這需要一個文件名。如何從PIL圖像創建OpenCV圖像?

此配方(改編自http://opencv.willowgarage.com/wiki/PythonInterface)不起作用,因爲cvSetData抱怨argument 2 of type 'void *'。有任何想法嗎?

from opencv.cv import * 
from PIL import Image 

pi = Image.open('foo.png')      # PIL image 
ci = cvCreateImage(pi.size, IPL_DEPTH_8U, 1)  # OpenCV image 
data = pi.tostring() 
cvSetData(ci, data, len(data)) 

我覺得最後一個參數cvSetData是錯的太多,但我不知道它應該是什麼。

+1

你在上面鍵入的代碼中有(cvSetData)一個未定義的名稱,所以它的很難知道你是否真的嘗試過。 – 2009-10-30 15:47:17

+0

@Jonathan:我沒有看到你提到的錯誤。 cvSetData的確是一個在opencv.cv中定義的有效函數 – Arkady 2009-10-30 16:22:54

+0

當前答案的狀態是什麼? – 2010-04-13 20:45:01

回答

8

您嘗試調整的示例是針對OpenCV 2.0的新python界面。這可能是前綴和非前綴函數名稱(cv.cvSetData()cv.SetData())之間混淆的根源。

的OpenCV 2.0現在一般用兩組蟒綁定:

錯誤消息背後的原因是SWIG包裝per不處理從python字符串到普通的舊C緩衝區的轉換。但是,SWIG包裝附帶opencv.adaptors模塊,該模塊旨在支持從numpyPIL圖像到OpenCV的轉換。

以下(測試)的代碼應該解決您原來的問題(轉化率從PIL到OpenCV的),使用SWIG接口:

# PIL to OpenCV using the SWIG wrapper 
from opencv import cv, adaptors, highgui 
import PIL 

pil_img = PIL.Image.open(filename) 

cv_img = adaptors.PIL2Ipl(pil_img) 

highgui.cvNamedWindow("pil2ipl") 
highgui.cvShowImage("pil2ipl", cv_img) 

然而,這並沒有解決的事實cv.cvSetData()函數總是失敗(使用當前的SWIG包裝器實現)。 然後,您可以使用新的風格的包裝,它允許您使用cv.SetData()功能,你會期望:

# PIL to OpenCV using the new wrapper 
import cv 
import PIL 

pil_img = PIL.Image.open(filename)  

cv_img = cv.CreateImageHeader(pil_img.size, cv.IPL_DEPTH_8U, 3) # RGB image 
cv.SetData(cv_img, pil_img.tostring(), pil_img.size[0]*3) 

cv.NamedWindow("pil2ipl") 
cv.ShowImage("pil2ipl", cv_img) 

第三種方法是你的OpenCV的Python接口切換到ctypes-based wrapper。它帶有實用功能,可在例如python字符串和C緩衝區。快速瀏覽google code search似乎表明這是一種工作方法。

關於cvSetData()函數的第三個參數,圖像緩衝區的大小,但圖像的步驟。步驟是圖像的一行中的字節數,即pixel_depth * number_of_channels * image_widthpixel_depth參數是與一個通道關聯的數據的大小(以字節爲單位)。在你的例子中,它只是圖像的寬度(只有一個通道,每個像素一個字節)。

+0

@sevas:我還沒有接受你的答案,因爲我使用的是OpenCV的2.0版本。直到我將cv.CreateImageHeader更改爲cvCreateImage和cv.SetData更改爲cvSetData之前,鏈接到的頁面上的配方根本無法工作,所以我仍對此感到困惑。我打算用ctypes-opencv試試你的方法,如果這樣做的話,我會在這裏發佈我的發現。 – Arkady 2009-11-02 18:34:20

+0

@scrible:我添加了關於與OpenCV 2.0一起發佈的兩組併發綁定的信息。我可能會繼續尋找更好的解決方案。 – 2009-11-02 21:25:03

+0

@scrible:我用我能找到的最新信息更新了答案(具體來說,adaptators模塊和兩套python綁定。) – 2009-11-03 15:36:42

4

讓swig和新的python綁定真的讓人困惑。例如,在OpenCV 2.0中,cmake可以接受BUILD_SWIG_PYTHON_SUPPORT和BUILD_NEW_PYTHON_SUPPORT。但無論如何,我有點想出了大部分的陷阱。

在使用「import cv」(新的python綁定)的情況下,還需要一個步驟。

由於PIL和IplImage中的順序不同,轉換對RGB圖像是必需的。這同樣適用於Ipl至PIL。

但是,如果你使用opencv.adaptors,它已經被照顧了。如果感興趣,可以查看adaptors.py中的詳細信息。

3

我這樣做使用OpenCV2.1的python2.6的綁定:

... 
    cv_img = cv.CreateImageHeader(img.size, cv.IPL_DEPTH_8U, 3) 
    cv.SetData(cv_img, img.rotate(180).tostring()[::-1]) 
    ... 

圖像旋轉和字符串的復原是交換RGB成BGR的是,在OpenCV的視頻編碼被使用。我認爲這對於從PIL轉換成OpenCV的圖像的任何其他用途也是必需的。

0

我不是專家,但我設法從PIL圖像獲得OpenCV的圖像與此代碼:

import opencv 

img = opencv.adaptors.PIL2Ipl(pilimg)