python - 应用过滤器后在 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_())
裁剪图形用户界面
解决方案
推荐阅读
- c++ - CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, PID) 返回 INVALID_HANDLE_VALUE
- flutter - 如何在颤振中使用下限?
- php - 在 PHP 中设置复选框默认选中
- airflow-scheduler - 如何在 x 次后强制失败?
- flutter - FLutter:将Listtile高度匹配到卡片高度
- javascript - 功能复制项目
- swift - Swift:更改 UIKit ViewController 呈现的 SwiftUI 视图的大小
- sql-server - 是否有选项告诉 SSMS 在生成脚本时不要使用 OPTIMIZE_FOR_SEQUENTIAL_KEY 标志?
- python - While 循环不遵守约束
- python - 如何从具有日期时间索引的数据帧中减去具有月份索引的数据帧