在Matplotlib.pyplot.imshow()中显示OpenCV的二维数组
我在用Python做一个项目,使用OpenCV库来读取视频的每一帧,把它们当作二维数组来处理。这些视频是黑白的,所以我用的是无符号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
期望结果的参考。这是我从之前的代码得到的图像,而这是我从上面代码得到的图像。
你可以看到,它们差别很大。我从实际图像中只能看出一些条纹:看起来像是宽度的像素比高度的多(这张图应该是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 个回答
1
你是在用2.3.1版本吗?使用cv2这个接口后,我们不需要自己去实现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()
5
我觉得问题出在你的 cv2numpy 函数上。试试这个:
def cv2numpy(cvarr, the_type):
a = np.asarray(cv.GetMat(cvarr), dtype=the_type)
return a
这个对我有效。如果你不是用灰度图像作为输入(我知道你说你现在在用灰度图像),那么你需要用 cv.CreateImage 和 cv.CvtColor 来进行转换。