使用matplotlib重现OpenCV的imshow()和waitKey()函数

3
以下代码在Windows上运行良好,但我需要在Ubuntu上运行它,而cv2.imshow()似乎不被支持。我正在寻找一种替代方法,使用matplotlib任何其他在Ubuntu上运行的库。

它的工作原理如下:

我有一个帧列表,其中每个帧都是表示RGB图像的numpy数组。我循环遍历这些帧,在当前帧中显示它们,使用cv2.imshow()并使用waitKey()注册操作,无论是保留该帧(将其附加到另一个列表中)还是取消。我需要将图像显示在与其他图像相同的窗口中。

代码如下:

"""
    frames is a list of 3-d numpy array representing an RGB image.
"""
keeped_frames = []
frame_index = 0
frames_upper_bound = len(frames)
for frame in frames:
    print('Showing frame {} / {}'.format(frame_index + 1,frames_upper_bound))
    cv2.imshow('frame', frame)
    key = cv2.waitKey(0) & 0xFF
    if key == ord('0'):
        print('Not appending frame {} / {} to list'.format(frame_index + 1, frames_upper_bound))
    elif key == ord('1'):
        print('Appending frame {} / {} to list'.format(frame_index + 1, frames_upper_bound))
        keeped_frames.append(frame)
    elif key == ord('q'):
        cv2.destroyAllWindows()
        break
    frame_index += 1

我尝试用plt.imshow()在循环中展示图像,但它每次都会创建新的窗口。即使这个问题得到解决,我也怎么能轻松地注册键盘动作并快速切换到下一帧呢? 使用cv2就可以很好地解决这个问题,我可以按住键盘上的键来快速播放帧;因为需要以这种方式注释成千上万个帧,所以我想要类似的功能。 我能用matplotlib或任何其他在Ubuntu上运行的库复制这种行为吗?
1个回答

10

你可以使用matplotlib.pyplotimshow方法和matplotlib的事件处理功能。你可以尝试以下代码,看看它是否适合你:

import matplotlib as mpl 
mpl.use('wxAgg')

import numpy as np 
import matplotlib.pyplot as plt

# just some random data 
frames = [np.random.random((10, 10)) for _ in range(100)]
keeped_frames = [] 
i = 0

# event listener 
def press(event):
    global i
    if event.key == '1':
        print('Appending frame')
        keeped_frames.append(frames[i % 100])
    i += 1
    imgplot.set_data(frames[i % 100])
    fig.canvas.draw()

fig, ax = plt.subplots() 
fig.canvas.mpl_connect('key_press_event', press)
imgplot = ax.imshow(frames[i % 100]) 
plt.show()

需要注意的一点是,监听器的行为取决于你正在使用的后端。在Qt5Agg中,每次按键都会触发一个key_press事件,无论你是否按住该键;而在wxAgg中,按住键会连续触发按下和释放事件(我猜这就是你想要的行为)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接