PyQtGraph ROI RemoveHandle 不会删除椭圆 ROI 的圆形句柄

问题描述 投票:0回答:2

我的目标是编写一个无法旋转的椭圆 ROI。考虑以下从 PyQtGraph 示例之一修改而来的代码:


import numpy as np
import cv2
import pyqtgraph as pg
from PyQt5 import QtGui
import numpy.ma as ma
from PyQt5.QtWidgets import QMessageBox

pg.setConfigOptions(imageAxisOrder='row-major')

## Create image to display
image = cv2.imread('panda.jpg')


def picturetranspose(picture):
    shape = picture.shape
    result = np.empty((shape[1],shape[0],shape[2]),dtype= np.uint8)
    for i in range(0,3):
        result[:,:,i] = np.transpose(picture[:,:,i])
    return result
    
arr = np.rot90(picturetranspose(image))
app = pg.mkQApp("ROI Examples")
w = pg.GraphicsLayoutWidget(show=True, size=(1000,800), border=True)
w.setWindowTitle('pyqtgraph example: ROI Examples')
w1 = w.addLayout(row=0, col=0)
v1a = w1.addViewBox(row=1, col=0, lockAspect = True)
v1a.setLimits(minXRange = arr.shape[0]//10, minYRange = arr.shape[1]//10, maxXRange = 5*arr.shape[0], maxYRange = 5*arr.shape[1])
img1a = pg.ImageItem(arr)
v1a.addItem(img1a)

rois = []
x=pg.EllipseROI([60, 10], [30, 20], pen=pg.mkPen('b', width=5),rotatable = False)
x.removeHandle(0)
rois.append(x)

for roi in rois:
    roi.sigRegionChanged.connect(img1a.setImage(arr))
    v1a.addItem(roi)

img1a.setImage(arr)

这里的图像“panda.jpg”由以下方式给出:https://drive.google.com/drive/folders/1ejY0CjfEwS6SGS2qe_uRX2JvlruMKvPX?usp=sharing。运行代码并移动 ROI 将给出:

enter image description here

通过单击浅蓝色方形手柄,可以更改 ROI 的大小。由于我设置了

rotatable = False
,ROI无法旋转,点击圆形手柄也不会旋转ROI。

但是,

x.removeHandle(0)
行应该删除浅蓝色圆形手柄,以便它根本不会显示在屏幕上。这是一个错误吗?我错过了什么?

python python-3.x opencv pyqt5 pyqtgraph
2个回答
3
投票

创建 QGraphicsItem 时,它不会立即添加到场景中,并且在该时间范围内,一些与场景相关的方面会被“存储”,直到该项目实际放入场景中。其中一些属性非常明显(例如项目位置),但其他属性则不然。其中之一是添加 child 项目。当“主要”项目添加到场景中时,它的所有子项(以及孙子项、曾孙项等)都会随之添加。

这就是创建 ROI 时发生的情况:它的句柄是在其

__init__
中创建的(请参阅),但是
removeHandle()
仅当 ROI 实际上具有
scene()
时才会从场景中删除句柄.

请记住,PyQt(和 PySide)是 Qt 的绑定,这意味着我们始终使用围绕 C++ 对象的 Python 包装器。即使删除了对 python 对象的最后一个引用,实际上也只删除了 python 对象,但如果该对象是 C++ 对象的包装器并且该对象有父对象,则 actual 对象毕竟不会被删除。
虽然 pyqtgraph 从其内部列表中删除句柄,但表示句柄的 C++ 对象仍然作为 ROI 的子对象存在,因此,当 ROI 添加到场景时,句柄仍然存在。

一个可能的解决方案是在 ROI 添加到场景后删除手柄:

for roi in rois: roi.sigRegionChanged.connect(img1a.setImage(arr)) v1a.addItem(roi) roi.removeHandle(0)
这是有效的,因为

removeHandle

仅在该项目存在场景时删除句柄,这样子项目就可以从场景中实际删除。

请注意,根据消息来源,

EllipseROI

添加了
两个手柄:旋转缩放。您可能想删除所有这些:

for roi in rois: roi.sigRegionChanged.connect(img1a.setImage(arr)) v1a.addItem(roi) while roi.handles: roi.removeHandle(0)
我建议您在 

pyqtgraph 存储库上提交一份关于此问题的报告,在他们这边解决它应该非常容易。


0
投票
我想到了一个解决这个问题的方法:

pg.ROI( # arguments handlePen='#0000', handleHoverPen='#0000', # arguments )
然后

然后按照您的描述禁用手柄。这使得手柄完全透明(即不可见)

希望对遇到这个问题的人有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.