OpenCV - 关闭图像显示窗口

pen*_*ope 20 c c++ opencv

我正在做一个搜索图像数据库的项目,当我找到一些查询的结果--5个数据库图像时,我想直观地显示结果.我没有将所有图像保存在内存中,所以我先加载图像以显示它.

在伪代码中,我有一些简单的想法:

for image 1..5
    load images
    display image in a window
    wait for any keypress
    close the window
Run Code Online (Sandbox Code Playgroud)

这里是我的代码片段C++使用OpenCV用于此目的:

IplImage *img;

for (int i=0; i < 5; ++i){
    img = cvLoadImage(images[i].name.c_str(),1);
    cvShowImage(("Match" + images[i].name).c_str(), img);
    cvWaitKey(0);
    cvDestroyWindow(("Match" + images[i].name).c_str());
    // sleep(1);
    cvReleaseImage(&img);
}
Run Code Online (Sandbox Code Playgroud)

images这里使用的数组并不存在于我的代码中,但是为了问题,它包含相对于当前程序运行点(如果是其name成员)的图像的文件名.我在项目中存储的图像名称略有不同.

上面的代码几乎可以工作:我可以迭代4/5图像OK,但是当显示最后一个图像并按下一个键时,图像变为灰色,我无法关闭图像窗口而不会崩溃我的应用程序的其余部分.

我的第一个想法是因为编译时优化,cvReleaseImagecvDestroyWindow完成之前释放图像,并以某种方式使其冻结.但是,我已经尝试添加一些等待时间(因此sleep(1)我的代码注释掉了)并没有帮助.

我从我的控制台应用程序调用此显示功能,当图像冻结时,控件返回到我的应用程序,我可以继续使用它(但图像窗口仍然在后台冻结).

你能给我一些关于如何解决这个问题的建议吗?

编辑

自从提出问题以来,我已经定期与一些处理计算机视觉和OpenCV的人交谈,但仍然没有想法.

我也发现了类似的stackoverflow问题,但仍然没有接受的答案.谷歌只是提出类似的问题,但没有答案.

任何关于尝试什么的想法(即使它们不是完整的解决方案)都非常感谢.

kar*_*lip 22

出于测试目的,下面应用程序完全按照您在问题中所述的内容执行:它通过命令行逐个加载7个图像,并为每个要显示的图像创建一个新窗口.

它与Linux上的OpenCV 2.3.1完美配合.

#include <cv.h>
#include <highgui.h>

#define NUM_IMGS 7

int main(int argc, char* argv[])
{
    if (argc < 8)
    {
        printf("Usage: %s <img1> <img2> <img3> <img4> <img5> <img6> <img7>\n", argv[0]);
        return -1;
    }

    // Array to store pointers for the images
    IplImage* images[NUM_IMGS] = { 0 };

    for (int i = 0; i < NUM_IMGS; i++)
    {
        // load image
        images[i] = cvLoadImage(argv[i+1], CV_LOAD_IMAGE_UNCHANGED);
        if (!images[i])
        {
            printf("!!! failed to load: %s\n", argv[i+1]);
            continue;
        }

        // display image in a window
        cvNamedWindow(argv[i+1], CV_WINDOW_AUTOSIZE); // creating a new window each time
        cvShowImage(argv[i+1], images[i]);

        // wait for keypress
        cvWaitKey(0);

        // close the window
        cvDestroyWindow(argv[i+1]);
        cvReleaseImage(&images[i]);
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Evg*_*uev 5

cvDestroyWindow()通常只会启动非常复杂的窗口破坏程序.此过程需要在窗口系统和应用程序之间进行一些交互(事件交换).在此过程完成之前,窗口无法完全销毁.这就是为什么当应用程序执行与GUI无关的操作时,您会看到部分销毁窗口的原因.

可以以系统相关的方式执行事件交换.在Windows中,这意味着(直接或间接)调用GetMessageMsgWaitFor*运行和处理结果.对于Unix,这意味着(直接或间接)调用XNextEvent和处理结果.

OpenCV允许以独立于系统的方式进行此事件交换.有两种记录方法可以做到这一点.第一个是cvWaitKey()(cvWaitKey(1)在关闭最后一个图像后调用).第二个是cvStartWindowThread()在程序开始时调用,以允许OpenCV自动更新其窗口.

这些方法中只有一种在我的Linux机器上使用libcv2.1正常工作:cvStartWindowThread().


更新(使用cvStartWindowThread()的代码片段)

//gcc -std=c99 main.c -lcv -lcxcore -lhighgui
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <stdio.h>
#include <unistd.h>

#define NUM_IMGS 2

int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        printf("Usage: %s <img1>\n", argv[0]);
        return -1;
    }

    cvStartWindowThread();

    // Array to store pointers for the images
    IplImage* images[NUM_IMGS] = { 0 };

    for (int i = 0; i < NUM_IMGS; i++)
    {
        // load image
        images[i] = cvLoadImage(argv[i+1], CV_LOAD_IMAGE_UNCHANGED);
        if (!images[i])
        {
            printf("!!! failed to load: %s\n", argv[i+1]);
            continue;
        }

        // display image in a window
        cvNamedWindow(argv[i+1], CV_WINDOW_AUTOSIZE); // creating a new window each time
        cvShowImage(argv[i+1], images[i]);

        // wait for keypress
        cvWaitKey(0);

        // close the window
        cvDestroyWindow(argv[i+1]);
        cvReleaseImage(&images[i]);
    }

    //    cvWaitKey(1);
    sleep(10);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)