Показать 2D-массив из OpenCV в Matplotlib.pyplot.imshow () - PullRequest
8 голосов
/ 23 января 2012

У меня есть настройка в Python, где я использую библиотеку OpenCV для считывания кадров видео в виде двумерных массивов - это видео в оттенках серого, поэтому я использую 8-разрядные целые числа без знака для значений пикселей.

На следующем шаге я пытаюсь использовать pyplot.imshow() из matplotlib для отображения кадра видео.К сожалению, я получаю то, что не имеет никакого смысла вообще.

Вот код для чтения видео:

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 - это служебная функция, которая преобразуетOpenCV массив в массив Numpy (просто вызов fromstring и затем reshape).Вот код, который я использую для построения первого кадра видео:

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

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

В каком-то другом коде я использовал OpenCV SaveImage на одном кадре, чтобы дать ссылку на то, что я ожидалот imshow. Вот изображение, которое я получаю от прежнего , а вот изображение, которое я получаю из кода выше .

Как вы можете видеть, они сильно отличаются.Единственное, что я могу извлечь из фактического изображения, это чередование: похоже, что он неправильно определяет размеры, что в пикселях больше ширины, чем высоты (это изображение должно быть 128 x 256).Но я попытался транспонировать массив перед его построением, изменив параметры extent и aspect и shape в соответствии с документацией imshow , и за исключением некоторого странного растяжения пикселей, которое у меня не было 'не нашел исправления.

Есть какие-нибудь мысли?

РЕДАКТИРОВАТЬ 1: Я полагаю, было бы разумно добавить код cv2numpy, в случае, если изменение формы каким-то путаницейвещи (поскольку мое изображение «истины» выше не использует этот код и, следовательно, cv2numpy участвует только в сомнительном конвейере).

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

Ответы [ 2 ]

5 голосов
/ 24 января 2012

Я считаю, что проблема в вашей функции cv2numpy.Попробуйте это:

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

Это помогло мне.Если вы не используете данные в градациях серого (я знаю, что вы сказали, что сейчас используете шкалу серого), вам нужно будет конвертировать, используя cv.CreateImage и cv.CvtColor.

1 голос
/ 25 января 2012

Вы используете версию 2.3.1?Используя cv2 API, нам больше не нужно реализовывать собственную версию преобразования OpenCV / Numpy.Например, следующий код работает правильно:

>>> 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...