2009-10-30 45 views
10

Tôi muốn thực hiện một số xử lý hình ảnh với OpenCV (bằng Python), nhưng tôi phải bắt đầu với đối tượng PIL Image, vì vậy tôi không thể sử dụng cuộc gọi cvLoadImage() vì tên đó có tên.Làm cách nào để tạo hình ảnh OpenCV từ hình ảnh PIL?

Công thức này (được điều chỉnh từ http://opencv.willowgarage.com/wiki/PythonInterface) không hoạt động vì cvSetData khiếu nại argument 2 of type 'void *'. Bất kỳ ý tưởng?

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

Tôi nghĩ rằng đối số cuối cùng để các cvSetData là sai quá, nhưng tôi không chắc chắn những gì nó nên được.

+1

Mã bạn nhập vào ở trên có một cái tên không xác định trong đó (cvSetData), vì vậy nó khó biết liệu bạn có thực sự thử nó hay không. –

+0

@ Jonathan: Tôi không gặp lỗi bạn đã đề cập. cvSetData thực sự là một hàm hợp lệ được xác định trong opencv.cv – Arkady

+0

Trạng thái của câu trả lời là gì? –

Trả lời

8

Ví dụ bạn đã cố gắng thích ứng là giao diện python mới cho OpenCV 2.0. Đây có lẽ là nguồn gốc của sự nhầm lẫn giữa tên hàm có tiền tố và không có tiền tố (cv.cvSetData() so với cv.SetData()).

OpenCV 2.0 tại tàu với hai bộ bindings python:

  • Các "old-style" python wrapper, một gói python với opencv.{cv,highgui,ml} module
  • Các new interface, một phần mở rộng python C (cv.pyd), mà kết thúc tốt đẹp tất cả các OpenCV chức năng (bao gồm các mô hình highguiml.)

Lý do đằng sau thông báo lỗi là gói SWIG mỗi không xử lý chuyển đổi từ một chuỗi python đến một bộ đệm C cũ. Tuy nhiên, trình bao bọc SWIG đi kèm với mô-đun opencv.adaptors, được thiết kế để hỗ trợ chuyển đổi từ các hình ảnh numpyPIL sang OpenCV.

Sau đây (thử nghiệm) Mã nên giải quyết vấn đề ban đầu của bạn (chuyển đổi từ PIL để OpenCV), sử dụng giao diện 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) 

Tuy nhiên, điều này không giải quyết được thực tế rằng cv.cvSetData() chức năng sẽ luôn luôn thất bại (với thực thi trình bao bọc SWIG hiện tại). Sau đó bạn có thể sử dụng các wrapper kiểu mới, cho phép bạn sử dụng cv.SetData() chức năng như bạn mong chờ:

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

Một cách tiếp cận thứ ba sẽ được chuyển giao diện OpenCV python của bạn vào ctypes-based wrapper. Nó đi kèm với các chức năng tiện ích để chuyển đổi dữ liệu rõ ràng giữa ví dụ: python strings và C buffer. Một cái nhìn nhanh chóng trên google code search dường như chỉ ra rằng đây là một phương pháp làm việc.

Liên quan đến tham số thứ ba của hàm cvSetData(), kích thước của bộ đệm hình ảnh, nhưng bước hình ảnh. Bước là số byte trong một hàng của hình ảnh của bạn, là pixel_depth * number_of_channels * image_width. Tham số pixel_depth là kích thước tính theo byte của dữ liệu được liên kết với một kênh. Trong ví dụ của bạn, nó sẽ chỉ đơn giản là chiều rộng hình ảnh (chỉ có một kênh, một byte cho mỗi pixel).

+0

@sevas: Tôi chưa chấp nhận câu trả lời của bạn (bởi vì tôi * đang sử dụng phiên bản 2.0 của OpenCV. Các công thức trên trang tôi liên kết đến đã không làm việc ở tất cả cho đến khi tôi thay đổi cv.CreateImageHeader để cvCreateImage và cv.SetData để cvSetData, vì vậy tôi vẫn còn nhầm lẫn về điều đó. Tôi sẽ thử cách tiếp cận của bạn với ctypes-opencv và nếu nó hoạt động, tôi sẽ đăng các phát hiện của tôi ở đây. – Arkady

+0

@scrible: Tôi đã thêm thông tin về hai tập hợp liên kết vận chuyển với OpenCV 2.0. Tôi có lẽ sẽ tiếp tục tìm kiếm một giải pháp tốt hơn mặc dù. –

+0

@scrible: Tôi đã cập nhật câu trả lời bằng cách sử dụng thông tin mới nhất mà tôi có thể tìm thấy (cụ thể, mô đun bộ điều hợp và hai bộ ràng buộc python.) –

4

Thật sự khó hiểu khi có cả ràng buộc trăn và mới. Ví dụ, trong OpenCV 2.0, cmake có thể chấp nhận cả BUILD_SWIG_PYTHON_SUPPORT và BUILD_NEW_PYTHON_SUPPORT. Nhưng dù sao, tôi cũng đã tìm ra nhiều cạm bẫy nhất.

Trong trường hợp sử dụng "nhập khẩu cv" (liên kết python mới), cần thêm một bước nữa.

Chuyển đổi là cần thiết cho hình ảnh RGB vì trình tự khác nhau trong PIL và IplImage. Điều tương tự cũng áp dụng đối với Ipl đối với PIL.

Nhưng nếu bạn sử dụng opencv.adaptors, nó đã được xử lý. Bạn có thể xem xét các chi tiết trong adaptors.py nếu quan tâm.

3

Tôi đã làm điều này bằng cách sử dụng các ràng buộc python2.6 của OpenCV2.1:

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

Vòng xoay hình ảnh và sự trở lại của chuỗi là để trao đổi RGB thành BGR, được sử dụng trong mã hóa video OpenCV. Tôi cho rằng điều này cũng sẽ cần thiết cho bất kỳ việc sử dụng hình ảnh nào khác được chuyển đổi từ PIL sang OpenCV.

0

Tôi không phải là một chuyên gia nhưng tôi quản lý để có được một hình ảnh opencv từ một hình ảnh PIL với mã này:

import opencv 

img = opencv.adaptors.PIL2Ipl(pilimg) 
Các vấn đề liên quan