简体   繁体   English

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

[英]Display 2D array from OpenCV in Matplotlib.pyplot.imshow()

I have a setup in Python where I use the OpenCV library to read the frames of a video in as 2D arrays--these videos are grayscale, so I'm using unsigned 8-bit integers for the pixel values. 我有一个Python设置,我使用OpenCV库以2D阵列的形式读取视频的帧 - 这些视频是灰度的,所以我使用无符号的8位整数作为像素值。

In my next step, I'm trying to use pyplot.imshow() from matplotlib to display the frame of the video. 在下一步中,我尝试使用matplotlib中的pyplot.imshow()来显示视频的帧。 Unfortunately, I'm getting something that doesn't make any sense at all. 不幸的是,我得到的东西根本没有任何意义。

Here's the code to read the 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 is a utility function that converts the OpenCV array to a numpy array (just a call to fromstring and then a reshape ). cv2numpy是一个实用程序函数,它将OpenCV数组转换为numpy数组(只需调用fromstring然后reshape fromstring )。 Here's the code I'm using to plot the first frame of the 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()

In some other code, I used the OpenCV SaveImage on a single frame to provide a reference for what I would expect from imshow . 在其他一些代码中,我在一个帧上使用OpenCV SaveImage来提供我对imshow期望。 Here's the image I get from the former , and here's the image I get from the code above . 这是我从前者得到的图像这是我从上面的代码中得到的图像

As you can see they're wildly different. 正如你所看到的,它们完全不同。 The only thing I can glean from the actual image is the striping: it looks almost like it's getting the dimensions wrong, that there are more pixels in the width than the height (this image is supposed to be 128 x 256). 我可以从实际图像中收集的唯一内容是条纹:它看起来几乎就像是尺寸错误,宽度上的像素多于高度(此图像应该是128 x 256)。 But I've tried transposing the array before plotting it, changing the extent and aspect and shape parameters as per the imshow documentation , and with the exception of some bizarre pixel stretching I haven't found a fix. 但我已经尝试在绘制它之前调换数组,根据imshow文档更改extentaspectshape参数,除了一些奇怪的像素拉伸我还没有找到修复。

Any thoughts? 有什么想法吗?

EDIT 1: I figure it may be prudent to add the cv2numpy code, in case that reshaping is somehow muddling things (since my "truth" image above does not use that code and hence cv2numpy is involved only in the questionable pipeline). 编辑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

I believe that the problem is with your cv2numpy function. 我相信问题出在你的cv2numpy函数上。 Try this one: 试试这个:

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

It did the trick for me. 它为我做了伎俩。 If you aren't using a grayscale input (I know that you said you are using grayscale now) then you will need to convert using cv.CreateImage and cv.CvtColor. 如果你没有使用灰度输入(我知道你说你现在使用的是灰度),那么你需要使用cv.CreateImage和cv.CvtColor进行转换。

Are you using version 2.3.1? 你使用的是2.3.1版吗? Using cv2 API, we don't need implement our own version of OpenCV/Numpy conversion anymore. 使用cv2 API,我们不再需要实现我们自己的OpenCV / Numpy转换版本。 For example, the following code works just right: 例如,以下代码工作正常:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM