【OpenCV】画像を見ながらトリミング【Python】

##実行の様子

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">pythonで画像を見ながらトリミングするコード書きました！ <a href="https://t.co/NDLoUkls4g">pic.twitter.com/NDLoUkls4g</a></p>&mdash; Natz (@Natz_tec) <a href="https://twitter.com/Natz_tec/status/1367378416429764610?ref_src=twsrc%5Etfw">March 4, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



OpenCVの練習のために作りました。備忘録も兼ねてアップします。





マウスイベントは覚える事が多くて大変です。以下のコードが最低限必要な雛形になるかと思います。

```
def mouseEventName(event,x,y,flags,param):
　　　　if event == cv2.EVENT_MOUSEMOVE:
　　　　　　　　hogehoge

windowName = "test window"
cv2.namedWindow(windowName)
cv2.setMouseCallback(windowName,mouseEventName)
cv2.imshow(windowName,testImage)
cv2.waitKey()
cv2.destroyAllWindows()
```

領域選択を何度でも行えるようにしたり、切り取り領域の外を暗くしたり、と工夫したので個人的には使いやすい仕上がりになりました。

以下全ソース

```
import cv2
import numpy as np

def draw_rectangle(event,x,y,flags,param):
    global cnt,windowName,testIm,beforeX,beforeY,xPos1,xPos2,yPos1,yPos2

    if event == cv2.EVENT_MOUSEMOVE:
        if (cnt >0)&(cnt%2==1):
            img_tmp = testIm.copy()*0.5
            
            cv2.line(img_tmp,(beforeX,beforeY),(x,beforeY),(0,0,255),thickness = 2)
            cv2.line(img_tmp,(beforeX,beforeY),(beforeX,y),(0,0,255),thickness = 2)
            cv2.line(img_tmp,(beforeX,y),(x,y),(0,0,255),thickness = 2)
            cv2.line(img_tmp,(x,beforeY),(x,y),(0,0,255),thickness = 2)
            img_tmp[min(y,beforeY):max(y,beforeY),min(x,beforeX):max(x,beforeX),:] = testIm[min(y,beforeY):max(y,beforeY),min(x,beforeX):max(x,beforeX),:]
            
            cv2.imshow(windowName,img_tmp)

    if event == cv2.EVENT_LBUTTONDOWN:
        cnt += 1
        if (cnt >1) & (cnt%2==0):
            [xPos1,xPos2,yPos1,yPos2] = [min(x,beforeX),max(x,beforeX),min(y,beforeY),max(y,beforeY)]
            #xPosは(x,beforeX)を、yPosは(y,beforeY)を小さい順に並べ替えて保存する
            print("If you select good area, please push [Y] key\n",[xPos1,yPos1],[xPos2,yPos2])
        (beforeX,beforeY) = (x,y) #座標の更新

def image_filter(img):
    kernel = np.array([[0,-1,0],[-1,4,-1],[0,-1,0]])
    img2 = cv2.filter2D(img,-1,kernel)
    return img2

def main():
    global cnt,windowName,testIm,beforeX,beforeY,xPos1,xPos2,yPos1,yPos2
    beforeX = 0                     #保存すべきX座標
    beforeY = 0                     #保存すべきY座標
    cnt = 0                         #画像内でのクリック回数
    testIm = cv2.imread(r'C:\Users\takum\OneDrive\Desktop\img_l.jpg')
    testIm = testIm/255
    windowName = "Select window"
    windowName2 = "Selected image"
    cv2.namedWindow(windowName)
    cv2.setMouseCallback(windowName,draw_rectangle)
    cv2.imshow(windowName,testIm)
    key = cv2.waitKey()
    if key == 27:
        cv2.destroyAllWindows()
    elif key ==121:
        print(key)
        cv2.destroyAllWindows()
        cv2.namedWindow(windowName2)
        cv2.imshow(windowName2,testIm[yPos1:yPos2,xPos1:xPos2,:])
        print("Save -> push [s] key")
        key = cv2.waitKey()
        if key ==115:
            cv2.imwrite(r'C:\Users\takum\OneDrive\Desktop\img_l2.bmp',testIm[yPos1:yPos2,xPos1:xPos2,:]*255)
            print("saved as img_l2.jpg")

if __name__=="__main__":
    main()
```