【OpenCV-Python】CvZoomWindow class(ズーム、パン機能付き画像表示ウィンドウ)

OpenCVで画像を表示するには、namedWindow()でウィンドウを作成して、imshow()で画像を表示しますが、画像は等倍で表示するか、cv2.WINDOW_NORMALを指定して、ウィンドウのサイズに合わせて画像の拡大縮小を行う事はできますが、画像の縦横比が狂ってしまうので、あまり使いやすい物にはなっていません。

そこで、namedWindow()のコールバック関数部分で、画像の拡大縮小や移動の表示処理部分を作成し、クラスにまとめた CvZoomWindowクラスを作成しました。

 

インストール方法

pip install cvzoomwindow

 

サンプルコード

import cv2
import cvzoomwindow

# Image loading
img = cv2.imread("image.bmp")

# Instance of CvZoomWindow class
zw = cvzoomwindow.CvZoomWindow(
    "Zoom Window") # Name of the window 

# Displays an image
zw.imshow(img)

# Waits for a pressed key.
cv2.waitKey()

 

ウィンドウ操作方法

マウス操作 表示
左ボタンのダブルクリック 画像全体表示
右ボタンダブルクリック 等倍(1倍)表示
左ボタンのドラッグ 画像の移動
マウスホイールの上回転 画像の拡大
マウスホイールの下回転 画像の縮小

 

CvZoomWindowクラス

 

コンストラクタ

CvZoomWindowクラスの内部で、OpenCVのnamedWindow()関数により画像表示用ウィンドウを作成し、マウス操作によるコールバック処理を追加しています。

def __init__(self, winname : str, back_color = (128, 128, 0), inter = cv2.INTER_NEAREST):
引数 説明
winname 表示するウィンドウのタイトルを指定します。
日本語を指定すると文字化けします。
back_color ウィンドウの背景色を(B, G, R)の値で指定します。
inter 画像表示の補間モードを指定します。
cv2.INTER_NEAREST
cv2.INTER_LINEAR
cv2.INTER_CUBIC
cv2.INTER_AREA
cv2.INTER_LANCZOS4

 

imshowメソッド

画像をウィンドウに表示します。

OpenCVのcv2.imshow()相当です。
実際に画面に画像が表示されるのは、cv2.waitKey()関数が呼ばれたタイミングで表示されます。

def imshow(self, image, zoom_fit : bool = True):
引数 説明
image 表示するOpenCVの画像データを指定します。
zoom_fit imshowメソッド実行後に画像全体を表示するかどうかの設定
True: 画像全体を表示する(初期値)
Flase:画像全体を表意しないカメラ画像など、連続的に画像を表示する場合はFalseに設定してください。
inter 画像表示の補間モードを指定します。
cv2.INTER_NEAREST
cv2.INTER_LINEAR
cv2.INTER_CUBIC
cv2.INTER_AREA
cv2.INTER_LANCZOS4

 

set_mouse_callbackメソッド

マウス操作によるコールバック関数を登録します。

 

コールバック関数は以下のように登録します。

import cvzoomwindow

# CvZoomWindowクラスのインスタンス
zw = cvzoomwindow.CvZoomWindow("Zoom Window" # Name of the window)

# コールバック関数
def mouse_callback(obj, event, w_x, w_y, flags, params, img_x, img_y, scale):
    print(event, w_x, w_y, flags, params, img_x, img_y, scale)
# コールバック関数の登録
zw.set_mouse_callback(mouse_callback)

コールバック関数は、OpenCVのcv2.setMouseCallback()関数で取得できる値に追加して、画像上の座標と画像の表示倍率を取得できます。

def mouse_callback(obj, event, w_x, w_y, flags, params, img_x, img_y, scale):

引数

obj コールバック元のクラスオブジェクト
event 押されたマウスボタンの種類および状態の値。別途、下記参照
w_x マウスポインタのウィンドウ上のX座標
w_y マウスポインタのウィンドウ上のY座標
flags Shift, Ctrl, Altキーの押された種類。別途、下記参照
params ウィンドウのタイトル
img_x マウスポインタの画像上のX座標
img_y マウスポインタの画像上のY標
scale 画像の表示倍率
●eventの値
cv2.EVENT_MOUSEMOVE マウスが動いたとき(ボタンは押されていない)
cv2.EVENT_LBUTTONDOWN マウスの左ボタンが押されたとき
cv2.EVENT_RBUTTONDOWN マウスの右ボタンが押されたとき
cv2.EVENT_MBUTTONDOWN マウスの中央ボタンが押されたとき
cv2.EVENT_LBUTTONUP マウスの左ボタンが離されたとき
cv2.EVENT_RBUTTONUP マウスの右ボタンが離されたとき
EVENT_MBUTTONUP マウスの中央ボタンが離されたとき
EVENT_LBUTTONDBLCLK マウスの左ボタンがダブルクリックされたとき
EVENT_RBUTTONDBLCLK マウスの右ボタンがダブルクリックされたとき
EVENT_MBUTTONDBLCLK マウスの中央ボタンがダブルクリックされたとき
EVENT_MOUSEWHEEL flagの値が正のとき、マウスホイールを上へ回転
EVENT_MOUSEHWHEEL flagの値が負のとき、マウスホイールを下へ回転
●flagsの値
cv2.EVENT_FLAG_LBUTTON マウスの左ボタン
cv2.EVENT_FLAG_RBUTTON マウスの右ボタン
cv2.EVENT_FLAG_MBUTTON マウスの中央ボタン
cv2.EVENT_FLAG_CTRLKEY Ctrlキー
cv2.EVENT_FLAG_SHIFTKEY Shiftキー
cv2.EVENT_FLAG_ALTKEY Altキー

 

プロパティ

Property name Get Set
affine_matrix 画像表示に用いたアフィン変換行列
bright_disp_enabled 輝度値表示の有効(True)、無効(False)設定
displayed_image 拡大縮小されてウィンドウに表示されている画像データ(np.ndarray)
grid_color グリッド線の色を(B,G,R)で設定
grid_disp_enabled グリッド線表示の有効(True)、無効(False)設定
inter 画像表示の補間方法をOpenCVのcv::InterpolationFlags enumで指定します。
max_scale 最大画像表示倍率
min_bright_disp_scale 輝度値を表示する最小倍率
min_grid_disp_scale グリッド線を表示する最小倍率
min_scale 最小画像表示倍率
mouse_event_enabled マウス操作による画像の拡大縮小、移動の操作の有効(True)、無効(False)設定
scale 現在の画像表示倍率
winname ウィンドウのタイトル名
zoom_delta マウスホイール1ノッチあたりの倍率を1以上の値で設定します。

 

関連ページ

https://pypi.org/project/cvzoomwindow/

【OpenCV-Python】Tkinter GUI Sample

 

まとめ

OpenCVのウィンドウで画像の拡大縮小表示をするのは、出来ないと思っていたので、Tkinterで作ってみたのですが、そもそもTkinterでウィンドウを作るのが大変なので、このCvZoomWindowは、とても簡単に使えるのでおススメです。

ライセンス的にはMITとしましたが、本当に自由に使って頂いて構いません。

現状、既知のバグとして、

●マウス操作で画像の拡大/縮小を繰り返した状態で、ウィンドウの×ボタンでウィンドウを閉じるとエラーになります。

●画像を表示した状態で、ウィンドウをリサイズすると、縦横比の崩れた画像が表示されます。

→マウス操作で、画像の拡大、縮小、移動などを行うと、元に戻ります。

 

 

【OpenCV-Python】getWindowImageRect(画像表示領域の取得)

OpenCVのnameWindow()やimshow()で表示されたウィンドウの画像表示領域の情報(位置、幅、高さ)を取得するには、getWindowImageRect()関数を用います。

 

getWindowImageRect()関数で取得する領域の情報は、画像表示領域の位置は、デスクトップのx, y座標となります。

 

getWindowImageRect()関数の構文

getWindowImageRect( winname ) -> retval

引数

winname 画像表示領域を取得するウィンドウのタイトル名

 

戻り値

retval 画像の表示領域の情報
画像表示領域の左上の座標を(x, y)、画像表示領域のサイズを(width, height)とすると、(x, y, width, height) となるタプルで取得します。

 

サンプルプログラム

ウィンドウの画像部分をマウスの左クリックすると、画像の表示領域の情報をコンソールに表示されます。

import cv2
import numpy as np

WINDOW_TITLE = 'Image Window'

def onMouse(event, x, y, flags, params):
    '''マウスのコールバック関数'''

    if event == cv2.EVENT_LBUTTONDOWN:
        # 左ボタンがクリックされたとき、領域情報の表示
        rect = cv2.getWindowImageRect(WINDOW_TITLE)
        print(f"rect:{rect}")

# テスト画像の生成
image = np.zeros((30, 50, 3), dtype = np.uint8)
cv2.circle(image, (25, 15), 10, (0, 255, 0), -1, cv2.LINE_AA)

cv2.namedWindow(WINDOW_TITLE, cv2.WINDOW_NORMAL)
cv2.imshow(WINDOW_TITLE, image)

# コールバック関数の登録
cv2.setMouseCallback(WINDOW_TITLE, onMouse, "Image")

cv2.waitKey() 

 

参照ページ

https://docs.opencv.org/4.x/d7/dfc/group__highgui.html#ga73b55e9851b5691f6a6a4a4e6c57258e

【OpenCV-Python】rectangle(矩形(長方形)の描画)

OpenCVで矩形(長方形)を描画するにはrectangle()関数を用います。

 

rectangle()関数には、長方形の対角の2点の座標を指定する方法と、Rect(長方形の左上のX座標、Y座標、幅、高さ)を指定する方法があります。

 

長方形の対角の2点を指定する方法

rectangle( img, pt1, pt2, color[, thickness[, lineType[, shift]]] ) -> img

引数

img 線の描画先の画像データ
pt1 矩形を構成する座標 (X座標, Y座標)をタプルで指定します。
ただし、座標の値は整数です。(小数は非対応)
pt2 pt1の対角の座標 (X座標, Y座標)をタプルで指定します。
ただし、座標の値は整数です。(小数は非対応)
color 線色
カラーの場合は、(B, G, R)の順のタプルで指定します。
thickness 線幅を整数で指定します。
マイナスの値を指定すると、矩形の内側が塗りつぶされます。
lineType cv2.LINE_4     4連結
cv2.LINE_8     8連結(デフォルト)
cv2.LINE_AA   アンチエイリアス
のいずれかを指定します。
shift 点座標の小数ビット数、デフォルトで0
x, y座標が以下の式に基づいて変換されます。
(x, y) -> (x * 2^(-shift),  y * 2^(-shift))

pt1, pt2の座標は、長方形の対角の座標であれば、組み合わせ、順番は任意に指定できます。

 

戻り値

img 画像データに追加で線が描画された画像データ(引数で渡した画像と同じデータ)

 

サンプルプログラム

import cv2
import numpy as np

img = np.zeros((10, 15, 3), dtype = np.uint8) # 幅15画素、高さ10画素で確保

# Rectで矩形の描画
# Rectは (左上のX座標、Y座標、矩形の幅、高さを指定)
cv2.rectangle(img, (1, 1), (13, 8), (0, 0, 255), 1)

cv2.namedWindow("Image", cv2.WINDOW_NORMAL)
cv2.imshow("Image", img)
cv2.waitKey()

実行結果

 

Rect(長方形の左上のX座標、Y座標、幅、高さ)を指定する方法

rectangle( img, rec, color[, thickness[, lineType[, shift]]] ) -> img

引数

img 線の描画先の画像データ
rec 矩形の領域を、矩形の(左上のX座標, 左上のY座標, 矩形の幅, 矩形の高さ)の順のタプルで指定します。
ただし、値は整数です。(小数は非対応)
color 線色
カラーの場合は、(B, G, R)の順のタプルで指定します。
thickness 線幅を整数で指定します。
マイナスの値を指定すると、矩形の内側が塗りつぶされます。
lineType cv2.LINE_4     4連結
cv2.LINE_8     8連結(デフォルト)
cv2.LINE_AA   アンチエイリアス
のいずれかを指定します。
shift 点座標の小数ビット数、デフォルトで0
x, y座標が以下の式に基づいて変換されます。
(x, y) -> (x * 2^(-shift),  y * 2^(-shift))

 

戻り値

img 画像データに追加で線が描画された画像データ(引数で渡した画像と同じデータ)

 

サンプルプログラム

import cv2
import numpy as np

img = np.zeros((10, 15, 3), dtype = np.uint8) # 幅15画素、高さ10画素で確保

# Rectで矩形の描画
# Rectは (左上のX座標、Y座標、矩形の幅、高さを指定)
cv2.rectangle(img, (1, 1, 13, 8), (255, 0, 0), 1)

cv2.namedWindow("Image", cv2.WINDOW_NORMAL)
cv2.imshow("Image", img)
cv2.waitKey()

実行結果

 

注意点

矩形の左上のX座標、Y座標、幅、高さで指定したとき、幅方向、高さ方法の座標間の距離は、

 矩形の幅 – 1矩形の高さ – 1

になる事に注意してください。

rec = (1, 1, 13, 8) として、指定した場合の座標は、以下のようになります。

 

関連リンク

https://imagingsolution.net/program/python/opencv-python/opencv-reference/opencv-python-line/

 

参照ページ

https://docs.opencv.org/4.8.0/d6/d6e/group__imgproc__draw.html#ga07d2f74cadcf8e305e810ce8eed13bc9

【OpenCV-Python】circle(円の描画)

OpenCVで画像に円を描画するには、circle()関数を用います。

circle()関数の構文

circle( img, center, radius, color[, thickness[, lineType[, shift]]] ) -> img

引数

img 円の描画先の画像データ
center 中心の座標 (X座標, Y座標)のタプルで指定します。
ただし、座標の値は整数です。(小数は非対応)
radius 円の半径を整数で指定します。
color 線色
カラーの場合は、(B, G, R)の順のタプルで指定します。
thickness 線幅を整数で指定します。
負の値を指定すると、大きさに関係なく、円の内側が塗りつぶされます。
lineType cv2.LINE_4     4連結
cv2.LINE_8     8連結(デフォルト)
cv2.LINE_AA   アンチエイリアス
のいずれかを指定します。
shift 点座標の小数ビット数、デフォルトで0
x, y座標が以下の式に基づいて変換されます。
(x, y) -> (x * 2^(-shift),  y * 2^(-shift))

戻り値

img 画像データに追加で円が描画された画像データ(引数で渡した画像と同じデータ)

 

lineType(アンチエイリアス)を変えながら描画したサンプル

import cv2
import numpy as np

img = np.zeros((50, 50, 3), dtype = np.uint8)

cv2.circle(img, (25, 25), 20, (255, 0, 0),  1, cv2.LINE_4)
cv2.circle(img, (25, 25), 15, (0, 255, 0),  1, cv2.LINE_8)
cv2.circle(img, (25, 25), 10, (0, 0, 255),  1, cv2.LINE_AA)

cv2.namedWindow("Image", cv2.WINDOW_NORMAL)
cv2.imshow("Image", img)
cv2.waitKey()

実行結果

 

線幅を変えながら描画したサンプル

import cv2
import numpy as np

img = np.zeros((50, 50, 3), dtype = np.uint8)

cv2.circle(img, (25, 25), 22, (255, 0, 0),  3)
cv2.circle(img, (25, 25), 15, (0, 255, 0),  2)
cv2.circle(img, (25, 25), 10, (0, 0, 255),  1)

cv2.namedWindow("Image", cv2.WINDOW_NORMAL)
cv2.imshow("Image", img)
cv2.waitKey()

実行結果

 

円の内側を塗りつぶして描画したサンプル

import cv2
import numpy as np

img = np.zeros((50, 50, 3), dtype = np.uint8)

cv2.circle(img, (25, 25), 20, (255, 0, 0),  -3)
cv2.circle(img, (25, 25), 15, (0, 255, 0),  -2)
cv2.circle(img, (25, 25), 10, (0, 0, 255),  -1)

cv2.namedWindow("Image", cv2.WINDOW_NORMAL)
cv2.imshow("Image", img)
cv2.waitKey()

実行結果

半径(radius)が負の場合、値の大きさに関係なく、円の内側が塗りつぶされます。

 

参考リンク

https://docs.opencv.org/4.8.0/d6/d6e/group__imgproc__draw.html#gaf10604b069374903dbd0f0488cb43670

https://imagingsolution.net/program/python/opencv-python/opencv-reference/opencv-python-linetypes/

 

【OpenCV-Python】setMouseCallback(マウスのコールバック関数登録)

OpenCVのnamedWindow()で作られたウィンドウやimshow()で自動で表示されたウィンドウのマウスイベントのコールバック関数を登録するにはsetMouseCallback()関数を用います。

 

setMouseCallback()関数の構文

cv2.setMouseCallback(winname, onMouse[, userdata])
引数
winname コールバック関数に関連付けるウィンドウのタイトル
onMouse 登録するコールバック関数名
userdata コールバック関数へ渡す値(オプション)
(ウィンドウタイトルを渡すと便利)

登録するコールバック関数の構文

コールバック関数の関数名は何でも構いませんが、引数は以下のようにする必要があります。
def onMouse(event, x, y, flags, params):
引数
event 押されたマウスボタンの種類および状態の値。別途、下記参照
x マウスポインタのX座標(ウィンドウの座標ではなく画像上のX座標)
y マウスポインタのX座標(ウィンドウの座標ではなく画像上のY座標)
flags Shift, Ctrl, Altキーの押された種類。別途、下記参照
params コールバック関数登録時に渡された値
●eventの値
cv2.EVENT_MOUSEMOVE マウスが動いたとき(ボタンは押されていない)
cv2.EVENT_LBUTTONDOWN マウスの左ボタンが押されたとき
cv2.EVENT_RBUTTONDOWN マウスの右ボタンが押されたとき
cv2.EVENT_MBUTTONDOWN マウスの中央ボタンが押されたとき
cv2.EVENT_LBUTTONUP マウスの左ボタンが離されたとき
cv2.EVENT_RBUTTONUP マウスの右ボタンが離されたとき
EVENT_MBUTTONUP マウスの中央ボタンが離されたとき
EVENT_LBUTTONDBLCLK マウスの左ボタンがダブルクリックされたとき
EVENT_RBUTTONDBLCLK マウスの右ボタンがダブルクリックされたとき
EVENT_MBUTTONDBLCLK マウスの中央ボタンがダブルクリックされたとき
EVENT_MOUSEWHEEL flagの値が正のとき、マウスホイールを上へ回転
flagの値が負のとき、マウスホイールを下へ回転
EVENT_MOUSEHWHEEL
●flagsの値
cv2.EVENT_FLAG_LBUTTON マウスの左ボタン
cv2.EVENT_FLAG_RBUTTON マウスの右ボタン
cv2.EVENT_FLAG_MBUTTON マウスの中央ボタン
cv2.EVENT_FLAG_CTRLKEY Ctrlキー
cv2.EVENT_FLAG_SHIFTKEY Shiftキー
cv2.EVENT_FLAG_ALTKEY Altキー

サンプルプログラム

import cv2
import numpy as np

def create_test_image():
    '''テスト画像の作成'''
    img = np.zeros((30, 50, 3), dtype = np.uint8)
    cv2.circle(img, (10, 15), 10, (255, 0, 0), -1, cv2.LINE_AA)
    cv2.circle(img, (25, 15), 10, (0, 255, 0), -1, cv2.LINE_AA)
    cv2.circle(img, (40, 15), 10, (0, 0, 255), -1, cv2.LINE_AA)
    return img

def onMouse(event, x, y, flags, params):
    '''マウスのコールバック関数

    Parameters
    ----------
    event : int
        押されたマウスボタンの種類
    x : int
        マウスポインタの画像上のX座標
    y : int
        マウスポインタの画像上のY座標
    flags : int
        Shift, Ctrl, Altキーの押された種類
    params : 
        コールバック関数登録時に渡された値
    '''
    if disp_image is not None:
        print(f"[{x}, {y}] (R, G, B) = ({disp_image[y, x, 2]}, {disp_image[y, x, 1]}, {disp_image[y, x, 0]}) event = {event} flags = {flags} params = {params}")

# テスト画像の生成
disp_image = create_test_image()

cv2.namedWindow('Image', cv2.WINDOW_NORMAL)
cv2.imshow('Image', disp_image)

# コールバック関数の登録
cv2.setMouseCallback('Image', onMouse, "Image")

cv2.waitKey() 
実行結果

参照ページ

https://docs.opencv.org/4.8.0/d7/dfc/group__highgui.html#ga89e7806b0a616f6f1d502bd8c183ad3e
https://docs.opencv.org/4.8.0/d0/d90/group__highgui__window__flags.html#gaab4dc057947f70058c80626c9f1c25ce
https://docs.opencv.org/4.8.0/d0/d90/group__highgui__window__flags.html#ga927593befdddc7e7013602bca9b079b0

【OpenCV-Python】line(線の描画)

OpenCVで画像に線を描画するには、line()関数を用います。

line()関数の構文

line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) ->img

引数

img 線の描画先の画像データ
pt1 線の始点の座標 (X座標, Y座標)のタプルで指定します。
ただし、座標の値は整数です。(小数は非対応)
pt2 線の終点の座標 (X座標, Y座標)のタプルで指定します。
ただし、座標の値は整数です。(小数は非対応)
color 線色
カラーの場合は、(B, G, R)の順のタプルで指定します。
thickness 線幅を整数で指定します。
lineType cv2.LINE_4     4連結
cv2.LINE_8     8連結(デフォルト)
cv2.LINE_AA   アンチエイリアス
のいずれかを指定します。
shift 点座標の小数ビット数、デフォルトで0
x, y座標が以下の式に基づいて変換されます。
(x, y) -> (x * 2^(-shift),  y * 2^(-shift))

 

戻り値

img 画像データに追加で線が描画された画像データ(引数で渡した画像と同じデータ)

 

サンプルプログラム

import cv2
import numpy as np

img = np.zeros((10, 10, 3), dtype = np.uint8)

cv2.line(img, (1, 0), (8, 3), (10, 20, 128), 1)
cv2.line(img, (8, 5), (1, 8), (255, 128, 10), 1)

cv2.namedWindow("Image", cv2.WINDOW_NORMAL)
cv2.imshow("Image", img)
cv2.waitKey()

実行結果

 

まとめ

線の始点、終点の座標は整数となります。

特に、座標を計算で求めた時に、小数座標を渡してエラーにはまりやすいので、注意してください。

 

参考リンク

https://docs.opencv.org/4.8.0/d6/d6e/group__imgproc__draw.html#ga7078a9fae8c7e7d13d24dac2520ae4a2

https://imagingsolution.net/program/python/opencv-python/opencv-reference/opencv-python-linetypes/

https://imagingsolution.net/program/python/opencv-python/create_new_opencv_image_data/

https://docs.opencv.org/3.4/d6/d6e/group__imgproc__draw.html

【OpenCV-Python】カメラからの画像取込を別スレッドにする

カメラからの画像取込を、なぜ、わざわざ別スレッドにしたいか?というと、よくある画像取込のプログラム

import cv2

# カメラを開く
cap = cv2.VideoCapture(0)

while True:
    # 画像をキャプチャする
    _, frame = cap.read()

    # 画像を表示する
    cv2.imshow("Image", frame)

    # キーを押すとループを終了する
    if cv2.waitKey(1) > 0:
        break

# カメラを閉じる
cap.release()
# すべてのウィンドウを閉じる
cv2.destroyAllWindows()

を実行し、画像が表示されたウィンドウのタイトルバーの部分をマウスでクリックすると、while文のループ内で、waitKey(1) の部分で処理が停止します。

 

処理が停止するということは、画像の表示(imshow())や画像の取込(read())も、つられて実行されなくなってしまいます。

 

画像の表示は、最悪、停止してもしょうがないとしても、画像の取込が停止するのは、画像の取込ながら画像処理する場合には、不都合です。

 

そこで、画像の取込部分を別スレッドにしたプログラムがこちら↓

import threading
import queue

import cv2

# カメラを開く
cap = cv2.VideoCapture(0)

# フレーム共用のキュー
q_frames = queue.Queue()

def frame_update():
    '''画像取込'''
    while True:
        # カメラ画像の取得
        _, frame = cap.read()
        # 取得した画像をキューに追加
        q_frames.put(frame)
        print(f"qsize:{q_frames.qsize()}")

# 画像取り込みスレッドの作成
thread = threading.Thread(target=frame_update, daemon=True)
# スレッドの開始
thread.start()

# 画像表示用スレッド
while True:
    frame = q_frames.get() # queueが空の場合、キューに何か入るまで、スレッドをブロックする。
    cv2.imshow("Image", frame)

    # キーを押すとループを終了する
    if cv2.waitKey(1) > 0:
        break

# カメラを閉じる
cap.release()
# すべてのウィンドウを閉じる
cv2.destroyAllWindows()

このようにすることで、画像を表示しているウィンドウのタイトルバーの部分をクリックしても、画像の取込(read())が停止する事は無くなります。

 

ただし、少々、厄介なのが、別スレッドからGUIの表示を行う事が出来ないので、queueを介して画像データをメインスレッド側で画像を表示するようにしています。

 

今回は、waitKeyの部分で処理が停止してしまうのを、スレッドで回避していますが、waitKeyの関数に限らず、処理が停止してしまう関数が他にもあるので、注意が必要です。