2012-01-23 64 views
8

Tôi có một thiết lập bằng Python, nơi tôi sử dụng thư viện OpenCV để đọc các khung của một video ở dạng mảng 2D - những video này là màu xám, vì vậy tôi sử dụng số nguyên 8 bit chưa được ký cho các giá trị pixel.Hiển thị mảng 2D từ OpenCV trong Matplotlib.pyplot.imshow()

Trong bước tiếp theo, tôi đang cố gắng sử dụng pyplot.imshow() từ matplotlib để hiển thị khung của video. Thật không may, tôi nhận được một cái gì đó mà không có ý nghĩa gì cả.

Dưới đây là đoạn code để đọc video:

import numpy as np 
import cv 

def read_video(filename): 
    video = cv.CaptureFromFile('%s' % filename) 
    num_frames = int(cv.GetCaptureProperty(video, cv.CV_CAP_PROP_FRAME_COUNT)) 

    frames = [] 
    for i in range(0, num_frames): 
    frame = cv.QueryFrame(video) 
    if frame is None: 
     quit('Failed to extract frame %s of %s!' % (i, num_frames)) 
    toadd = cv2numpy(frame, 'uint8') 
    frames.append(np.array(toadd)) 
    return np.array(frames) 

cv2numpy là một chức năng hữu ích có thể chuyển đổi các mảng OpenCV để một mảng NumPy (chỉ cần một cuộc gọi đến fromstring và sau đó một reshape). Dưới đây là đoạn code tôi đang sử dụng để vẽ khung đầu tiên của video:

import matplotlib.pyplot as plot 
import matplotlib.cm as cm 

frames = read_video('video.avi') 
plot.imshow(frames[0], cmap = cm.gray) 
plot.show() 

Trong một số mã khác, tôi đã sử dụng OpenCV SaveImage trên một khung duy nhất để cung cấp một tài liệu tham khảo cho những gì tôi mong chờ từ imshow. Here's the image I get from the formerhere's the image I get from the code above.

Như bạn có thể thấy chúng cực kỳ khác nhau. Điều duy nhất tôi có thể thu thập từ hình ảnh thực tế là dải phân cách: có vẻ như nó bị sai kích thước, có nhiều pixel hơn chiều rộng hơn chiều cao (ảnh này được cho là 128 x 256). Nhưng tôi đã cố gắng chuyển mảng trước khi vẽ đồ thị, thay đổi các thông số extentaspectshape theo imshow documentation và ngoại trừ một số điểm ảnh kỳ lạ mà tôi không tìm thấy bản sửa lỗi.

Mọi suy nghĩ?

EDIT 1: Tôi hình dung nó có thể là khôn ngoan để thêm mã cv2numpy, trong trường hợp đó định hình lại được bằng cách nào đó muddling vật (kể từ khi tôi "chân lý" hình ảnh trên không sử dụng mã đó và vì thế cv2numpy chỉ tham gia vào việc đường ống có vấn đề).

def cv2numpy(cvarr, the_type): 
    a = np.fromstring(
     cvarr.tostring(), 
     dtype = the_type, 
     count = cvarr.width * cvarr.height) 
    a.shape = (cvarr.height, cvarr.width) 
    return a 

Trả lời

5

Tôi tin rằng vấn đề là với hàm cv2numpy của bạn. Hãy dùng thử sản phẩm này:

def cv2numpy(cvarr, the_type): 
    a = np.asarray(cv.GetMat(cvarr), dtype=the_type) 
    return a 

Nó đã làm điều đó cho tôi. Nếu bạn không sử dụng một đầu vào màu xám (tôi biết rằng bạn đã nói bạn đang sử dụng màu xám bây giờ) thì bạn sẽ cần phải chuyển đổi bằng cách sử dụng cv.CreateImage và cv.CvtColor.

+0

Đây chính xác là vấn đề. OpenCV vẫn đọc các video như RGB, vì vậy tôi đã thêm vào trong 'cv.CreateImage' và' cv.CvtColor', in ra hình ảnh, và nó trông giống như những gì tôi mong đợi. Cám ơn rất nhiều! Dường như chuyển đổi các mảng OpenCV thành các mảng có nhiều mảng thông qua chuỗi là tối ưu. – Magsol

1

Bạn đang sử dụng phiên bản 2.3.1? Sử dụng API cv2, chúng tôi không cần triển khai phiên bản OpenCV/Numpy của riêng mình nữa. Ví dụ: mã sau hoạt động vừa phải:

>>> import cv2 
>>> from matplotlib import pyplot as plt 
>>> lenna = cv2.imread('lenna.tiff', cv2.CV_LOAD_IMAGE_GRAYSCALE) 
>>> lenna 
array([[162, 162, 162, ..., 170, 155, 128], 
     [162, 162, 162, ..., 170, 155, 128], 
     [162, 162, 162, ..., 170, 155, 128], 
     ..., 
     [ 43, 43, 50, ..., 104, 100, 98], 
     [ 44, 44, 55, ..., 104, 105, 108], 
     [ 44, 44, 55, ..., 104, 105, 108]], dtype=uint8) 
>>> plt.imshow(lenna, cmap='gray') 
>>> plt.show() 
+0

Đây có thể là một câu hỏi ngớ ngẩn, nhưng làm thế nào tôi có thể xác định phiên bản OpenCV mà tôi đang sử dụng? Tất cả những gì tôi thấy là một tùy chọn '.__ version__', nhưng nó chỉ cho tôi biết bản sửa đổi. – Magsol

+0

@Magsol, các phiên bản gần đây của OpenCV trình bày cả hai giao diện. Bạn có thể sử dụng "import cv" và "import cv2". Hãy thử "nhập khẩu cv2" và xem những gì bạn nhận được. Cũng sử dụng hệ thống quản lý gói của bạn để tìm phiên bản OpenCV bạn có trong hệ thống của mình.Hoặc biên dịch từ các nguồn (xem http://goo.gl/8ds4i). –

+0

Tài liệu cơ sở Sphinx OpenCV hiển thị cả hai giao diện, nhưng giao diện cv được coi là "kế thừa". http://opencv.itseez.com/ –

Các vấn đề liên quan