26

Using cvShowImage, one can easily show an image in OpenCV. However, how do you tell OpenCV to show the window on top of every other window?

I run a full screen OpenGL application while showing images. The first time the OpenCV window pops up on top of my application window, but if I click on the window of my application (i.e. give focus back to it), then I can't manage to have the OpenCV come back on top of the OpenGL window, even when destroying and recreating the window.

I thought of renaming the window each time, but is there another way to do it?

karlphillip
  • 92,053
  • 36
  • 243
  • 426
seb
  • 2,136
  • 3
  • 20
  • 27
  • This openGL application runs in full screen or in a window? I'm torn apart between "full screen openGL app" and "clicked on application window" – Marcin Deptuła Dec 07 '11 at 15:17
  • you're right, this wasn't clear: the OpenGL application takes the entire screen but is not launched in full screen mode; does this change something though? – seb Dec 07 '11 at 16:49
  • 1
    It does. Added to karl's answer. When you get handle with cvGetHandle you can windows as on-top, or set opengl window as a parent of cv image with SetParent() function, this way, when your parent window (openGL) will be active, child window will still be visible but not active, which is what you want. – Marcin Deptuła Dec 07 '11 at 17:14
  • You would be better off feeding the OpenCV Mat object into a Qt GUI (using `QImage` or `QPixmap` static methods), then the Qt GUI will give you total control. – msmith81886 Mar 21 '18 at 19:19

8 Answers8

32

Beginning with OpenCV releases 3.4.8 and 4.1.2, setWindowProperty has a WND_PROP_TOPMOST property that you can set. Example Python code:

import cv2
import numpy as np

window_name = "image"
img = np.zeros([480, 640, 1])
cv2.imshow(window_name, img)
cv2.setWindowProperty(window_name, cv2.WND_PROP_TOPMOST, 1)
cv2.waitKey(0)
Dan Mašek
  • 17,852
  • 6
  • 57
  • 85
Bruce Christensen
  • 1,564
  • 1
  • 11
  • 12
13

OK, I figured it out which works for both OSX and Windows. You just need to create a full-screen window and show it for a very short time, then your next window from OpenCV will be in front. So, first to open a full-screen window:

cv::namedWindow("GetFocus", CV_WINDOW_NORMAL);
cv::Mat img = cv::Mat::zeros(100, 100, CV_8UC3);
cv::imshow("GetFocus", img);
cv::setWindowProperty("GetFocus", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
waitKey(1);
cv::setWindowProperty("GetFocus", CV_WND_PROP_FULLSCREEN, CV_WINDOW_NORMAL);
destroyWindow("GetFocus");

And then you can open up anther window that actually show the image:

Mat your_image = ...;
cv::namedWindow("ShowImg");
cv::imshow("ShowImg", your_image);

It works for me.

xczhang
  • 166
  • 1
  • 3
  • works for me too, on OSX El Capitan 10.11.6 with OpenCV 3.3.0_3 – VisorZ Oct 02 '17 at 12:44
  • This worked OSX High Sierra. Using Python 2 though you have to convert 'cv::' and 'CV_'* above to 'cv2.' and then it will compile. It's not a great hack as the UX is bad, but for hacky code it's adequate. – jeffg Mar 07 '18 at 02:07
6

OpenCV has no native way to do this (that I'm aware of).

The answer is platform dependent. If your target is Windows, check this answer and then this and this will certainly be useful.

If you are on Linux, you need to take a look at how OpenCV was compiled and check what system its built on (probably GTK+ 2.x). Then, do some research of your own.

Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • 1
    Maybe something more than "do some research on your own" would be helpful. – Kalev Maricq Jan 25 '20 at 17:05
  • 1
    @KalevMaricq The question was vague in terms of target platform. I offered external resources that would help him achieve what he wanted to do on Windows, hence the Official Answer check-mark. At the time (8 years ago), if you wanted to do this in other platforms it required additional research to get the answers because Stackoverflow didn't had 20% of the answers it has today. Feel free to down vote this answer, up vote somebody else's or add your own answer which covers how to do this in all platforms that support OpenCV. That would be pretty cool. – karlphillip Jan 25 '20 at 18:26
  • Bruce Christensen answered below, that there is a WND_PROP_TOPMOST property: cv2.setWindowProperty(window_name, cv2.WND_PROP_TOPMOST, 1) Works fine with OpenCV only... – Walchy Mar 15 '21 at 01:08
  • 1
    NB: As of OpenCV releases 3.4.8/4.1.2 this answer is no longer accurate (That's when `WND_PROP_TOPMOST` was added). – Dan Mašek Jun 14 '21 at 08:58
  • @DanMašek Feel free to add your comment as an answer. – karlphillip Jun 14 '21 at 13:41
4

import os os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')

Adding this before any of my code worked for me. Python 3.6.6 & macOS Mojave 10.14.2

Be careful though, the image is gonna pop up on one of your "Desktops" and not in any Maximized Window App screen (when you press the green button in the top left of your app)

Alex
  • 41
  • 2
  • This worked for me in macOS Mojave, but a note that I had to put the `os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')` code after I called `namedWindow` – Will Nathan Aug 29 '19 at 18:33
3

On MAC-OSX (El Capitan) OpenCV 3.1.0, calling moveWindow seems to bring the window just moved to the top.

PolarBear2015
  • 745
  • 6
  • 14
2

I found that all I needed to do was set my main window to fullscreen then back to normal. I did not need to open a separate window. I did not need to display a dummy image. I did not need to call waitKey.

    #!/usr/bin/env python
    import cv2
    import numpy

    WindowName="Main View"
    view_window = cv2.namedWindow(WindowName,cv2.WINDOW_NORMAL)

    # These two lines will force your "Main View" window to be on top with focus.
    cv2.setWindowProperty(WindowName,cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN)
    cv2.setWindowProperty(WindowName,cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_NORMAL)

    # The rest of this does not matter. This would be the rest of your program.
    # This just shows an image so that you can see that this example works.
    img = numpy.zeros((400,400,3), numpy.uint8)
    for x in range(0,401,100):
        for y in range(0,401,100):
            cv2.line(img,(x,0),(0,y),(128,128,254),1)
            cv2.line(img,(x,399),(0,y),(254,128,128),1)
            cv2.line(img,(399,y),(x,399),(128,254,128),1)
            cv2.line(img,(399,y),(x,0),(254,254,254),1)
    cv2.imshow(WindowName, img)
    cv2.waitKey(0)
    cv2.destroyWindow(WindowName)
Noah Spurrier
  • 508
  • 5
  • 8
0

My solution for OSX was to modify my OpenCV code (version 2.4.8), specifically the file windows_cocoa.mm in the highgui/src directory.

If you want to just bring the new window to the front without making it active, add the following line just before the end of the function cvNamedWindow() in windows_cocoa.mm:

[window orderFrontRegardless];

To force the new window to always be made active, add the following line instead:

[application activateIgnoringOtherApps:YES];

It's probably not the best idea for all windows but works in my situation. I got tired of always having to bring them to the front by clicking on them to make them active.

0

I found the best solution posted in comments here: Python OpenCV open window on top of other applications

Simply add the command below after opening a window, e.g.

cv2.namedWindow('img_file_name', cv2.WINDOW_NORMAL) # Creates a window
os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "python" to true' ''') # To make window active

Use "python" in lower case. Using "Python", as I found in some answers, gave me an error:

21:62: execution error: Finder got an error: Can’t set process "Python" to true. (-10006))

At first I tried editing the windows_cocoa.mm file, as suggested above, but it doesn't exist in my computer. I am using a mac osx mojave, OpenCV 3.4.2.