2021年1月5日火曜日

WindowsでOpenCVウィンドウを常に手前で表示する

OpenCVで表示されたウィンドウを常に手前に表示する方法のメモ. ついでにウィンドウ位置を固定(というより,動かしても元に戻す)機能を加えておく. この方法はWindows限定で今回はPythonでの実装方法.

必要なライブラリはOpenCVとWindowsのAPIに関するもの.

import cv2
import win32gui
import win32con

画像(test.png)を一旦imshowで表示してその画像の解像度とウィンドウハンドル(hwnd)を取得しておく.

window_name = "opencv always on top"
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
frame = cv2.imread("test.png")
cv2.imshow(window_name, frame)
hwnd = win32gui.GetActiveWindow()

この部分は定数値で指定するなら必要ない. マウスでウィンドウサイズを自由に指定できるようにするために,一旦while文を使ってウィンドウサイズを変更できるようにする. 変更してスペースキーを押したら,ウィンドウ位置とサイズを取得する(この位置,サイズに固定する).

while True:
    key = cv2.waitKey(1)
    if key == ord(' '):
        break            
    cv2.imshow(window_name, frame)

(x, y, w, h) = cv2.getWindowImageRect(window_name)

HWND_TOPMOSTを指定することで手前に表示することができます.

while True:
    key = cv2.waitKey(1)
    if key == 27:
        break            
    ret, frame = cap.read()
    cv2.imshow(window_name, frame)
	win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, x, y, w, h, win32con.SWP_NOMOVE | win32con.SWP_NOSIZE)

手前だけじゃなくてサイズも固定したければ最後をこれに変える. ウィンドウ位置やサイズを変えられてしまっても, SetWindowPos関数で毎回表示位置とサイズを元に戻す.

win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, x, y, w, h, win32con.SWP_NOACTIVATE)