PyQt5:QPolygonF 的中心线
PyQt5: Centre line of a QPolygonF
我正在尝试获取 QPolygonF 对象的中心线,这意味着对于从最小到最大的每个 y 坐标,位于最小和最大 X 坐标中间的线。
所需的输出将是一条中心线,但由于某种原因,绘制的对象/中心线有面积。为什么会这样?我应该怎么做才能获得中心线?如下图黑线粗略估计
代码如下:
import PyQt5
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication,QWidget, QMainWindow,QVBoxLayout, QGraphicsScene, QGraphicsPixmapItem,QGraphicsView
from PyQt5.QtGui import QPixmap,QPolygonF
from PyQt5.QtCore import Qt,QPointF
import sys
import time
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setFixedSize(1200, 800)
self.ImageDisplay = QGraphicsView()
self.qwidget = QWidget()
qpixmap = QPixmap()
qpixmap2 = qpixmap.scaledToWidth(self.ImageDisplay.width())
qgraphicsitem = QGraphicsPixmapItem(qpixmap2)
qscene = QGraphicsScene(self.ImageDisplay)
qscene.addItem(qgraphicsitem)
self.ImageDisplay.setScene(qscene)
self.ImageDisplay.setMouseTracking(True)
self.ImageDisplay.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.ImageDisplay.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
self.ImageDisplay.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.ImageDisplay.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
start = time.time()
poly = QPolygonF([QPointF(400, 400), QPointF(100, 10), QPointF(20, 100), QPointF(0, 400)])#, QPointF(105, 5), QPointF(9, 300)])
min_y, max_y = poly.boundingRect().y(), poly.boundingRect().y() + poly.boundingRect().height()
min_x,max_x = poly.boundingRect().x(), poly.boundingRect().x() + poly.boundingRect().width()
print("min_y="+str(min_y)+", max_y="+str(max_y))
print("min_x=" + str(min_x) + ", max_x=" + str(max_x))
end = time.time()
print(f"runtime: {end - start}")
middle_points= []
for y in range(int(min_y),int(max_y)):
# for x in range(int(min_x),int(max_x)):
polyline = QPolygonF([QPointF(min_x,y),QPointF(max_x,y),QPointF(min_x,y+0.1),QPointF(max_x,y+0.1)])
intersection_points = poly.intersected(polyline)
intersection_points = intersection_points.boundingRect()
middle_point = QPointF(intersection_points.x()+intersection_points.width()/2,intersection_points.y()+intersection_points.height()/2)
middle_points.append(middle_point)
middle_poly = QPolygonF(middle_points)
self.ImageDisplay.scene().addPolygon(middle_poly, QtGui.QColor(20, 0, 255, 28),
QtGui.QColor(20, 0, 255, 28))
end = time.time()
print(f"runtime: {end - start}")
self.vlayout = QVBoxLayout()
self.vlayout.addWidget(self.ImageDisplay)
self.qwidget.setLayout(self.vlayout)
self.setCentralWidget(self.qwidget)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
你必须考虑到:
- 当添加 QPolygon 时,将绘制一个闭合图形。
- 不是一条中心线,而是一条由线段组成的中心曲线
- 代码
for y in range(int(min_y),int(max_y)):
适用于 (ymax-ymin) 大于 1 但在其他情况下失败。
要绘制中心曲线,除了使用np.arange()
.
外,还必须使用QPainterPath
import sys
from PyQt5.QtCore import QPointF, QRectF
from PyQt5.QtGui import QPainterPath, QPolygonF
from PyQt5.QtWidgets import QApplication, QGraphicsScene, QGraphicsView
import numpy as np
def build_center_line(polygon):
points = []
minx, miny, maxx, maxy = polygon.boundingRect().getCoords()
dy = (maxy - miny) / 200
for y in np.arange(miny, maxy, dy):
polyline = QPolygonF(
QRectF(QPointF(minx, y - dy / 2), QPointF(maxx, y + dy / 2))
)
p = polygon.intersected(polyline).boundingRect().center()
points.append(p)
return points
def main():
app = QApplication(sys.argv)
polygon = QPolygonF(
[QPointF(400, 400), QPointF(100, 10), QPointF(20, 100), QPointF(0, 400)]
)
points = build_center_line(polygon)
path = QPainterPath()
if points:
path.moveTo(points[0])
for point in points[1:]:
path.lineTo(point)
scene = QGraphicsScene()
view = QGraphicsView(scene)
scene.addPolygon(polygon)
scene.addPath(path)
view.resize(640, 480)
view.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
我正在尝试获取 QPolygonF 对象的中心线,这意味着对于从最小到最大的每个 y 坐标,位于最小和最大 X 坐标中间的线。
所需的输出将是一条中心线,但由于某种原因,绘制的对象/中心线有面积。为什么会这样?我应该怎么做才能获得中心线?如下图黑线粗略估计
代码如下:
import PyQt5
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication,QWidget, QMainWindow,QVBoxLayout, QGraphicsScene, QGraphicsPixmapItem,QGraphicsView
from PyQt5.QtGui import QPixmap,QPolygonF
from PyQt5.QtCore import Qt,QPointF
import sys
import time
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.setFixedSize(1200, 800)
self.ImageDisplay = QGraphicsView()
self.qwidget = QWidget()
qpixmap = QPixmap()
qpixmap2 = qpixmap.scaledToWidth(self.ImageDisplay.width())
qgraphicsitem = QGraphicsPixmapItem(qpixmap2)
qscene = QGraphicsScene(self.ImageDisplay)
qscene.addItem(qgraphicsitem)
self.ImageDisplay.setScene(qscene)
self.ImageDisplay.setMouseTracking(True)
self.ImageDisplay.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
self.ImageDisplay.setResizeAnchor(QGraphicsView.AnchorUnderMouse)
self.ImageDisplay.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.ImageDisplay.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
start = time.time()
poly = QPolygonF([QPointF(400, 400), QPointF(100, 10), QPointF(20, 100), QPointF(0, 400)])#, QPointF(105, 5), QPointF(9, 300)])
min_y, max_y = poly.boundingRect().y(), poly.boundingRect().y() + poly.boundingRect().height()
min_x,max_x = poly.boundingRect().x(), poly.boundingRect().x() + poly.boundingRect().width()
print("min_y="+str(min_y)+", max_y="+str(max_y))
print("min_x=" + str(min_x) + ", max_x=" + str(max_x))
end = time.time()
print(f"runtime: {end - start}")
middle_points= []
for y in range(int(min_y),int(max_y)):
# for x in range(int(min_x),int(max_x)):
polyline = QPolygonF([QPointF(min_x,y),QPointF(max_x,y),QPointF(min_x,y+0.1),QPointF(max_x,y+0.1)])
intersection_points = poly.intersected(polyline)
intersection_points = intersection_points.boundingRect()
middle_point = QPointF(intersection_points.x()+intersection_points.width()/2,intersection_points.y()+intersection_points.height()/2)
middle_points.append(middle_point)
middle_poly = QPolygonF(middle_points)
self.ImageDisplay.scene().addPolygon(middle_poly, QtGui.QColor(20, 0, 255, 28),
QtGui.QColor(20, 0, 255, 28))
end = time.time()
print(f"runtime: {end - start}")
self.vlayout = QVBoxLayout()
self.vlayout.addWidget(self.ImageDisplay)
self.qwidget.setLayout(self.vlayout)
self.setCentralWidget(self.qwidget)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
你必须考虑到:
- 当添加 QPolygon 时,将绘制一个闭合图形。
- 不是一条中心线,而是一条由线段组成的中心曲线
- 代码
for y in range(int(min_y),int(max_y)):
适用于 (ymax-ymin) 大于 1 但在其他情况下失败。
要绘制中心曲线,除了使用np.arange()
.
import sys
from PyQt5.QtCore import QPointF, QRectF
from PyQt5.QtGui import QPainterPath, QPolygonF
from PyQt5.QtWidgets import QApplication, QGraphicsScene, QGraphicsView
import numpy as np
def build_center_line(polygon):
points = []
minx, miny, maxx, maxy = polygon.boundingRect().getCoords()
dy = (maxy - miny) / 200
for y in np.arange(miny, maxy, dy):
polyline = QPolygonF(
QRectF(QPointF(minx, y - dy / 2), QPointF(maxx, y + dy / 2))
)
p = polygon.intersected(polyline).boundingRect().center()
points.append(p)
return points
def main():
app = QApplication(sys.argv)
polygon = QPolygonF(
[QPointF(400, 400), QPointF(100, 10), QPointF(20, 100), QPointF(0, 400)]
)
points = build_center_line(polygon)
path = QPainterPath()
if points:
path.moveTo(points[0])
for point in points[1:]:
path.lineTo(point)
scene = QGraphicsScene()
view = QGraphicsView(scene)
scene.addPolygon(polygon)
scene.addPath(path)
view.resize(640, 480)
view.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()