↓もし、良かったらSNSでの紹介よろしくお願いします。

OpenCV(Python)GUI基礎編、画像の拡大表示2

bootstrap

画像の拡大表示

OpenCV(Python)GUI基礎編、画像の拡大表示

前回の記事で画像の拡大表示について解説しました。前回のスクリプトに今回は次の2つの機能を付けてみます。

  • 画面外が選択されたときに表示を調整する。
  • 画面の移動ができるようにする。

こんな感じ

実際に動作させると次のようになります。

zoom2

画像の拡大表示スクリプト

# -*- coding: utf-8 -*-
import cv2
import numpy as np
#画像を読み込む
img = cv2.imread("img.jpg")
img_win = img.copy()
rect = (0, 0, img.shape[1], img.shape[0])
#マウスの操作のコールバック関数
def callback(event, x, y, flags, param):
    global img, img_win, sx, sy, rect, abs_x, abs_y, abs_sx, abs_sy
    abs_x, abs_y = rect[0] + x, rect[1] + y
    #拡大領域の始点
    if event == cv2.EVENT_RBUTTONDOWN:
        sx, sy = x, y
        abs_sx, abs_sy = abs_x, abs_y
    #拡大領域の選択
    if flags == cv2.EVENT_FLAG_RBUTTON:
        img_win = img.copy()[rect[1]:rect[1]+rect[3], rect[0]:rect[0] + rect[2]]
        cv2.rectangle(img_win, (sx, sy), (x, y), (0, 0, 0), 2)
    #拡大結果の出力
    if event == cv2.EVENT_RBUTTONUP:
        rect_x = np.clip(min(abs_sx, abs_x), 0, img.shape[1] - 2)
        rect_y = np.clip(min(abs_sy, abs_y), 0, img.shape[0] - 2)
        rect_w = np.clip(abs(abs_sx - abs_x), 1, img.shape[1] - rect_x)
        rect_h = np.clip(abs(abs_sy - abs_y), 1, img.shape[0] - rect_y)
        rect = (rect_x, rect_y, rect_w, rect_h)
        img_win = img.copy()[rect[1]:rect[1]+rect[3], rect[0]:rect[0] + rect[2]]
    #左クリックしたら移動の始点を決定
    if event == cv2.EVENT_LBUTTONDOWN:
        sx, sy = x, y
        abs_sx, abs_sy = abs_x, abs_y
    #マウスの動きに合わせて画面移動
    if flags == cv2.EVENT_FLAG_LBUTTON:
        rect_x = np.clip(rect[0] + abs_sx - abs_x, 0, img.shape[1] - rect[2])
        rect_y = np.clip(rect[1] + abs_sy - abs_y, 0, img.shape[0] - rect[3])
        rect_w = rect[2]
        rect_h = rect[3]
        rect = (rect_x, rect_y, rect_w, rect_h)
        img_win = img.copy()[rect[1]:rect[1]+rect[3], rect[0]:rect[0] + rect[2]]
cv2.namedWindow("img", cv2.WINDOW_NORMAL)
cv2.setMouseCallback("img", callback)
while(1):
    cv2.imshow("img", img_win)
    k = cv2.waitKey(1)
    #Escキーを押すと終了
    if k == 27:
        break

    #拡大をリセット
    if k == ord("r"):
        rect = (0, 0, img.shape[1], img.shape[0])
        img_win = img.copy()

画面外が選択されたときに表示を調整する。

    #拡大結果の出力
if event == cv2.EVENT_RBUTTONUP:
    rect_x = np.clip(min(abs_sx, abs_x), 0, img.shape[1] - 2)
    rect_y = np.clip(min(abs_sy, abs_y), 0, img.shape[0] - 2)
    rect_w = np.clip(abs(abs_sx - abs_x), 1, img.shape[1] - rect_x)
    rect_h = np.clip(abs(abs_sy - abs_y), 1, img.shape[0] - rect_y)
    rect = (rect_x, rect_y, rect_w, rect_h)
    img_win = img.copy()[rect[1]:rect[1]+rect[3], rect[0]:rect[0] + rect[2]]

np.clip(value, min, max)はvalueがmin以下だったら値がminになります。valueがmax以上だったら値がmaxになります。
この関数を使って、ウィンドに表示する領域が画像から外れないように調整します。

画面の移動ができるようにする。

    #マウスの動きに合わせて画面移動
if flags == cv2.EVENT_FLAG_LBUTTON:
    rect_x = np.clip(rect[0] + abs_sx - abs_x, 0, img.shape[1] - rect[2])
    rect_y = np.clip(rect[1] + abs_sy - abs_y, 0, img.shape[0] - rect[3])
    rect_w = rect[2]
    rect_h = rect[3]
    rect = (rect_x, rect_y, rect_w, rect_h)
    img_win = img.copy()[rect[1]:rect[1]+rect[3], rect[0]:rect[0] + rect[2]]

マウスが左クリックされた状態で動かすとウィンドに表示されている領域が移動します。
画像からはずれないようにnp.clipで調整します。