LoginSignup
33
25

More than 5 years have passed since last update.

matplotlibだけで画像からマウスで指定した領域を抜き出す

Last updated at Posted at 2017-12-21

目的

matplotlibだけで画像からマウスで指定した領域を抜き出したい

結果

Dec-21-2017 18-04-35.gif

ソースコード

import numpy as np 
import matplotlib.pyplot as plt 

# 押した時
def Press(event):
    global x1,y1,DragFlag
    # 値がNoneなら終了
    if (event.xdata is None) or (event.ydata is None):
        return 

    # 丸める
    cx = int(round(event.xdata))
    cy = int(round(event.ydata))

    x1 = cx
    y1 = cy

    # フラグをたてる
    DragFlag = True

# ドラッグした時
def Drag(event):
    global x1,y1,x2,y2,DragFlag

    # ドラッグしていなければ終了
    if DragFlag == False:
        return

    # 値がNoneなら終了
    if (event.xdata is None) or (event.ydata is None):
        return 

    # 丸める
    cx = int(round(event.xdata))
    cy = int(round(event.ydata))

    x2 = cx
    y2 = cy

    # ソート
    ix1, ix2 = sorted([x1,x2])
    iy1, iy2 = sorted([y1,y2])

    # 画像の一部を抜き出す
    cimg = img[iy1:iy2,ix1:ix2,:]

    # 画像を更新
    im2.set_data(cimg)

    # 四角形を更新
    DrawRect(x1,x2,y1,y2)

    # 描画
    plt.draw()

# 離した時
def Release(event):
    global DragFlag
    # フラグをたおす
    DragFlag = False

# 四角形を描く関数
def DrawRect(x1,x2,y1,y2):
    Rect = [ [ [x1,x2], [y1,y1] ],
             [ [x2,x2], [y1,y2] ],
             [ [x1,x2], [y2,y2] ],
             [ [x1,x1], [y1,y2] ] ]
    for i, rect in enumerate(Rect):
        lns[i].set_data(rect[0],rect[1])

# 画像を開く    
from PIL import Image
fnm = 'lena.tif'
img = Image.open(fnm)

# numpy.ndarrayに
img = np.asarray(img)

# 初期値
x1  = 0 
y1  = 0
x2  = 50
y2  = 50

# ドラッグしているかのフラグ
DragFlag = False

# ソート
ix1, ix2 = sorted([x1,x2])
iy1, iy2 = sorted([y1,y2])

# 画像の一部を抜き出す
cimg = img[iy1:iy2,ix1:ix2,:]

# plot
plt.close('all')
plt.figure(figsize=(8,4))

# subplot 1
plt.subplot(1,2,1)

# 画像を描画
im1 = plt.imshow(img, cmap='gray')

# 四角形を描画
Rect = [ [ [x1,x2], [y1,y1] ],
         [ [x2,x2], [y1,y2] ],
         [ [x1,x2], [y2,y2] ],
         [ [x1,x1], [y1,y2] ] ]

lns = []
for rect in Rect:
    ln, = plt.plot(rect[0],rect[1],color='r',lw=2)
    lns.append(ln)

# 軸を消す
plt.axis('off')

# subplot 2
plt.subplot(1,2,2)
im2 = plt.imshow(cimg, cmap='gray')

# カラーマップの範囲を合わせる 
plt.clim(im1.get_clim())

# 軸を消す
plt.axis('off')

# イベント
plt.connect('button_press_event', Press)
plt.connect('motion_notify_event', Drag)
plt.connect('button_release_event', Release)

plt.show()

動作確認

[mac]
Python 3.6.2
matplotlib 2.0.2
backend : MacOSX and Qt5Agg

[win7]
Python 3.6.3
matplotlib 2.1.0
backend : Qt5Agg

参考文献

Event handling and picking

33
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
25