画像の2点をクリックしてcropした画像と座標を手に入れるpython

前書き

画像の切り抜きとそれの座標がほしかった

使い方

クリップボードに画像があればそのまま実行
もしくは画像を実行ファイルにD&D

実際に書いたもの

from PIL import Image, ImageTk, ImageGrab
import numpy as np
import cv2
import os
import sys

class img2crop():
    def __init__(self):
        os.chdir(os.path.dirname(os.path.abspath(__file__)))
        self.x1=self.y1=self.x2=self.y2=self.f=0
        if len(sys.argv) <= 1:
            self.paste_clipboard()
        else:
            self.open_img()

    def pil2cv(self,image):
        ''' PIL型 -> OpenCV型 '''
        new_image = np.array(image, dtype=np.uint8)
        if new_image.ndim == 2:  # モノクロ
            pass
        elif new_image.shape[2] == 3:  # カラー
            new_image = new_image[:, :, ::-1]
        elif new_image.shape[2] == 4:  # 透過
            new_image = new_image[:, :, [2, 1, 0, 3]]
        return new_image

    def onMouse(self,event, x, y, flags, params):
        if event == cv2.EVENT_LBUTTONDOWN:
            if not self.f:
                self.x1=x
                self.y1=y
                self.f=True
            else:
                self.x2=x
                self.y2=y
                if (self.x1 >= self.x2 and self.y1 >= self.y2):
                    t = self.x1
                    self.x1 = self.x2
                    self.x2 = t
                    t = self.y1
                    self.y1 = self.y2
                    self.y2 = t
                
                # 出力文字列
                print(f'{self.x1},{self.y1},{self.x2},{self.y2}')

                self.f=False
                cv2.imshow(f'img2crop - {self.x1},{self.y1},{self.x2},{self.y2}', self.cv_im[self.y1:self.y2,self.x1:self.x2])
                cv2.imwrite(f'{self.x1},{self.y1},{self.x2},{self.y2}.png', self.cv_im[self.y1:self.y2,self.x1:self.x2])

    def paste_clipboard(self):
        self.im = ImageGrab.grabclipboard()
        if isinstance(self.im, Image.Image):
            self.view_im()
        else:
            print(u"クリップボードは画像ではありません")
            input()

    def open_img(self):
        try:
            self.im = Image.open(sys.argv[1])
            self.view_im()
        except:
            print(u"ファイルは画像ではありません")
            input()

    def view_im(self):
        self.cv_im = self.pil2cv(self.im)
        cv2.imshow('img2crop', self.cv_im)
        cv2.setMouseCallback('img2crop', self.onMouse)
        cv2.waitKey(0)

if __name__ == '__main__':
    img2crop()