我想制作一个python脚本,其中程序显示包含矩形或正方形的图像,然后最终用户应通过在其角度上拖动一些指针来指定该形状的四个角度。这些指针将由程序呈现。
基于这些角度,程序应从其余图像中裁剪形状。
我该怎么做? 我正在使用 Python3 , PyQt5 。
这是我到目前为止所做的,是允许用户浏览以从他的计算机中选择图像并将其上传到程序的过程
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QCursor
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.setEnabled(True)
Dialog.resize(1050, 800)
Dialog.setMinimumSize(QtCore.QSize(1050, 800))
Dialog.setMaximumSize(QtCore.QSize(1050, 800))
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("project pic/images LPR icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
Dialog.setWindowIcon(icon)
Dialog.setStyleSheet("background-color: rgb(217, 217, 217);\n"
"background-color: rgb(243, 243, 243);")
self.UserImageLbl = QtWidgets.QLabel(Dialog)
self.UserImageLbl.setGeometry(QtCore.QRect(130, 60, 800, 600))
self.UserImageLbl.setMinimumSize(QtCore.QSize(800, 600))
self.UserImageLbl.setMaximumSize(QtCore.QSize(800, 600))
self.UserImageLbl.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.UserImageLbl.setFrameShadow(QtWidgets.QFrame.Plain)
self.UserImageLbl.setLineWidth(1)
self.UserImageLbl.setMidLineWidth(0)
self.UserImageLbl.setText("")
self.UserImageLbl.setPixmap(QtGui.QPixmap("project pic/upn.png"))
self.UserImageLbl.setScaledContents(False)
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter)
self.UserImageLbl.setObjectName("UserImageLbl")
self.BrowesImageButton = QtWidgets.QPushButton(Dialog)
self.BrowesImageButton.setGeometry(QtCore.QRect(430, 690, 230, 60))
self.BrowesImageButton.setMinimumSize(QtCore.QSize(230, 60))
self.BrowesImageButton.setMaximumSize(QtCore.QSize(230, 60))
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
self.BrowesImageButton.setFont(font)
self.BrowesImageButton.setStyleSheet("background-color: rgb(0, 214, 157);\n"
"background-color: rgb(0, 170, 127);")
self.BrowesImageButton.setCursor(QCursor(QtCore.Qt.PointingHandCursor))
# self.BrowesImageButton.setStyleSheet("BrowesImageButton:hover { background-color: rgb(0, 214, 157) }" )
self.BrowesImageButton.setCheckable(True)
self.BrowesImageButton.setObjectName("BrowesImageButton")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.BrowesImageButton.clicked.connect(self.setImage)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", " Cropping Shapes"))
self.BrowesImageButton.setText(_translate("Dialog", "Browse Image"))
def setImage(self):
#fileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select Image", "", "Image Files (*.png *.jpg *jpeg *.bmp);;All Files (*)") # Ask for file
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(None, "Select Image", "", "Image Files (*.png)") # Ask for file
if fileName: # If the user gives a file
pixmap = QtGui.QPixmap(fileName) # Setup pixmap with the provided image
pixmap = pixmap.scaled(self.UserImageLbl.width(), self.UserImageLbl.height(), QtCore.Qt.KeepAspectRatio) # Scale pixmap
self.UserImageLbl.setPixmap(pixmap) # Set the pixmap onto the label
self.UserImageLbl.setAlignment(QtCore.Qt.AlignCenter) # Align the label to center
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
谢谢。
答案 0 :(得分:2)
在这种情况下,最好使用QGraphicsView,因为它允许我们添加其他图像而无需缩放图像。在QGraphicsView中,您可以单击包含图像的项目,然后使用my previous answer使用该信息,获得以下内容:
import os
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
current_dir = os.path.dirname(os.path.realpath(__file__))
point_filename = os.path.join(current_dir, "41uu2.png")
class GraphicsView(QtWidgets.QGraphicsView):
def __init__(self, parent=None):
super().__init__(QtWidgets.QGraphicsScene(), parent)
self.pixmap_item = self.scene().addPixmap(QtGui.QPixmap())
self.pixmap_item.setShapeMode(QtWidgets.QGraphicsPixmapItem.BoundingRectShape)
self.setAlignment(QtCore.Qt.AlignCenter)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
def set_image(self, pixmap):
self.pixmap_item.setPixmap(pixmap)
self.fitInView(self.pixmap_item, QtCore.Qt.KeepAspectRatio)
class CropView(GraphicsView):
resultChanged = QtCore.pyqtSignal(QtGui.QPixmap)
def __init__(self, parent=None):
super().__init__(parent)
self.point_items = []
def mousePressEvent(self, event):
if not self.pixmap_item.pixmap().isNull():
sp = self.mapToScene(event.pos())
lp = self.pixmap_item.mapFromScene(sp)
if self.pixmap_item.contains(lp):
size = QtCore.QSize(30, 30)
height = (
self.mapToScene(QtCore.QRect(QtCore.QPoint(), size))
.boundingRect()
.size()
.height()
)
pixmap = QtGui.QPixmap(point_filename)
point_item = QtWidgets.QGraphicsPixmapItem(pixmap, self.pixmap_item)
point_item.setOffset(
-QtCore.QRect(QtCore.QPoint(), pixmap.size()).center()
)
point_item.setPos(lp)
scale = height / point_item.boundingRect().size().height()
point_item.setScale(scale)
self.point_items.append(point_item)
if len(self.point_items) == 4:
points = []
for it in self.point_items:
points.append(it.pos().toPoint())
self.crop(points)
elif len(self.point_items) == 5:
for it in self.point_items[:-1]:
self.scene().removeItem(it)
self.point_items = [self.point_items[-1]]
else:
print("outside")
super().mousePressEvent(event)
def crop(self, points):
# https://stackoverflow.com/a/55714969/6622587
polygon = QtGui.QPolygonF(points)
path = QtGui.QPainterPath()
path.addPolygon(polygon)
source = self.pixmap_item.pixmap()
r = path.boundingRect().toRect().intersected(source.rect())
pixmap = QtGui.QPixmap(source.size())
pixmap.fill(QtCore.Qt.transparent)
painter = QtGui.QPainter(pixmap)
painter.setClipPath(path)
painter.drawPixmap(QtCore.QPoint(), source, source.rect())
painter.end()
result = pixmap.copy(r)
self.resultChanged.emit(result)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setFixedSize(1050, 600)
self.left_view = CropView()
self.rigth_view = GraphicsView()
self.left_view.resultChanged.connect(self.rigth_view.set_image)
button = QtWidgets.QPushButton(self.tr("Browse Image"))
button.setStyleSheet("background-color: rgb(0, 214, 157);")
button.setFixedSize(230, 60)
font = QtGui.QFont()
font.setFamily("Microsoft YaHei UI")
font.setPointSize(11)
font.setBold(True)
font.setWeight(75)
button.setFont(font)
button.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
button.clicked.connect(self.load_image)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
lay = QtWidgets.QGridLayout(central_widget)
lay.addWidget(self.left_view, 0, 0)
lay.addWidget(self.rigth_view, 0, 1)
lay.addWidget(button, 1, 0, 1, 2, alignment=QtCore.Qt.AlignHCenter)
@QtCore.pyqtSlot()
def load_image(self):
fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
None, "Select Image", "", "Image Files (*.png)"
)
if fileName:
pixmap = QtGui.QPixmap(fileName)
self.left_view.set_image(pixmap)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())