waitkey函数详解

一、waitkey函数是什么

waitkey函数是openCV库中一个非常重要的函数,它的主要作用是等待用户按下某个键,同时它还会返回该按键的ASCII码值。在图像处理的过程中,waitkey函数通常用来实现按键控制,比如实现按Esc键退出程序。

int waitKey(int delay)

二、waitkey函数的调用方法

waitkey函数的调用非常简单,只需要将想要等待的时间以毫秒为单位作为参数传递给该函数即可。如果在等待过程中用户没有按下任何键,waitkey函数会在超时后返回-1。

例如:

char key = 0;
while(key != 27) // 27是ASCII码中的Esc键
{
    Mat frame;
    cap >> frame; // 读取一帧图像
    imshow("video", frame); // 在窗口中显示该帧图像
    key = waitKey(30); // 等待30毫秒,如果用户按下任意键则返回该键的ASCII码值
}

三、waitkey函数的注意事项

1、waitkey函数的参数设置

在使用waitkey函数时,其参数delay需要进行合理设置。如果参数设置的过大,则程序在等待用户按下键盘时会卡死,无法进行下一步操作,而如果参数设置的过小,则程序会非常占用系统资源。一般来说,建议将参数设置在20~50之间。

2、waitkey函数与imshow函数的配合使用

在使用waitkey函数时,通常会与imshow函数一起使用。在imshow函数中,需要为窗口命名,因为waitkey函数会等待用户在该窗口中进行按键操作。同时,需要注意的是,在建立窗口后,必须在waitkey函数之后再使用imshow函数,否则imshow函数无法正常工作。

例如:

namedWindow("video", CV_WINDOW_NORMAL); // 建立一个名为"video"的窗口
while(key != 27) // 27是ASCII码中的Esc键
{
    Mat frame;
    cap >> frame; // 读取一帧图像
    key = waitKey(30); // 等待30毫秒,如果用户按下任意键则返回该键的ASCII码值
    imshow("video", frame); // 在窗口中显示该帧图像
}
destroyWindow("video"); // 销毁窗口

3、waitkey函数与多线程的配合使用

在进行图像处理时,可能需要使用多线程来提高程序的运行效率。如果在多个线程中同时使用waitkey函数,可能会导致程序无法正常运行,因为waitkey函数只能在主线程中使用。

解决办法是将waitkey函数从子线程中移出,改为在主线程中进行调用。在子线程中,如果需要进行按键操作,则通常使用消息循环来实现。具体实现方法可以参考以下代码:

void captureThread()
{
    while (true)
    {
        if (!bStop)
        {
            Mat frame;
            cap >> frame; // 读取一帧图像
            imshow("video", frame); // 在窗口中显示该帧图像
        }
        int c = waitKey(1);
        if ((char)c == 27)
            break;
    }
}

四、waitkey函数的实例

1、实现按Esc键退出程序

int main()
{
    VideoCapture cap(0); // 打开摄像头
    if (!cap.isOpened()) // 如果摄像头未正常打开,则结束程序
        return -1;
    namedWindow("video", CV_WINDOW_NORMAL); // 建立一个名为"video"的窗口
    char key = 0;
    while(key != 27) // 27是ASCII码中的Esc键
    {
        Mat frame;
        cap >> frame; // 读取一帧图像
        imshow("video", frame); // 在窗口中显示该帧图像
        key = waitKey(30); // 等待30毫秒,如果用户按下任意键则返回该键的ASCII码值
    }
    destroyWindow("video"); // 销毁窗口
    return 0;
}

2、实现按下s键保存当前帧图像

int main()
{
    VideoCapture cap(0); // 打开摄像头
    if (!cap.isOpened()) // 如果摄像头未正常打开,则结束程序
        return -1;
    namedWindow("video", CV_WINDOW_NORMAL); // 建立一个名为"video"的窗口
    char key = 0;
    int count = 0; // 用于保存图像的计数器
    while(key != 27) // 27是ASCII码中的Esc键
    {
        Mat frame;
        cap >> frame; // 读取一帧图像
        imshow("video", frame); // 在窗口中显示该帧图像
        key = waitKey(30); // 等待30毫秒,如果用户按下任意键则返回该键的ASCII码值
        if (key == 's') // 如果用户按下s键,则保存当前帧图像
        {
            String savePath = format("./image/frame_%d.jpg", count++);
            imwrite(savePath, frame);
            cout << "Save image " << savePath << " successfully!" << endl;
        }
    }
    destroyWindow("video"); // 销毁窗口
    return 0;
}

3、实现通过按下数字键来切换视频流

int main()
{
    vector files; // 用于存储视频流文件名的向量
    files.push_back("./video/video1.mp4");
    files.push_back("./video/video2.mp4");
    files.push_back("./video/video3.mp4");
    int index = 0; // 当前视频流的索引
    VideoCapture cap(files[index]); // 打开第一个视频流
    if (!cap.isOpened()) // 如果视频流未正常打开,则结束程序
        return -1;
    namedWindow("video", CV_WINDOW_NORMAL); // 建立一个名为"video"的窗口
    char key = 0;
    while(key != 27) // 27是ASCII码中的Esc键
    {
        Mat frame;
        cap >> frame; // 读取一帧图像
        imshow("video", frame); // 在窗口中显示该帧图像
        key = waitKey(30); // 等待30毫秒,如果用户按下任意键则返回该键的ASCII码值
        if (key >= '1' && key <= '3') // 如果用户按下数字键,则切换到对应的视频流
        {
            index = key - '1';
            cap.release(); // 释放当前视频流
            cap.open(files[index]); // 打开新的视频流
        }
    }
    destroyWindow("video"); // 销毁窗口
    return 0;
}

4、实现打开多个摄像头并显示在不同的窗口中

int main()
{
    VideoCapture cap1(0); // 打开第一个摄像头
    if (!cap1.isOpened()) // 如果摄像头未正常打开,则结束程序
        return -1;
    VideoCapture cap2(1); // 打开第二个摄像头
    if (!cap2.isOpened()) // 如果摄像头未正常打开,则结束程序
        return -1;
    namedWindow("video1", CV_WINDOW_NORMAL); // 建立一个名为"video1"的窗口
    namedWindow("video2", CV_WINDOW_NORMAL); // 建立一个名为"video2"的窗口
    char key = 0;
    while(key != 27) // 27是ASCII码中的Esc键
    {
        Mat frame1, frame2;
        cap1 >> frame1; // 读取第一个摄像头的一帧图像
        cap2 >> frame2; // 读取第二个摄像头的一帧图像
        imshow("video1", frame1); // 在"video1"窗口中显示第一个摄像头的帧图像
        imshow("video2", frame2); // 在"video2"窗口中显示第二个摄像头的帧图像
        key = waitKey(30); // 等待30毫秒,如果用户按下任意键则返回该键的ASCII码值
    }
    destroyWindow("video1"); // 销毁"video1"窗口
    destroyWindow("video2"); // 销毁"video2"窗口
    return 0;
}

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/196447.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-03 09:56
下一篇 2024-12-03 09:56

相关推荐

  • Python中引入上一级目录中函数

    Python中经常需要调用其他文件夹中的模块或函数,其中一个常见的操作是引入上一级目录中的函数。在此,我们将从多个角度详细解释如何在Python中引入上一级目录的函数。 一、加入环…

    编程 2025-04-29
  • Python中capitalize函数的使用

    在Python的字符串操作中,capitalize函数常常被用到,这个函数可以使字符串中的第一个单词首字母大写,其余字母小写。在本文中,我们将从以下几个方面对capitalize函…

    编程 2025-04-29
  • Python中set函数的作用

    Python中set函数是一个有用的数据类型,可以被用于许多编程场景中。在这篇文章中,我们将学习Python中set函数的多个方面,从而深入了解这个函数在Python中的用途。 一…

    编程 2025-04-29
  • 单片机打印函数

    单片机打印是指通过串口或并口将一些数据打印到终端设备上。在单片机应用中,打印非常重要。正确的打印数据可以让我们知道单片机运行的状态,方便我们进行调试;错误的打印数据可以帮助我们快速…

    编程 2025-04-29
  • 三角函数用英语怎么说

    三角函数,即三角比函数,是指在一个锐角三角形中某一角的对边、邻边之比。在数学中,三角函数包括正弦、余弦、正切等,它们在数学、物理、工程和计算机等领域都得到了广泛的应用。 一、正弦函…

    编程 2025-04-29
  • Python3定义函数参数类型

    Python是一门动态类型语言,不需要在定义变量时显示的指定变量类型,但是Python3中提供了函数参数类型的声明功能,在函数定义时明确定义参数类型。在函数的形参后面加上冒号(:)…

    编程 2025-04-29
  • Python实现计算阶乘的函数

    本文将介绍如何使用Python定义函数fact(n),计算n的阶乘。 一、什么是阶乘 阶乘指从1乘到指定数之间所有整数的乘积。如:5! = 5 * 4 * 3 * 2 * 1 = …

    编程 2025-04-29
  • Python定义函数判断奇偶数

    本文将从多个方面详细阐述Python定义函数判断奇偶数的方法,并提供完整的代码示例。 一、初步了解Python函数 在介绍Python如何定义函数判断奇偶数之前,我们先来了解一下P…

    编程 2025-04-29
  • Python函数名称相同参数不同:多态

    Python是一门面向对象的编程语言,它强烈支持多态性 一、什么是多态多态是面向对象三大特性中的一种,它指的是:相同的函数名称可以有不同的实现方式。也就是说,不同的对象调用同名方法…

    编程 2025-04-29
  • 分段函数Python

    本文将从以下几个方面详细阐述Python中的分段函数,包括函数基本定义、调用示例、图像绘制、函数优化和应用实例。 一、函数基本定义 分段函数又称为条件函数,指一条直线段或曲线段,由…

    编程 2025-04-29

发表回复

登录后才能评论