How to check if an opencv window is closed - c++

How do you check if an opencv window has been closed?
I would like to do:
cvNamedWindow("main", 1);
while(!cvWindowIsClosed("main"))
{
cvShowImage("main", myImage);
}
but these is no such cvWindowIsClosed(...) function!

What you are trying to do can be achieved with cvGetWindowHandle():
The function cvGetWindowHandle returns the native window handle (HWND in case of Win32 and GtkWidget in case of GTK+). [Qt Backend Only] qt-specific details: The function cvGetWindowHandle returns the native window handle inheriting from the Qt class QWidget.
The idea is to get the handle of the window and then use specific platform API functions to check if that handle is still valid.
EDIT:
Or you could use the tradicional cvWaitKey() approach:
char exit_key_press = 0;
while (exit_key_press != 'q') // or key != ESC
{
// retrieve frame
// display frame
exit_key_press = cvWaitKey(10);
}

Suppose you have only one image window open, then clicking the 'x' button at its corner causes the waitkey() function to return a -1 value.
Then check if the cvGetWindowHandle("name_of_the_window") function returns 0 or not. If it does return 0, then the window is actually closed.
I have tested it in OpenCV3.
But I am still not very clear on the reason why the waitkey() return -. I will much appreciate if anyone explains why this happens.
[I don't know if my answer to this question will be relevant or not after such a long time. But hopefully if anyone else gets stuck with the same issue (like me), this answer might help them out.]
Thanks.

You can use the cv::getWindowProperty method.
Do like that:
cv::namedWindow("main", WINDOW_AUTOSIZE);
while(1)
{
cv::imshow("main", myImage);
// add this IF.
if (cv::getWindowProperty("main", WND_PROP_AUTOSIZE) == -1)
break;
}
When the windows be closed the getWindowProperty will return -1.

This should do
#include <opencv2/opencv.hpp>
std::string mTitle = "title of my window";
while (cvGetWindowHandle(mTitle.c_str()))
{
// ...
}

In Python OpenCV version 3.4.2, Ubuntu Bionic, cv2.getWindowProperty('Main', cv2.WND_PROP_VISIBLE) returns a floating 0.0 (zero) when the window is closed and 1.0 (one) when it's open, whether see-able or not. Yes, still a 1.0 when it's minimized or behind another window or on a different desktop.

Just before the end of the main(), put the following code:
int main(int, char**){
.
.
.
bool visible = true;
while(visible){
waitKey(1000);
visible = getWindowProperty("Main",WND_PROP_VISIBLE) > 0;
}
return 0;
}

Related

X11 DestroyNotify event returns wrong window parameter

I'm currently working on writing a reparenting window manager using C++ and the XCB library. I unmanage windows when I recieve an UnmapNotify event; in this case the code is very simple:
if (unmap_ignore > 0) {
unmap_ignore--;
return;
}
client *cl = nullptr;
size_t idx = 0;
for (client &c : clients) {
if (c.window == ev->window) {
cl = &c;
break;
}
idx++;
}
if (!cl)
return;
xcb_unmap_window(conn, cl->frame);
clients.erase(clients.begin() + idx);
However, this does not work for some clients that don't bother unmapping the window (usually happens when you force kill the process). Then instead a DestroyNotify is sent. However the ev->window field there (typeof ev = xcb_destroy_notify_event_t) is some value that isn't what I want... here are some example logs (also note each line is a new DestroyNotify event, I get it twice for some reason and each time the #window field is different but not correct):
Found a client window: 4194307 but this was destroyed: 4194305
Found a client window: 4194307 but this was destroyed: 4194313
I remember before I tried to write a window manager in Xlib and had this exact same issue. I must be missing something obvious though, but if I look at the code of other reparenting window managers like Awesome or Herbsluftwm they just use the window field and have no problems. What am I doing wrong?
(my full code is here: http://ix.io/3yDj)
One thing I suspect is that it is just giving me two children windows of the destroyed parent instead of sending the actual parent. no idea why, but it is the most logical thing I can come up with. I just want to be able to handle this so I can unmap the frame for things that don't send UnmapNotify events.
I also first thought that it may report DestroyNotify on the parent window instead of the client reparented one, so I tried checking the frame but to no avail:
Found a client window: 2097152 but this was destroyed: 4194305
Found a client window: 2097152 but this was destroyed: 4194313
I've been truly stumped on this so any help is appreciated, thanks!
Awesome for example does the exact same thing as I tried with ev->window:
static void
event_handle_destroynotify(xcb_destroy_notify_event_t *ev)
{
client_t *c;
if((c = client_getbywin(ev->window)))
client_unmanage(c, CLIENT_UNMANAGE_DESTROYED);
else
for(int i = 0; i < globalconf.embedded.len; i++)
if(globalconf.embedded.tab[i].win == ev->window)
{
xembed_window_array_take(&globalconf.embedded, i);
luaA_systray_invalidate();
}
}

C++ Finding Index for Font temporarily added to System Font Table with AddFontResource() to use in Console

I am trying to temporarily install a font to use in the win32 console with
int AddFontResource(LPCTSTR lpszFilename);
and
BOOL WINAPI SetConsoleFont(HANDLE hOutput, DWORD fontIndex)
I got hold of this function from this site.
Although both functions seem to work fine I have no idea how to find the added font index to use with SetConsoleFont.
AddFontResource returns no index value or key to the temporary font.
Here is my relevant code:
#include "Level.h"
#include "ConsoleFont.h" //acquired from above mentioned site
#include <Windows.h>
//-------------------------------------------------------------------------------
void init();
void cleanup();
int main()
{
FileManager *pFileManager = new FileManager(); //unrelated
Level *lvl1 = new Level("filename",pFileManager); //unrelated
///TEMPORARY PLANNING
// using add font resource. how can i get this fonts index value?
int err = AddFontResource(L"Files/gamefont.fnt");
if (err == 0)
{
MessageBox(NULL,L"loading font failed",L"Error",0);
}
else
{
wchar_t message[100];
swprintf_s(message,100,L"AddFontResource returned: %d",err);
MessageBox(NULL,LPTSTR(message),L"error",0);
}
SendMessage(HWND_BROADCAST, WM_FONTCHANGE,0,0);
//acquiring handle to current active screen buffer
HANDLE tempHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (tempHandle == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,L"Failed to aquire Screen Buffer handle",L"Error",0);
}
//I dont know what to set this to. this is the crux of the problem.
DWORD fontIndex = 1;
if (FALSE == SetConsoleFont(tempHandle,fontIndex))
{
MessageBox(NULL,L"loading console font failed",L"Error",0);
}
//draws a house when in correct font
std::cout<<"!!!!!!!!#\n"
<<"!!!!!!!!!\n"
<<"! !! !! !\n"
<<"!!!!!!!!!\n"
<<"! !! !! !\n"
<<"!!!!!!!!!\n"
<<"! !! !! !\n"
<<"!!!!!!!!!\n"
<<"! !! !! !#\n"
<<"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<std::endl;
///PLANNING OVERS
bool quit = false;
while(!quit)
{
//still to be implemented
}
err = RemoveFontResource(L"Files/gamefont.fnt");
if (err==0)
{
MessageBox(NULL,L"removing font failed",L"Error",0);
}
return 0;
}
I don't know how to go about finding my new font's index value or even if this is possible using my current method.
If someone knows or has a better method please help me out.
any help or hints are appreciated. It must possible to use a custom font in the win32 Console without fiddling with the registry. I'm sure of it :)
Unfortunately you entered the dark world on Win APIs. There is no documentation (or atleast I could never find it) for a console font table lookup. You can try the method "GetNumberOfConsoleFonts()" to see what is returned. I think the font at index 10 is Lucida Console. You'll have to play around a little. Also, this may not work for the OS version you have. Worked for me on XP. Never had to try on anything else. And honestly, never got it fully working on XP too.
For the registry,
Fonts registries are here:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts
Console registries are here:
HKEY_CURRENT_USER\Console
If you end up modifying the registry, the changes may not be reflected immediately. You need to either restart the console or send a special WM_* message (sorry don't remember the name).
Will be great if you can find a solution/workaround :)
int err = AddFontResource(L"Files/gamefont.fnt");
if (err == 0)
{
MessageBox(NULL,L"loading font failed",L"Error",0);
}
else
{
wchar_t message[100];
swprintf_s(message,100,L"AddFontResource returned: %d",err);
MessageBox(NULL,LPTSTR(message),L"error",0);
}
this is wrong AddFontResource returns the number of fonts loaded, so the code in the ELSE doesn't make sense.

OpenCV - closing the image display window

I am doing on a project for searching through an image database, and when I find the results to some query - 5 database images, I would like to display the results visually. I do not keep all the images in memory, so I have do load the image first in order to display it.
I had something simple in mind, in pseudocode:
for image 1..5
load images
display image in a window
wait for any keypress
close the window
Here's a snippet of my code in C++ using OpenCV for this purpose:
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);
}
The images array used here does not as such exist in my code, but for the sake of the question, it contains the File Names of the images relative to the current program running point if its name member. I store the image names a bit differently in my project.
The code above almost works: I can iterate through 4/5 images OK, but when last image is displayed and a key is pressed, the image goes gray and I can not close the image window withouth crashing the rest of my application.
My first idea was that becouse of compile-time optimizations, cvReleaseImage releases the image before cvDestroyWindow is finished, and that somehow makes it freeze. But, I've tried adding some waiting time (hence the commented out sleep(1) line of my code) and it didn't help.
I am calling this display functionality from my console application, and when the image freezes, the control returns back to my application and I can keep using it (but the image window is still frozen in the background).
Can you give me any suggestions on how to fix this?
EDIT
I have talked to some people dealing with computer vision and OpenCV on a regular basis since asking the question, and still no ideas.
I have also found a similar stackoverflow question, but there is still no accepted answer. Googleing just gives similar questions as a result, but no answers.
Any ideas on what to try (even if they are not the complete solution) are very much appreciated.
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;
}
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;
}
There is no need to destroy the window on each frame, you can simply call cvShowImage() with the same window name and it will replace the current image.
You only need to call destroy window at shutdown. You can use cvCreateWindow() to create the window at startup but it will be created automatically on the first showWindow() call.
In your code, I've seen no calls of cvNamedWindow() to create any of the windows you use to show images on (and that you destroy). You should probably put one of those calls into the loop, before you cvShowImage() (as karlphillip has shown in his answer).
If you create the named windows before the loop: Have you made sure that none of the images have duplicate names? To make sure you don't assign an image to a destroyed window, and to make sure you don't destroy a window that has already been destroyed?
Would omitting all calls of cvDestroyWindow() and using a single call of cvDestroyAllWindows() instead help to avoid your problem?
Did you test that your 5th image is correctly loaded? What about this?
for(...)
{
if(!img)
break;
// display it
}
The problem you encounter sounds like a null pointer to cvShowImage();
I love openCV but it is not the only way to display the search result from your test query. You could write a html file from your c++-code in the root of your image folder and open it in a browser.
If you are running a webserver you could write a simple file list and publish it with a simple php-script or similar.
The resulting html-code would be something like:
<!DOCTYPE html>
<html>
<head>
<style>img {display:block}</style>
<meta http-equiv="refresh" content="5">
</head>
<body>
<img src="subfolderA/img1.png" />
<img src="subfolderB/img2.png" />
<img src="subfolderC/img3.png" />
<img src="subfolderD/img4.png" />
<img src="subfolderE/img5.png" />
</body>
</html>
On advantage of this approach is that it can run on a headless server.
For closing the image display window look at the documentation for opencv2.3:
waitKey (especially notes about events), destroyWindow and this code example based on the image.cpp sample in openCV2.3:
#include "cv.h" // include standard OpenCV headers, same as before
#include "highgui.h"
#include <stdio.h>
#include <iostream>
using namespace cv; // all the new API is put into "cv" namespace. Export its content
using namespace std;
void help(){
cout <<
"\nThis program shows how to use cv::Mat and IplImages converting back and forth.\n"
"Call:\n"
"./image img1.png img2.png img3.png img4.png img5.png\n" << endl;
}
int main( int argc, char** argv ){
help();
namedWindow("Peephole", CV_WINDOW_AUTOSIZE);
int i=0;
while ((argc-1) > i){
i++;
const char* imagename = argv[i];
Ptr<IplImage> iplimg = cvLoadImage(imagename); // Ptr<T> is safe ref-conting pointer class
if(iplimg.empty()){
fprintf(stderr, "Can not load image %s\n", imagename);
return -1;
}
Mat img(iplimg); // cv::Mat replaces the CvMat and IplImage, but it's easy to convert
// between the old and the new data structures (by default, only the header
// is converted, while the data is shared)
if( !img.data ) // check if the image has been loaded properly
return -1;
// it's easy to pass the new matrices to the functions that only work with IplImage or CvMat:
// step 1) - convert the headers, data will not be copied
// this is counterpart for cvNamedWindow
imshow("Peephole", img);
waitKey();
}
destroyAllWindows();
while (1) {
waitKey(10);
}
// all the memory will automatically be released by Vector<>, Mat and Ptr<> destructors.
return 0;
}
If you want to close all OpenCV image display windows
use: destroyAllWindows();
What I was looking for is a solution to check wether a key has been pressed or if the window has been closed. That way python doesn't stall:
"""Check if window closed or key pressed"""
import cv2 as cv
img = cv.imread('image.jpg')
cv.imshow("MyWindow", img)
while cv.getWindowProperty("MyWindow", cv.WND_PROP_VISIBLE) > 0:
if cv.waitKey(1000) > 0:
break
Try using
cvDestroyWindow("Match");
// sleep(1);
cvReleaseImage(&img); // outside the for loop

FLTK Closing window

I am using FLTK. I have a window with a variety of buttons the user can click to perform some action. In my int main() i have a switch statement to handle all of these. When the user clicks exit the switch statement is setup like so:
case Exit_program:
cout << "save files and exit\n";
do_save_exit(sw);
This goes to the do_save_exit function that creates a exit confirmation window with two buttons yes (exit) and no (don't exit). I got the yes button to work, exits the program, but the no button mean i should just hide the confirmation window. This is the follow functions:
void yes(Address addr, Address)
{
exit(0);
}
void no(Address addr, Address)
{
}
void do_save_exit(Window& w)
{
Window quit(Point(w.x()+100, w.y()+100), 250, 55, "Exit confirmation");
Text conf(Point(15,15),"Do you really want to save and exit?");
Button yes(Point(60, 20),35,30,"Yes",yes);
Button no(Point(140, 20),35,30,"No",no);
quit.attach(conf);
quit.attach(yes);
quit.attach(no);
wait_for_main_window_click();
}
The problem is, when i click the no button it goes to void no, but I can't go anywhere from there. I just want to do quit.hide() but the no function doesn't have sight of the quit window (out of scope). How should I proceed? Thank you
P.S: I have thought about using a pointer to the quit window and then using the pointer to quit the window in the no function but am not sure how to do that exactly.
The Fl_Window callback is called when an attempt is made to close the window. The default callback hides the window (and if all windows are hidden, your application ends). If you set your own window callback, you can override this behaviour, so as not to hide the window:
// This window callback allows the user to save & exit, don't save, or cancel.
static void window_cb (Fl_Widget *widget, void *)
{
Fl_Window *window = (Fl_Window *)widget;
// fl_choice presents a modal dialog window with up to three choices.
int result = fl_choice("Do you want to save before quitting?",
"Don't Save", // 0
"Save", // 1
"Cancel" // 2
);
if (result == 0) { // Close without saving
window->hide();
} else if (result == 1) { // Save and close
save();
window->hide();
} else if (result == 2) { // Cancel / don't close
// don't do anything
}
}
Set your window's callback wherever you set up your Fl_Window, e.g. in your main function:
window->callback( win_cb );
You probably need to look at using a modal (i.e., dialog) window. Look at <FL/fl_ask.h>
if (fl_ask("Do you really want to save and exit?"))
save_and_exit();
The header also has functions for the popup's font, title, etc.
When you build you don't get an error or warning? The problem is probably that you have both global functions names yes and no and also local variables called just the same. Rename either the functions of the variables.
No need to use hide().
You can simply use exit(0); in a callback.

What is the nicest way to close FreeGLUT?

I'm really having trouble closing my console application with FreeGLUT.
I would like to know what the best way is to take every possible closing, because I don't want any memory leaks (I'm pretty afraid of those).
So I already tried the following, which is giving me an exception like this:
First-chance exception at 0x754e6a6f in myProject.exe: 0x40010005: Control-C.
int main(int argc, char **argv)
{
if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, true) )
{
// more code here as well ....
glutCloseFunc(close); // set the window closing function of opengl
glutMainLoop();
close(); // close function if coming here somehow
}
else
{
return 1;
}
return 0;
}
void close()
{
// keyboardManager is a pointer to a class
// which I want to delete, so no memory will leak.
if(keyboardManager) // do I need this check?
delete keyboardManager;
}
bool CtrlHandler(DWORD fdwCtrlType)
{
switch(fdwCtrlType)
{
// Handle the CTRL-C signal.
case CTRL_C_EVENT:
// and the close button
case CTRL_CLOSE_EVENT:
close();
return true;
// Pass other signals to the next handler.
case CTRL_BREAK_EVENT:
return false;
// delete the pointer anyway
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
default:
close();
return false;
}
}
So what goes right is:
Closing the window of glut
Closing the console application with the x
Closing my window of glut with my keyboardmanager if(keyboardManager->isKeyDown[27]) glutExit();
What goes wrong is:
Closing the console application with CTRL+C, it gives the exception from above.
This is in Visual Studio 2008 C++.
UPDATE
I found that the exception is thrown, because I'm in debug. So that won't be a problem. But the question is still open: What is the most elegant way to actually close glut?
atexit() seems to work as well, so maybe I can use this?
I use this function:
void glutLeaveMainLoop ( void );
There is more information on their sourceforge page but I never used that functionality:
The glutLeaveMainLoop function causes freeglut to stop the event loop. If the GLUT_ACTION_ON_WINDOW_CLOSE option has been set to GLUT_ACTION_CONTINUE_EXECUTION, control will return to the function which called glutMainLoop; otherwise the application will exit.
http://freeglut.sourceforge.net/docs/api.php#EventProcessing
It is safe to use delete on a null pointer, no need to check.
Thanks to Maarten's post, this works to me:
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_CONTINUE_EXECUTION);
whenever you want to leave the mainloop without termiante the application use:
glutLeaveMainLoop();
don't forget to include "freeglut.h"
I use glutDestroyWindow(int handle);
or
According to ID: RigidBody at OpenGL forum
void destroy_window()
{
window_valid = -1;
}
void display_func()
{
if(window_valid == -1)
return;
// draw things
}
Try this method:
glutDestroyWindow(glutGetWindow());