首页 > 解决方案 > 应用过滤器后在 PyQt5 GUI 中裁剪图像

问题描述

我正在构建一个图像编辑器应用程序。我使用 Qt Creator 的 GUI 和 OpenCV 来操作图像。我正在寻找裁剪图像并将其显示在新窗口中。下面是代码的截图和代码。我想合并以下代码:

from PyQt5 import QtCore, QtGui, QtWidgets # GUI REQUIREMENTS
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys # RUNNING THE APP REQUIREMENTS
import cv2 as cv # FILTER REQUIREMENTS
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import (QApplication, QDialog, QFileDialog, QGridLayout,
                         QLabel, QPushButton, QGraphicsView)
from PyQt5.QtWidgets import QGraphicsView                  
fname=''

class Ui_Form(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
    super().__init__(QtWidgets.QGraphicsScene(), parent)

    self.setupUi(self)

    #QGraphicsScene class provides a surface for managing a large number of 2D graphical items
    self.pixmap_item = self.scene().addPixmap(QtGui.QPixmap())
    # alignment of the widgets
    self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag) 
    # user clicks on the scene background and drags the mouse
    self.rubberBandChanged.connect(self.onRubberBandChanged) 
    # onRubberBandChanged = selects the area
    self.last_rect = QtCore.QPointF() 
    #defines a point in the plane using floating point precision.

def setupUi(self, Form):
    Form.setObjectName("Form")
    Form.resize(800, 600)
    self.setWindowTitle("#1 Task Sagar")
    # Dimensions of the 2 wraps, 2 buttons (open n apply), 2 labels for displaying image
    self.groupBox = QtWidgets.QGroupBox(Form)
    self.groupBox.setGeometry(QtCore.QRect(40, 20, 331, 500))
    self.groupBox.setObjectName("groupBox")
    self.btn1 = QtWidgets.QPushButton(self.groupBox)
    self.btn1.setGeometry(QtCore.QRect(130, 40, 156, 23))
    self.btn1.setObjectName("btn1")
    self.btn1.clicked.connect(self.open)
    self.label = QtWidgets.QLabel(self.groupBox)
    self.label.setGeometry(QtCore.QRect(45, 90, 271, 450))
    self.label.setText("")
    self.label.setObjectName("label")

    self.groupBox_2 = QtWidgets.QGroupBox(Form)
    self.groupBox_2.setGeometry(QtCore.QRect(440, 20, 331, 500))
    self.groupBox_2.setObjectName("groupBox_2")
    self.btn2 = QtWidgets.QPushButton(self.groupBox_2)
    self.btn2.setGeometry(QtCore.QRect(110, 40, 156, 23))
    self.btn2.setObjectName("btn2")
    self.btn2.clicked.connect(self.gray_scale)
    self.label_2 = QtWidgets.QLabel(self.groupBox_2)
    self.label_2.setGeometry(QtCore.QRect(45, 90, 271, 450))
    self.label_2.setText("")
    self.label_2.setObjectName("label_2")
    self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag) 
    # user clicks on the scene background and drags the mouse
    self.rubberBandChanged.connect(self.onRubberBandChanged) 
    # onRubberBandChanged = selects the area
    self.last_rect = QtCore.QPointF() 
    #defines a point in the plane using floating point precision.


    self.retranslateUi(Form)
    QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
    _translate = QtCore.QCoreApplication.translate
    Form.setWindowTitle(_translate("Form", "#1 Task Sagar"))
    self.groupBox.setTitle(_translate("Form", "Original image"))
    self.btn1.setText(_translate("Form", "Select"))
    self.groupBox_2.setTitle(_translate("Form", "Gray"))
    self.btn2.setText(_translate("Form", "Apply"))


def setPixmap(self, pixmap):
    self.pixmap_item.setPixmap(pixmap)

def open(self):
    global fname
    imgName, imgType = QFileDialog.getOpenFileName(self, "Open picture", "", "*;;*.png;;All Files(*)")
    image = cv.imread(imgName)
    if image is None:
        print("No picture selected")
    else:
        size = (int(self.label.width()), int(self.label.height())) # width n height of label
        shrink = cv.resize(image, size, interpolation=cv.INTER_AREA) # Resize image to label size using Interpolation
        shrink = cv.cvtColor(shrink, cv.COLOR_BGR2RGB) # convert Color space
        self.QtImg = QtGui.QImage(shrink.data, #resize image in QT without distortion
                                  shrink.shape[1], # get rows, columns data and store in tuple
                                  shrink.shape[0],
                                  shrink.shape[1]*3,
                                  QtGui.QImage.Format_RGB888) # Qt color spaces rgb convert
        self.label.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))
        fname = imgName
        print(imgName)
        one = 50
        two = 50


def gray_scale(self):
    global fname
    image = cv.imread(fname)
    if image is None:
        print("No picture selected")
    else:
        image = cv.cvtColor(image, cv.COLOR_BGR2GRAY) #calling gray filter from CV
        size = (int(self.label_2.width()), int(self.label_2.height())) # width n height of label
        shrink = cv.resize(image, size, interpolation=cv.INTER_AREA) # Resize image to label size using Interpolation 
        shrink = cv.cvtColor(shrink, cv.COLOR_BGR2RGB) ## convert Color space
        self.QtImg = QtGui.QImage(shrink.data, #resize image in QT without distortion
                                  shrink.shape[1], # get rows, columns data and store in tuple
                                  shrink.shape[0], 
                                  shrink.shape[1]*3, 
                                  QtGui.QImage.Format_RGB888) # Qt color spaces rgb convert
        self.label_2.setPixmap(QtGui.QPixmap.fromImage(self.QtImg))

@QtCore.pyqtSlot(QtCore.QRect, QtCore.QPointF, QtCore.QPointF) 
def onRubberBandChanged(self, rubberBandRect, fromScenePoint, toScenePoint): #This signal is emitted when the rubber band rect is changed. The viewport Rect is specified by rubberBandRect. 
    if rubberBandRect.isNull(): 
        #The drag start position and drag end position are provided in scene points with fromScenePoint and toScenePoint.
        pixmap = self.pixmap_item.pixmap() 
        # Fit to window
        rect = self.pixmap_item.mapFromScene(self.last_rect).boundingRect().toRect() 
        # the outer bounds of the item as a rectangle; all painting must be restricted to inside an item's bounding rect.
        #Maps the rectangle rect, which is in this item's scene's coordinate system, to this item's coordinate system, and returns the mapped rectangle as a polygon.
        if not rect.intersected(pixmap.rect()).isNull(): #Intersection of ROI and viewport, if viewport is null
            crop_pixmap = pixmap.copy(rect) #Returns a deep copy of the subset of the pixmap that is specified by the given rectangle.
            label_3 = QtWidgets.QLabel(pixmap=crop_pixmap) # QLabel widget provides a text or image display. 
            dialog = QtWidgets.QDialog(self) #provide a return value
            lay = QtWidgets.QVBoxLayout(dialog) #vertical alaign of boxes
            lay.addWidget(label) #Adds widget to the end of this box layout, with a stretch factor of stretch and alignment alignment.
            dialog.exec_() # Modal dialog -users cannot interact with any other window in the same application until they close the dialog
        self.last_rect = QtCore.QRectF() #QRectF class defines a rectangle in the plane using floating point precision.
    else:
        self.last_rect = QtCore.QRectF(fromScenePoint, toScenePoint)


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

使用 Qt 的图像处理 GUI

这是裁剪代码,它也使用 Qt 并使用 GraphicScene 类进行裁剪:

from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport


class Viewer(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
    super().__init__(QtWidgets.QGraphicsScene(), parent) 
    #QGraphicsScene class provides a surface for managing a large number of 2D graphical items
    self.pixmap_item = self.scene().addPixmap(QtGui.QPixmap())
    #A pixmap stores and displays a graphical image as a rectangular array of pixel color values.
    self.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) 
    # alignment of the widgets
    self.setDragMode(QtWidgets.QGraphicsView.RubberBandDrag) 
    # user clicks on the scene background and drags the mouse
    self.rubberBandChanged.connect(self.onRubberBandChanged) 
    # onRubberBandChanged = selects the area
    self.last_rect = QtCore.QPointF() 
    #defines a point in the plane using floating point precision.

def setPixmap(self, pixmap):
    self.pixmap_item.setPixmap(pixmap) 
    #Sets the item's pixmap to pixmap.

def resetZoom(self):
    self.resetTransform() 
    #Reset this item’s transform to an identity transformation. identity transform is a data transformation that copies the source data into the destination data without change

def fitToWindow(self):
    self.fitInView(self.pixmap_item) 
    #Scales the view matrix and scrolls the scroll bars to ensure that the scene rectangle rect fits inside the viewport. 

@QtCore.pyqtSlot(QtCore.QRect, QtCore.QPointF, QtCore.QPointF) 
# QRect class defines a rectangle in the plane using integer precision
def onRubberBandChanged(self, rubberBandRect, fromScenePoint, toScenePoint): #This signal is emitted when the rubber band rect is changed. The viewport Rect is specified by rubberBandRect. 
    if rubberBandRect.isNull(): 
        #The drag start position and drag end position are provided in scene points with fromScenePoint and toScenePoint.
        pixmap = self.pixmap_item.pixmap() 
        # Fit to window
        rect = self.pixmap_item.mapFromScene(self.last_rect).boundingRect().toRect() 
        # the outer bounds of the item as a rectangle; all painting must be restricted to inside an item's bounding rect.
        #Maps the rectangle rect, which is in this item's scene's coordinate system, to this item's coordinate system, and returns the mapped rectangle as a polygon.
        if not rect.intersected(pixmap.rect()).isNull(): #Intersection of ROI and viewport, if viewport is null
            crop_pixmap = pixmap.copy(rect) #Returns a deep copy of the subset of the pixmap that is specified by the given rectangle.
            label = QtWidgets.QLabel(pixmap=crop_pixmap) # QLabel widget provides a text or image display. 
            dialog = QtWidgets.QDialog(self) #provide a return value
            lay = QtWidgets.QVBoxLayout(dialog) #vertical alaign of boxes
            lay.addWidget(label) #Adds widget to the end of this box layout, with a stretch factor of stretch and alignment alignment.
            dialog.exec_() # Modal dialog -users cannot interact with any other window in the same application until they close the dialog
        self.last_rect = QtCore.QRectF() #QRectF class defines a rectangle in the plane using floating point precision.
    else:
        self.last_rect = QtCore.QRectF(fromScenePoint, toScenePoint)


class QImageViewer(QtWidgets.QMainWindow):
def __init__(self, parent=None):
    super().__init__()

    self.view = Viewer()
    self.setCentralWidget(self.view)

    self.printer = QtPrintSupport.QPrinter() #The QPrinter class is a paint device that paints on a printer. like PIXMAP and QWidget

    self.createActions()
    self.createMenus()

    self.setWindowTitle("Image Viewer")
    self.resize(800, 600)

def open(self):
    fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
        self,
        "QFileDialog.getOpenFileName()",
        "",
        "Images (*.png *.jpeg *.jpg *.bmp *.gif)",
    )
    if fileName:
        pixmap = QtGui.QPixmap(fileName)
        if pixmap.isNull():
            QtWidgets.QMessageBox.information(
                self, "Image Viewer", "Cannot load %s." % fileName
            )
            return

        self.view.setPixmap(pixmap)

        self.printAct.setEnabled(True)
        self.fitToWindowAct.setEnabled(True)
        self.updateActions()

        if not self.fitToWindowAct.isChecked():
            pass
            # self.imageLabel.adjustSize()

def print_(self): # PRINTING IMAGE  wtf is this, 1999? 
    dialog = QtPrintSupport.QPrintDialog(self.printer, self)
    if dialog.exec_():
        pixmap = self.view.pixmap_item.pixmap()
        painter = QtGui.QPainter(self.printer)
        rect = painter.viewport()
        size = pixmap.size()
        size.scale(rect.size(), QtCore.Qt.KeepAspectRatio)
        painter.setViewport(rect.x(), rect.y(), size.width(), size.height())
        painter.setWindow(pixmap.rect())
        painter.drawPixmap(0, 0, pixmap)

def fitToWindow(self):
    if self.fitToWindowAct.isChecked():
        self.view.fitToWindow()
    else:
        self.view.resetZoom()
    self.updateActions()



def createActions(self):
    self.openAct = QtWidgets.QAction(
        "&Open...", self, shortcut="Ctrl+O", triggered=self.open
    )
    self.printAct = QtWidgets.QAction(
        "&Print...", self, shortcut="Ctrl+P", enabled=False, triggered=self.print_
    )

    self.normalSizeAct = QtWidgets.QAction(
        "&Normal Size",
        self,
        shortcut="Ctrl+S",
        enabled=False,
        triggered=self.view.resetZoom,
    )
    self.fitToWindowAct = QtWidgets.QAction(
        "&Fit to Window",
        self,
        enabled=False,
        checkable=True,
        shortcut="Ctrl+F",
        triggered=self.fitToWindow,
    )

def createMenus(self):
    self.fileMenu = QtWidgets.QMenu("&File", self)
    self.fileMenu.addAction(self.openAct)
    self.fileMenu.addSeparator()

    self.viewMenu = QtWidgets.QMenu("&View", self)

    self.menuBar().addMenu(self.fileMenu)
def updateActions(self):
    self.normalSizeAct.setEnabled(not self.fitToWindowAct.isChecked())


if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication

app = QApplication(sys.argv)
imageViewer = QImageViewer()
imageViewer.show()
sys.exit(app.exec_())

裁剪图形用户界面

标签: pythonuser-interfacepyqt5qt-creatorcrop

解决方案


推荐阅读