在Matplotlib.pyplot.imshow()中从OpenCV显示2D数组

时间:2012-01-23 19:01:58

标签: python opencv matplotlib computer-vision

我在Python中有一个设置,我使用OpenCV库以2D阵列的形式读取视频帧 - 这些视频是灰度的,所以我使用无符号8位整数作为像素值。

在下一步中,我尝试使用matplotlib中的pyplot.imshow()来显示视频的帧。不幸的是,我得到的东西根本没有任何意义。

以下是阅读视频的代码:

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所期望的参考。 Here's the image I get from the formerhere's the image I get from the code above

正如你所看到的,它们完全不同。我可以从实际图像中收集的唯一内容是条纹:它看起来几乎就像是尺寸错误,宽度上的像素多于高度(此图像应该是128 x 256)。但是我在绘制数据之前尝试过调换数组,根据imshow documentation更改extentaspect以及shape参数,并且除了一些奇怪的像素拉伸之外我还没有找到解决办法。

有什么想法吗?

编辑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 个答案:

答案 0 :(得分:5)

我认为问题在于你的cv2numpy功能。试试这个:

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

它为我做了伎俩。如果你没有使用灰度输入(我知道你说你现在使用的是灰度),那么你需要使用cv.CreateImage和cv.CvtColor进行转换。

答案 1 :(得分:1)

您使用的是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()