Получить координаты выделенной области через Python

У меня есть программа реализованная с помощью Qt Desinger, в ней находится картинка.
Мне нужно чтобы нажимая на кнопку можно было выделить определенную область на этой картинке и сохранить её, скажем так вырезать или скриншот.

Ну или как можно переписать код без использования Tkiner. Код ниже идеально работает, но он вызывает новое окно, а нужно в этом же, или как его впихнуть чтобы он включался по нажатию на кнопку.

import tkinter as tk
from PIL import Image, ImageTk, ImageGrab

WIDTH, HEIGHT = 900, 900
topx, topy, botx, boty = 0, 0, 0, 0
rect_id = None
path = "4.jpg"


def get_mouse_posn(event):
    global topy, topx

    topx, topy = event.x, event.y


def update_sel_rect(event):
    global rect_id
    global topy, topx, botx, boty

    botx, boty = event.x, event.y
    canvas.coords(rect_id, topx, topy, botx, boty)  # Update selection rect.

    image = Image.open('4.jpg')
    cropped = image.crop((topx, topy, botx, boty))
    cropped.save('cropped_jelly.png')


window = tk.Tk()
window.title("Select Area")
window.geometry('%sx%s' % (WIDTH, HEIGHT))
window.configure(background='grey')

img = ImageTk.PhotoImage(Image.open(path))
canvas = tk.Canvas(window, width=img.width(), height=img.height(),
                   borderwidth=0, highlightthickness=0)
canvas.pack(expand=True)
canvas.img = img  # Keep reference in case this code is put into a function.
canvas.create_image(0, 0, image=img, anchor=tk.NW)

# Create selection rectangle (invisible since corner points are equal).
rect_id = canvas.create_rectangle(topx, topy, topx, topy,
                                  dash=(2, 2), fill='', outline='black')

canvas.bind('<Button-1>', get_mouse_posn)
canvas.bind('<B1-Motion>', update_sel_rect)

window.mainloop()

Ответы (1 шт):

Автор решения: S. Nick

Попробуйте так:

import sys
from PyQt5.QtGui import QPainter, QPen, QImage, QPixmap
from PyQt5.QtWidgets import QMainWindow, QApplication, QAction, \
    QFileDialog, QRubberBand, QLabel
from PyQt5.QtCore import Qt, QRectF, QPointF, QRect, QTimer, QSize

from PIL import ImageGrab          
import numpy as np                 
import cv2                         


class Label(QLabel):
    def __init__(self, img, parent=None):
        super(Label, self).__init__(parent)
        self.setCursor(Qt.PointingHandCursor)
        self.pixmapImagen = QPixmap(img) 
        self.setPixmap(self.pixmapImagen)
        self.setAlignment(Qt.AlignCenter)
        
    def mousePressEvent(self, event):
        self.origin = event.pos()
        super().mousePressEvent(event)
        
    def mouseMoveEvent(self, event):
        if event.buttons() & Qt.LeftButton:
            self.move(event.windowPos().toPoint() - self.origin)
        super().mouseMoveEvent(event)


class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        
        mainMenu = self.menuBar()
        instmenu = mainMenu.addMenu("Инстументы")
        file = mainMenu.addMenu("Файл")
        videlenie = QAction("Выделить для копирования", self)
        instmenu.addAction(videlenie)                        
        videlenie.triggered.connect(self.screenshot)         
        photo = QAction("Вставить фото", self)
        file.addAction(photo)
        photo.triggered.connect(self.getImage)

        self.image_foreground = QImage(self.size(), QImage.Format_ARGB32_Premultiplied)
        self.image_foreground.fill(Qt.transparent)
        self.image_background = QImage(self.size(), QImage.Format_ARGB32_Premultiplied)
        self.image_background.fill(Qt.white)

        self.instrument = 'screenshot'

        self.selection = QRubberBand(QRubberBand.Rectangle, self) 
        self.start = QPointF() 
        self.end = QPointF()        

    def getImage(self):
        filename, _ = QFileDialog.getOpenFileName(
            self, 
            "Выберите изображение", 
            "",
            "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*)"
        )
        if not filename:
            return
        self.image_background.load(filename)
        self.selection.hide()                                

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawImage(self.rect(), self.image_background, self.image_background.rect())
        painter.drawImage(self.image_foreground.rect(), self.image_foreground)

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton and self.instrument == 'screenshot': 
            self.start = event.pos() 
            self._start = event.globalPos()

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton and self.instrument == 'screenshot': 
            self.end = event.pos()
            self.selection.setGeometry(QRect(self.start, self.end).normalized())
            self.selection.show()

    def mouseReleaseEvent(self, event):
        if self.instrument == 'screenshot':  
            self._end = event.globalPos()
            self.selection.hide()
            QTimer.singleShot(20, self.newLabel)

    def newLabel(self):
        self.selection.hide()
        self.instrument = 'None'
        img = ImageGrab.grab(bbox=(
            self._start.x(), 
            self._start.y(), 
            self._end.x(), 
            self._end.y()
        ))
        
        pathImage = 'new_image.png'                      # <--- тут будет обрезанное изображение
        img.save(pathImage)
        img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
        cv2.waitKey(0)
        cv2.destroyAllWindows()        

        # vvv это для демонстрации полученного изображения
        self.labelImagen = Label(pathImage, self)
        self.labelImagen.resize(self.selection.size())                          
        self.labelImagen.show()
        # ^^^ 
        
    def screenshot(self):        
        self.instrument = 'screenshot'
        
    def sizeHint(self):     
        return QSize(500, 500)    
        
    def resizeEvent(self, event):   
        self.image_foreground = QImage(self.size(), QImage.Format_ARGB32_Premultiplied)
        self.image_foreground.fill(Qt.transparent)
        self.update()
        super().resizeEvent(event)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    wnd = Window()
    wnd.show()
    sys.exit(app.exec_())

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

→ Ссылка