2012-01-23 12 views
8

Mam konfigurację w Pythonie, gdzie używam biblioteki OpenCV do odczytywania ramek wideo w postaci tablic 2D - te filmy są w skali szarości, więc jestem przy użyciu niepodpisanych 8-bitowych liczb całkowitych dla wartości pikseli.Wyświetlam tablicę 2D z OpenCV w Matplotlib.pyplot.imshow()

W następnym kroku próbuję użyć pyplot.imshow() z matplotlib, aby wyświetlić ramkę wideo. Niestety, dostaję coś, co nie ma żadnego sensu.

Oto kod do zapoznania się z filmem:

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 jest funkcją narzędzie, które konwertuje tablicę OpenCV do numpy tablicy (tylko wywołania fromstring a następnie reshape). Oto kod używam do działki pierwsza klatka filmu:

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

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

w jakiś inny kod, użyłem OpenCV SaveImage na jednej klatce, aby zapewnić odniesienie do tego, co można oczekiwać od imshow. Here's the image I get from the former i here's the image I get from the code above.

Jak widać są one zupełnie inne. Jedyną rzeczą, jaką mogę zebrać z rzeczywistego obrazu, jest pasmowanie: wygląda prawie tak, jakby miało błędne wymiary, że jest więcej pikseli na szerokości niż na wysokości (ten obrazek ma być 128 x 256). Ale próbowałem transponować tablicę przed jej wykreśleniem, zmieniając parametry extent i aspect, jak na imshow documentation iz wyjątkiem dziwacznego rozciągania pikseli, nie znalazłem poprawki.

Jakieś myśli?

EDIT 1: I postać może to być rozsądne, aby dodać kod cv2numpy, w przypadku, przekształcanie się jakoś muddling rzeczy (od mojego „prawda” obrazek powyżej nie używa tego kodu i stąd cv2numpy zaangażowany jest tylko w wątpliwy rurociąg).

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 

Odpowiedz

5

Uważam, że problem dotyczy funkcji cv2numpy. Wypróbuj to:

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

Zrobiłem to dla mnie. Jeśli nie używasz wejścia w skali szarości (wiem, że powiedziałeś, że używasz teraz skali szarości), musisz przekonwertować używając cv.CreateImage i cv.CvtColor.

+0

To był dokładnie problem. OpenCV wciąż czytał wideo jako RGB, więc dodałem je w "cv.CreateImage" i "cv.CvtColor", wydrukowałem obraz i wygląda dokładnie tak, jak oczekiwałem. Dzięki wielkie! Najwyraźniej konwersja macierzy OpenCV na numpy tablic za pomocą łańcuchów jest suboptymalna. – Magsol

1

Czy używasz wersji 2.3.1? Korzystając z API API, nie musimy już implementować naszej własnej wersji konwersji OpenCV/Numpy. Na przykład poniższy kod działa poprawnie:

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

To może być głupie pytanie, ale jak mogę określić wersję OpenCV, której używam? Widzę tylko opcję '.__ version__', ale to tylko informuje mnie o wersji. – Magsol

+0

@Magsol, ostatnie wersje OpenCV prezentują oba interfejsy. Możesz użyć "import cv" i "import cv2". Spróbuj "importuj cv2" i zobacz, co otrzymasz. Użyj również swojego systemu zarządzania pakietami, aby znaleźć wersję OpenCV, którą posiadasz w swoim systemie.Lub skompiluj ze źródeł (zobacz http://goo.gl/8ds4i). –

+0

Dokumentacja bazująca na OpenCV Sphinx pokazuje oba interfejsy, ale interfejs cv jest uważany za "starszą". http://opencv.itseez.com/ –

Powiązane problemy