Reputation: 2134
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?
Upvotes: 26
Views: 38516
Reputation: 1590
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)
Upvotes: 33
Reputation: 516
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)
Upvotes: 2
Reputation: 41
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)
Upvotes: 4
Reputation: 39
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.
Upvotes: 0
Reputation: 1
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.
Upvotes: 0
Reputation: 166
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.
Upvotes: 13
Reputation: 844
On MAC-OSX (El Capitan) OpenCV 3.1.0, calling moveWindow seems to bring the window just moved to the top.
Upvotes: 3
Reputation: 93410
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.
Upvotes: 6