OpenCV - closing the image display window

cvDestroyWindow() usually only starts pretty complicated procedure of window destruction. This procedure requires some interaction (event exchange) between windowing system and your application. Until this procedure finishes, the window cannot be completely destroyed. That is the reason why you see partially destroyed window while your application performs something not related to GUI.

Event exchange may be performed in system-dependent manner. In Windows this means (directly or indirectly) calling GetMessage or MsgWaitFor* functions and processing the result. For Unixes this means (directly or indirectly) calling XNextEvent and processing the result.

OpenCV allows to do this event exchange in system-independent way. There are two documented methods to do this. First one is cvWaitKey() (just call cvWaitKey(1) after you close the last image). Second one is to call cvStartWindowThread() at the start of your program to allow OpenCV updating its windows automatically.

Only one of these methods worked properly on my Linux box with libcv2.1: cvStartWindowThread().


Update (code snippet with 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;
}

For testing purposes, the application below does exactly what you stated in the question: it loads 7 images through the command line, one by one, and creates a new window for each image to be display.

It works flawlessly with OpenCV 2.3.1 on Linux.

#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;
}

Tags:

C++

C

Opencv