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に設定してください。 |
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 | 画像の表示倍率 |
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の値が負のとき、マウスホイールを下へ回転 |
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のウィンドウで画像の拡大縮小表示をするのは、出来ないと思っていたので、Tkinterで作ってみたのですが、そもそもTkinterでウィンドウを作るのが大変なので、このCvZoomWindowは、とても簡単に使えるのでおススメです。
ライセンス的にはMITとしましたが、本当に自由に使って頂いて構いません。
現状、既知のバグとして、
●マウス操作で画像の拡大/縮小を繰り返した状態で、ウィンドウの×ボタンでウィンドウを閉じるとエラーになります。
●画像を表示した状態で、ウィンドウをリサイズすると、縦横比の崩れた画像が表示されます。
→マウス操作で、画像の拡大、縮小、移動などを行うと、元に戻ります。