LoginSignup
2
1

More than 3 years have passed since last update.

【OpenCV】円の描画、マウスイベントで移動と拡大【Python】

Last updated at Posted at 2021-03-21

OpenCVで円を描画、マウスイベントによる移動と拡大を実装しました。

最初に左クリックした位置に円を配置します
円周で左クリックしたままドラッグすると円の位置が移動します。
円周で左クリックしたままドラッグすると円の半径が変化します。

左クリック判定
ON : isGrabbed = True
OFF: isGrabbed = False

ポインタ位置判定
bool.png
isInsideisOntheLineが両方Trueは存在しません)

以下サンプルコード  

testIm = cv2.imread(r'C:\****\sample_pic.jpg')で画像を読み込みます。使用する画像のアドレスに書き換えて使用して下さい。
グローバル変数を削除した改訂版はこちら

import cv2
import numpy as np
import math


def draw_circle(event,x,y,flags,params):
    global cnt,windowName,testIm,centerX,centerY,r,color,distX,distY,isGrabbed,isInside,isOntheLine,posState
    distR = math.ceil(math.sqrt((x-centerX)**2 + (y-centerY)**2))

    if event == cv2.EVENT_LBUTTONDOWN:
        cnt += 1
        isGrabbed = True
        if cnt == 1:
            [centerX,centerY] = [x,y]
            print([centerX,centerY])
        if cnt>1:
            if posState == 0: # inside
                isInside = True
                isOntheLine = False
                distX = centerX - x
                distY = centerY - y

            elif posState == 1: # on the line
                isInside = False
                isOntheLine = True

            elif posState == 2:
                isInside = False
                isOntheLine = False

    if event == cv2.EVENT_LBUTTONUP:
        isGrabbed = False


    if event == cv2.EVENT_MOUSEMOVE:
        if cnt == 0:
            [centerX,centerY] = [x,y]

        if cnt > 0:
            if isGrabbed == False:
                if distR < r-5: # inside
                    posState = 0
                    color = (255,0,0)
                elif (distR <= r+5) & (distR >= r-5): # on the line
                    posState = 1
                    color = (0,255,0)
                elif distR > r+5: # outside
                    posState = 2
                    color = (0,0,255)
            else:

                if isInside == True:
                    centerX = x+distX
                    centerY = y+distY
                elif isOntheLine == True:
                    r = distR
        img_tmp = testIm.copy()
        cv2.circle(img_tmp,(centerX,centerY), r, color, 5)
        cv2.imshow(windowName,img_tmp)

if __name__=="__main__":
    global cnt,windowName,testIm,centerX,centerY,r,color,distX,distY,isGrabbed,isInside,isOntheLine,posState
    centerX = 0                     #保存すべきX座標
    centerY = 0                     #保存すべきY座標
    cnt = 0                         #画像内でのクリック回数
    r = 50
    distX = 0
    distY = 0
    posState = 0 # 0,1,2
    isGrabbed = False
    isInside = False
    isOntheLine = False
    color = (0,0,255)
    testIm = cv2.imread(r'C:\****\sample_pic.jpg')
    testIm = testIm/255
    windowName = "Select window"
    cv2.namedWindow(windowName)
    cv2.setMouseCallback(windowName,draw_circle)
    cv2.imshow(windowName,testIm)
    key = cv2.waitKey()

※マウスイベントの宣言でグローバル変数を使っているので注意してください。

2
1
1

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
2
1