使用matplotlib重现OpenCV imshow()和waitKey()

时间:2017-04-28 07:36:53

标签: python opencv matplotlib

以下代码在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 个答案:

答案 0 :(得分:6)

当然,您可以使用matplotlib的imshowevent handling功能的matplotlib.pyplot方法。您可以尝试以下代码,看看它是否适合您:

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按键持续按下并释放事件(您想要的行为,我猜)。