OpenCV: как заставить окно изображения появляться поверх других окон?

Используя cvShowImage, можно легко показать изображение в OpenCV. Однако как вы говорите OpenCV показывать окно поверх каждого другого окна?

Я запускаю полноэкранное приложение OpenGL при отображении изображений. В первый раз, когда окно OpenCV появляется поверх окна моего приложения, но если я нажму на окно своего приложения (т.е. верну ему фокус), то мне не удастся вернуть OpenCV поверх окна. Окно OpenGL, даже при уничтожении и воссоздании окна.

Я думал о переименовании окна каждый раз, но есть ли другой способ сделать это?


person seb    schedule 07.12.2011    source источник
comment
Это приложение openGL работает в полноэкранном режиме или в окне? Я разрываюсь между полноэкранным приложением openGL и нажимаю на окно приложения   -  person Marcin Deptuła    schedule 07.12.2011
comment
вы правы, это было непонятно: приложение OpenGL занимает весь экран, но не запускается в полноэкранном режиме; хоть это что-то меняет?   -  person seb    schedule 07.12.2011
comment
Оно делает. Добавлено в ответ Карла. Когда вы получаете дескриптор с помощью cvGetHandle, вы можете установить окна как верхние или установить окно opengl в качестве родителя изображения cv с помощью функции SetParent(), таким образом, когда ваше родительское окно (openGL) будет активным, дочернее окно все равно будет видно но не активный, что вы хотите.   -  person Marcin Deptuła    schedule 07.12.2011
comment
Вам лучше передать объект OpenCV Mat в графический интерфейс Qt (используя статические методы QImage или QPixmap), тогда графический интерфейс Qt даст вам полный контроль.   -  person msmith81886    schedule 21.03.2018


Ответы (8)


У OpenCV нет собственного способа сделать это (о котором я знаю).

Ответ зависит от платформы. Если вашей целью является Windows, проверьте этот ответ, а затем это и this, безусловно, будет полезен.

Если вы работаете в Linux, вам нужно посмотреть, как был скомпилирован OpenCV, и проверить, на какой системе он построен (вероятно, GTK+ 2.x). Затем проведите собственное исследование.

person karlphillip    schedule 07.12.2011
comment
Может быть, было бы полезно что-то большее, чем самостоятельное исследование. - person Kalev Maricq; 25.01.2020
comment
@KalevMaricq Вопрос был расплывчатым с точки зрения целевой платформы. Я предложил внешние ресурсы, которые помогли бы ему добиться того, что он хотел сделать в Windows, отсюда и галочка «Официальный ответ». В то время (8 лет назад), если вы хотели сделать это на других платформах, требовалось дополнительное исследование, чтобы получить ответы, потому что у Stackoverflow не было 20% ответов, которые есть сегодня. Не стесняйтесь голосовать против этого ответа, голосовать за кого-то другого или добавлять свой собственный ответ, который описывает, как это сделать на всех платформах, поддерживающих OpenCV. Это было бы круто. - person karlphillip; 25.01.2020
comment
Брюс Кристенсен ответил ниже, что есть свойство WND_PROP_TOPMOST: cv2.setWindowProperty(window_name, cv2.WND_PROP_TOPMOST, 1) Отлично работает только с OpenCV... - person Walchy; 15.03.2021
comment
NB: начиная с выпусков OpenCV 3.4.8/4.1.2 этот ответ больше не является точным (вот когда был добавлен WND_PROP_TOPMOST). - person Dan Mašek; 14.06.2021
comment
@DanMašek Не стесняйтесь добавлять свой комментарий в качестве ответа. - person karlphillip; 14.06.2021

Хорошо, я понял, что работает как для OSX, так и для Windows. Вам просто нужно создать полноэкранное окно и показывать его очень короткое время, тогда ваше следующее окно из OpenCV будет впереди. Итак, сначала, чтобы открыть полноэкранное окно:

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");

И затем вы можете открыть другое окно, которое действительно показывает изображение:

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

Меня устраивает.

person xczhang    schedule 10.08.2017
comment
у меня тоже работает на OSX El Capitan 10.11.6 с OpenCV 3.3.0_3 - person VisorZ; 02.10.2017
comment
Это работало с OSX High Sierra. Используя Python 2, вы должны преобразовать «cv::» и «CV_» * выше в «cv2». и тогда он скомпилируется. Это не лучший хак, так как UX плохой, но для хакерского кода этого вполне достаточно. - person jeffg; 07.03.2018

Начиная с выпусков OpenCV 3.4.8 и 4.1.2, setWindowProperty< /a> имеет свойство WND_PROP_TOPMOST, которое вы можете набор. Пример кода Python:

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)
person Bruce Christensen    schedule 25.02.2021
comment
Работает! Это должен быть лучший ответ - person Walchy; 15.03.2021
comment
Действительно, я не знаю, работает ли это на всех платформах, но я убедился, что это работает на MacOS (Big Sur). - person blackjack75; 30.03.2021
comment
Теперь я могу создать окно на переднем плане. Но как сделать так, чтобы другое окно отображалось поверх него? Установка свойства обратно в 0 не позволяет этого. - person P i; 21.04.2021
comment
Проверено, что он работает с обычным бэкэндом Windows HighGUI. - person Dan Mašek; 14.06.2021

В MAC-OSX (El Capitan) OpenCV 3.1.0 вызов moveWindow, похоже, приводит к перемещению окна наверх.

person PolarBear2015    schedule 31.10.2016
comment
moveWindow не имеет такого эффекта в OpenCV 3.2.0 в Mac OS X Sierra. Окно по-прежнему открывается внизу. - person sh37211; 04.07.2017
comment
Та же проблема с OCV 3.4 на Mac 10.11 - person Mike Mitterer; 19.01.2018

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

Добавление этого до того, как какой-либо мой код сработал для меня. Python 3.6.6 и macOS Мохаве 10.14.2

Однако будьте осторожны, изображение появится на одном из ваших «рабочих столов», а не на любом экране приложения с развернутым окном (когда вы нажимаете зеленую кнопку в левом верхнем углу вашего приложения).

person Alex    schedule 04.02.2019
comment
Это сработало для меня в macOS Mojave, но обратите внимание, что мне пришлось ввести код os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''') после того, как я позвонил namedWindow - person Will Nathan; 29.08.2019

Мое решение для OSX состояло в том, чтобы изменить мой код OpenCV (версия 2.4.8), в частности, файл windows_cocoa.mm в каталоге highgui/src.

Если вы хотите просто вывести новое окно на передний план, не делая его активным, добавьте следующую строку непосредственно перед концом функции cvNamedWindow() в windows_cocoa.mm:

[window orderFrontRegardless];

Чтобы новое окно всегда было активным, добавьте вместо него следующую строку:

[application activateIgnoringOtherApps:YES];

Вероятно, это не лучшая идея для всех окон, но в моей ситуации работает. Мне надоело всегда выводить их на передний план, нажимая на них, чтобы сделать их активными.

person bjeepka    schedule 21.03.2018

Я нашел лучшее решение, опубликованное в комментариях здесь: Python OpenCV открыть окно поверх других приложений

Просто добавьте команду ниже после открытия окна, например.

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

Используйте «python» в нижнем регистре. Использование «Python», как я нашел в некоторых ответах, дало мне ошибку:

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

Сначала я попытался отредактировать файл windows_cocoa.mm, как было предложено выше, но его не существует на моем компьютере. Я использую mac osx mojave, OpenCV 3.4.2.

person Tauana Junqueira Cunha    schedule 04.01.2019
comment
Применимо только для Mac-OSX. Он работает, но всегда с задержкой ~ 30 секунд. - person ishahak; 20.08.2019

Я обнаружил, что все, что мне нужно было сделать, это настроить главное окно на полноэкранный режим, а затем вернуться к обычному режиму. Мне не нужно было открывать отдельное окно. Мне не нужно было отображать фиктивное изображение. Мне не нужно было вызывать 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)
person Noah Spurrier    schedule 27.03.2019