2017-03-11 43 views
0

私は画像を持っているところでこのコードを試していましたが、マウスをクリックしてドラッグしたときの矩形を描くことができます。 Mouse Downイベントでは、xとy座標を四角形の最初の角としてマークします。マウス移動では、私が保存した古いx座標とy座標から、マウスがある新しい座標に矩形を描画します。最後に、マウスアップで、私は最終として矩形を描画します。ここで Python OpenCV - 適切なサイズ変更の矩形を描く

は、私が使用しているコードです:

import cv2 
import numpy as np 

drawing = False # True if mouse is pressed 
mode = True # if True, draw rectangle. Press 'm' to toggle to curve 
ix, iy = -1, -1 

# mouse callback function 
def draw_circle(event, x, y, flags, param): 
    global ix, iy, drawing, mode, overlay, output, alpha 
    overlay = img.copy() 
    output = img.copy() 
    alpha = 0.5 

    if event == cv2.EVENT_LBUTTONDOWN: 
     drawing = True 
     ix, iy = x, y 

    elif event == cv2.EVENT_MOUSEMOVE: 
     if drawing == True: 
      if mode == True: 
       cv2.rectangle(overlay, (ix, iy), (x, y), (0, 255, 0), -1) 
       cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0, img) 
       cv2.imshow('image', img) 
      else: 
       cv2.circle(overlay, (x,y),5,(0,0,255),-1) 

    elif event == cv2.EVENT_LBUTTONUP: 
     drawing = False 
     if mode == True: 
      cv2.rectangle(overlay, (ix, iy), (x, y), (0, 255, 0), -1) 
      cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0, img) 

     else: 
      cv2.circle(overlay, (x, y), 5, (0, 0, 255), -1) 


##img = np.zeros((512, 512, 3), np.uint8) 
# Get our image 
img = cv2.imread("bed_cv.jpg", 1) 

#make cv2 windows, set mouse callback 
cv2.namedWindow('image') 
cv2.setMouseCallback('image', draw_circle) 

while(1): 
    cv2.imshow('image', img) 

    # This is where we get the keyboard input 
    # Then check if it's "m" (if so, toggle the drawing mode) 
    k = cv2.waitKey(1) & 0xFF 
    if k == ord('m'): 
     mode = not mode 
    elif k == 27: 
     break 

cv2.destroyAllWindows() 

もちろん、ここでの問題は、私が中心に開始した場合、その後、その後、右下にドラッグ左下に戻るということです、最初の矩形は消去されません。もちろん、これは、実際にはイメージ上に矩形を描いていてクリアしていないため、マウス移動イベントで作成されたすべての矩形が描画されるために発生します。

私が達成したい効果は、あなたがデスクトップ上にボックスを描いているときに似ていて、長方形を作らずに方向を変えることができます。

私の質問は、矩形を視覚的に描くことはできますが、まだイメージに書き込むことはできませんか?

+1

[こちら](http://stackoverflow.com/a/31376558/5008845)を参照してください。私は通常、元のイメージのコピーを保持しています。すべての矩形が既に描画されているイメージ(レイヤーコピー)とレイヤーコピーのコピーを作成します。ここで作成している「部分矩形」をコピーして、ワークコピーのみの長方形。 mouseUpで、作業コピーを新しいレイヤーコピーとして保存します。 – Miki

+0

@Mikiヒントのおかげで!私はそれをすることができた。私はまもなくコードを投稿します。 – Razgriz

+0

代替オプションは、いくつかの可逆操作を使用することです。それがアウトラインの場合は、XOR演算で描くことができます(ただし、OpenCVでは線イテレータを使用する必要があります)。塗りつぶされた長方形の場合、ROIを反転させることができます。もちろん、これは同じには見えませんが、画像のコピーを保持する必要性を避けるアプローチです。 –

答えて

0

アイデアはイメージ(この場合はimg2)のコピーを作成し、それをMouse Moveイベントのオーバーレイの出力として使用することでした。次に、ボタンアップイベントのオリジナルイメージ(この場合はimg)を使用します。

import cv2 
import numpy as np 

drawing = False # True if mouse is pressed 
mode = True # if True, draw rectangle. Press 'm' to toggle to curve 
ix, iy = -1, -1 

# mouse callback function 
def draw_circle(event, x, y, flags, param): 
    global ix, iy, drawing, mode, overlay, output, alpha 
    overlay = img.copy() 
    output = img.copy() 
    alpha = 0.5 

    if event == cv2.EVENT_LBUTTONDOWN: 
     drawing = True 
     ix, iy = x, y 

    elif event == cv2.EVENT_MOUSEMOVE: 
     if drawing == True: 
      if mode == True: 
       cv2.rectangle(overlay, (ix, iy), (x, y), (0, 255, 0), -1) 
       cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0, img2) 
       cv2.imshow('image', img2) 
      else: 
       cv2.circle(overlay, (x,y),5,(0,0,255),-1) 

    elif event == cv2.EVENT_LBUTTONUP: 
     drawing = False 
     if mode == True: 
      cv2.rectangle(overlay, (ix, iy), (x, y), (0, 255, 0), -1) 
      cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0, img) 

     else: 
      cv2.circle(overlay, (x, y), 5, (0, 0, 255), -1) 


##img = np.zeros((512, 512, 3), np.uint8) 
# Get our image 
img = cv2.imread("bed_cv.jpg", 1) 
img2 = img.copy() 

#make cv2 windows, set mouse callback 
cv2.namedWindow('image') 
cv2.setMouseCallback('image', draw_circle) 

while(1): 
    cv2.imshow('image', img2) 

    # This is where we get the keyboard input 
    # Then check if it's "m" (if so, toggle the drawing mode) 
    k = cv2.waitKey(1) & 0xFF 
    if k == ord('m'): 
     mode = not mode 
    elif k == 27: 
     break 

cv2.destroyAllWindows()