OpenCV

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

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

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

OpenCV CvZoomWindow class

 

インストール方法

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 画像の表示倍率
●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以上の値で設定します。

 

関連ページ

cvzoomwindow
CvNameWindow class that adds zoom and pan functions to OpenCV's namedWindow
【OpenCV-Python】Tkinter GUI Sample
OpenCVのPython版でもC#のようなウィンドウのGUIプログラムを作りたい! ということで、GUIにTkinterを使って、簡単なサンプルプログラムを作成しました。 ここで公開しているコードは自由に変更して使って頂いてもらって構いま...

 

まとめ

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

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

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

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

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

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

 

 

コメント

タイトルとURLをコピーしました