9

I have a VideoCapture in OpenCV, I can successfully display a given video. What I want to do now is to pause and play by pressing a key (optional which one as long as it works). I have been reading about waitKey but there is something about this whole thing I don't get (ASCII) and how to bind keys. What I understand it is used to let highgui process but can also be used for other purposes?

If it is hard/impossible to pause a video and start it again I would be happy with just a delay when key is pressed.

Help is much appreciated!

J.Smith
  • 335
  • 1
  • 3
  • 8

5 Answers5

20

With reference to OpenCV Documentation for cv::waitKey(delay), when delay <= 0 will cause to the function to wait infinitely for a key event.

Here is a sample Python script to display frames captured from computer's webcam. When q is pressed, the loop is exited. However, if p is pressed, the display pauses until any other key is pressed:

import cv2
cap = cv2.VideoCapture(0) # getting video from webcam
while cap.isOpened():
    ret, img = cap.read()

    cv2.imshow("Frame",img)

    key = cv2.waitKey(1)
    if key == ord('q'):
        break
    if key == ord('p'):
        cv2.waitKey(-1) #wait until any key is pressed
cap.release()
cv2.destroyAllWindows()
elcymon
  • 431
  • 4
  • 5
3

You dont need anything like binding keys. I have written a sample code which will play/pause the video whenever you press "p".

#include <iostream>
#include <fstream>
#include <string>
#include "opencv2/opencv_modules.hpp"
#include "opencv2/highgui/highgui.hpp"

using namespace std;
using namespace cv;

int main(int argc, char **argv)
{
    bool playVideo = true;
    VideoCapture cap(argv[1]);
    if(!cap.isOpened())
    {
        cout<<"Unable to open video "<<argv[1]<<"\n";
        return 0;
    }
    Mat frame;
    while(1)
    {
        if(playVideo)
            cap >> frame;
        if(frame.empty())
        {
            cout<<"Empty Frame\n";
            return 0;
        }
        imshow("Video",frame);
        char key = waitKey(5);
        if(key == 'p')
            playVideo = !playVideo; 
    }
    return 0;
}
Ahmed_Faraz
  • 615
  • 4
  • 25
  • 3
    I believe the flag `playVideo` is not necessary. `waitKey(0)` will pause indefinitely, so it will block your while loop until a key is pressed. Documentation [here](http://docs.opencv.org/2.4/modules/highgui/doc/user_interface.html#waitkey). – Shakkhar Jun 28 '16 at 04:23
  • yes waitKey(0) will pause indefinitely but in this case you will have to press a key for every frame to be displayed – Ahmed_Faraz Jun 29 '16 at 03:14
2

I have same problem as you before. I solved it in Python instead of C++, but I think the logic behind is same.

import cv2
cap = cv2.VideoCapture('my.avi')

while True:

    ret, frame = cap.read()
    key = cv2.waitKey(1) & 0xff

    if not ret:
        break

    if key == ord('p'):

        while True:

            key2 = cv2.waitKey(1) or 0xff
            cv2.imshow('frame', frame)

            if key2 == ord('p'):
                break

    cv2.imshow('frame',frame)

    if key == 27: 
        break

cap.release()
cv2.destroyAllWindows()
kai06046
  • 292
  • 1
  • 3
  • 10
2

If you want to pause and play with p use

if(cv::waitKey(1) == 'p')
    while(cv::waitKey(1) != 'p');
fabiomaia
  • 592
  • 9
  • 19
0

If you want to pause and unpause the video with the same key (e.g. 'Space'), and to exit the video by Esc even if it's paused then you can do the following:

enum Keys {ESC = 27, SPACE = 32};

cv::Mat newFrame;
bool stopVideo = false;

while(video.read(newFrame) && !stopVideo)
{
    cv::imshow("video", newFrame);

    switch(cv::waitKey(25))
    {
        case SPACE:
            while(true)
            {
                int k = cv::waitKey(0);
                if (k == SPACE)
                {
                    break;
                }
                else if (k == ESC)
                {
                    stopVideo = true;
                    break;
                }
            }
            break;

        case ESC:
            stopVideo = true;
            break;
    }
}
Jackdaw
  • 7,626
  • 5
  • 15
  • 33
orbit
  • 133
  • 7