【OpenCV】waitKey()函数为什么不工作了?

在通过imshow()显示图像时,要想能够正常的看到所要显示的图像,通常都要waitKey()函数的参与。下面来看看waitKey()函数。

函数原型:

Waits for a pressed key.

int waitKey(int delay = 0);

Parameters

        delay – Delay in milliseconds. 0 is the special value that means “forever”.

The function waitKey waits for a key event infinitely (when delay ≤ 0 )or for delay milliseconds, when it is positive. Since the OS has a minimum time between switching threads, the function will not wait exactly delay ms, itwill wait at least delay ms, depending on what else is running on your computer at that time.It returns the code of the pressed key or -1 if no key was pressed before the specified time had elapsed.

Note1: This function is the only method in HighGUI that can fetch and handle events, so it needs to be called periodically for normal event processing unless HighGUI is used within an environment that takes care of event processing.

Note2: The function only works if there is at least one HighGUI window created and the window is active. If there are several HighGUI windows, any of them can be active.

函数实现:

int waitKey(int delay)
{
    return cvWaitKey(delay);
}
对cvWaitKey()函数做一个简单的说明:

int cvWaitKey( int delay )
{
    int time0 = GetTickCount();

    for(;;)
    {
	// 忽略了窗口和消息处理部分...

        if( (delay > 0 && abs((int)(GetTickCount() - time0)) >= delay) || hg_windows == 0 )
            return -1;

        if( delay <= 0 )
            GetMessage(&message, 0, 0, 0);
        else if( PeekMessage(&message, 0, 0, 0, PM_REMOVE) == FALSE )
        {
            Sleep(1);
            continue;
        }

	// 忽略了窗口和消息处理部分...
    }
}
从上面的代码中即可以看出当delay<=0以及delay>0时,函数cvWaitKey()是怎么分别来处理的。

下面给出一个例子:

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("Lena.jpg");

	// waiKey1...
	int key1 = -2;
	key1 = waitKey(5000);
	cout << "key1: " << key1 << endl;

	// waiKey2...
	imshow("img", img);
	int key2 = -3;
	key2 = waitKey(5000);
	cout << "key2: " << key2 << endl;

	// waiKey3...
	double time = (double)getTickCount();
	waitKey(5000);
	time = (double)getTickCount() - time;
	time = time / getTickFrequency() * 1000;
	cout << "time: " << time << endl;

	return 0;
}

在第二个waitKey中在相应时间内没有按任何键,测试结果为:


在第二个waitKey中在相应时间内按下空格键,测试结果为:


有点迷惑,有时候time会小于5000,为什么?

在cvWaitKey()中的变量hg_windows的定义如下:

static CvWindow* hg_windows = 0;
在cvNamedWindow()函数中hg_windows的值将会被改变而不再为0。

所以在上例中,第一个waitKey()的前面既没有imshow()函数,也没有cvNamedWindow()函数,所以hg_windows保持不变。

因此在第一个waitKey()中,cvWaitKey()函数在执行到

if( (delay > 0 && abs((int)(GetTickCount() - time0)) >= delay) || hg_windows == 0 )
    return -1;
便会直接返回-1;这也验证上面Note2中的 The function only works if there is at least one HighGUI window created and the window is active

在第二个waitKey()中,因为在之前有调用imshow()函数,而imshow()函数会检测窗口名称,如果窗口名称不存在,则会调用cvNamedWindow()函数创建窗口,所以hg_windows将会被赋值,故不会出现上面第一个waitKey()时的情况。在等待的时间内如果不按任何键,同样会进入上面的if语句,从而返回-1,可以通过上面的实验结果来验证。当在等待时间内按下按键的时候,这个就涉及到了Windows的消息传递机制,感兴趣的可以自己查看MSG类及相关的MSDN文档。由于对这个也不是很熟悉,就不陈述啦。。。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值