I am making perspective transform by Mouse Drag.
I maked almost, but When transform by Qtransform.quadToQuad, Position(Coordinate) is not fit. (See uploaded Image)
Good Example - When Size not Changed

Bad Example - When Size Changed?

How To Fit 4 Point(by Square Point) and Transformed image? Maybe Need to change Postion(size) Image?
import sys
from PySide2.QtCore import QRectF, QPointF
from PySide2.QtGui import *
from PySide2.QtWidgets import *
from mylogger import logger
class Map(QWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# set windowflag
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
# monitor 0 execute
monitor = QDesktopWidget().screenGeometry(0)
self.move(monitor.left(), monitor.top())
self.layout = QVBoxLayout(self)
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.setSpacing(0)
# QGraphicsView
self.view = QGraphicsView()
self.view.setViewportMargins(0, 0, 0, 0)
self.view.setFrameStyle(QFrame.NoFrame)
self.view.setRenderHints(QPainter.Antialiasing)
self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.layout.addWidget(self.view)
# QGraphicsScene
self.scene = QGraphicsScene()
self.view.setScene(self.scene)
# Set Image
self.pixmap = QPixmap("../sample.png")
self.pixmap = self.pixmap.scaled(monitor.width(), monitor.height())
self.image = self.scene.addPixmap(self.pixmap)
self.image.setFlag(QGraphicsItem.ItemIsMovable)
# Set 4 Point (square point)
self.point_size = 8
self.point_left_top = ROIPoint(QRectF(0, 0, self.point_size, self.point_size), "left_top", self)
self.point_left_top.setFlag(QGraphicsItem.ItemIsMovable)
self.scene.addItem(self.point_left_top)
self.point_right_top = ROIPoint(QRectF(monitor.width() - self.point_size, 0, self.point_size, self.point_size),
"right_top", self)
self.point_right_top.setFlag(QGraphicsItem.ItemIsMovable)
self.scene.addItem(self.point_right_top)
self.point_right_bottom = ROIPoint(
QRectF(monitor.width() - self.point_size, monitor.height() - self.point_size, self.point_size,
self.point_size), "right_bottom", self)
self.point_right_bottom.setFlag(QGraphicsItem.ItemIsMovable)
self.scene.addItem(self.point_right_bottom)
self.point_left_bottom = ROIPoint(
QRectF(0, monitor.height() - self.point_size, self.point_size, self.point_size), "left_bottom", self)
self.point_left_bottom.setFlag(QGraphicsItem.ItemIsMovable)
self.scene.addItem(self.point_left_bottom)
self.scene.update()
class ROIPoint(QGraphicsRectItem):
parent = None
position_str = None
def __init__(self, rect, position_str, parent):
super(ROIPoint, self).__init__()
self.parent = parent
self.position_str = position_str
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges, True)
self.setAcceptHoverEvents(True)
self.setCursor(Qt.PointingHandCursor)
self.rectangle = rect
self.setBrush(Qt.red)
self.setRect(rect)
def boundingRect(self):
return QRectF(self.rectangle)
def dragMoveEvent(self, event):
logger.info(f"dragMoveEvent() : {event} ")
def calcurated_position(self):
value = self.pos()
if self.position_str == "left_top":
logger.debug(f" left_top : {self.parent.image.mapFromScene(value)}")
pos = self.parent.image.mapFromScene(value)
if self.position_str == "right_top":
logger.debug(f" right_top : {self.parent.image.mapFromScene(value)}")
pos = QPointF(self.scene().width() + self.parent.image.mapFromScene(value).x(),
self.parent.image.mapFromScene(value).y())
if self.position_str == "right_bottom":
logger.debug(f" right_bottom : {self.parent.image.mapFromScene(value)}")
pos = QPointF(self.scene().width() + self.parent.image.mapFromScene(value).x(),
self.scene().height() + self.parent.image.mapFromScene(value).y())
if self.position_str == "left_bottom":
logger.debug(f" left_bottom : {self.parent.image.mapFromScene(value)}")
pos = QPointF(self.parent.image.mapFromScene(value).x(),
self.scene().height() + self.parent.image.mapFromScene(value).y())
return pos
def itemChange(self, change, value):
if change == QGraphicsItem.ItemPositionChange:
logger.info(f"calcurated_position : {self.calcurated_position()}")
# transform
square = QPolygonF(self.scene().sceneRect())
square.remove(4)
logger.info(f"square:{square}")
cone = QPolygonF([
self.parent.point_left_top.calcurated_position(),
self.parent.point_right_top.calcurated_position(),
self.parent.point_right_bottom.calcurated_position(),
self.parent.point_left_bottom.calcurated_position()
])
transform = QTransform()
if QTransform.quadToQuad(square, cone, transform):
new = self.parent.pixmap.transformed(transform, Qt.SmoothTransformation)
self.parent.image.setPixmap(new)
return super().itemChange(change, value)
if __name__ == "__main__":
app = QApplication(sys.argv)
view = Map()
view.showFullScreen()
sys.exit(app.exec_())