VTK 鼠标交互实时显示窗口内图像的像素坐标(二维图像)

 

【2021.2.3更新部分:

有很多读者反映这个代码运行得时候出问题,那我就再推荐一个例子:https://kitware.github.io/vtk-examples/site/Cxx/Interaction/PointPicker/

显示在这里的都是我亲测过的!有可能版本什么的原因导致的,如果出问题的话,大家可以去官网例子里(https://kitware.github.io/vtk-examples/site/)找找,都可以找到的。】

 

 

 这是VTK的例子:(大家说的出问题的就是这个,我也亲测过的)

https://vtk.org/Wiki/VTK/Examples/Cxx/Images/PickPixel 

注意:主函数里(main)一定有一个picker已经建立好了,交互的时候鼠标取点才有用;

有的小伙伴取点后得到的世界坐标一直是0,就是因为主函数没有建立picker

#include <vtkVersion.h>
#include <vtkAssemblyPath.h>
#include <vtkCell.h>
#include <vtkCommand.h>
#include <vtkCornerAnnotation.h>
#include <vtkDataArray.h>
#include <vtkImageActor.h>
#include <vtkImageData.h>
#include <vtkImageViewer2.h>
#include <vtkInteractorStyleImage.h>
#include <vtkDICOMImageReader.h>
#include <vtkPointData.h>
#include <vtkPropPicker.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkTextProperty.h>

// The mouse motion callback, to pick the image and recover pixel values
class vtkImageInteractionCallback1 : public vtkCommand
{
public:
    
    static vtkImageInteractionCallback1 *New()
    {
        return new vtkImageInteractionCallback1;
    }
    
    vtkImageInteractionCallback1()
    {
        this->Viewer = 0;
        this->Picker = 0;
        this->Annotation = 0;
        this->PointData = vtkPointData::New();
    }
    
    ~vtkImageInteractionCallback1()
    {
        this->Viewer = 0;
        this->Picker = 0;
        this->Annotation = 0;
        this->PointData->Delete();
    }
    
    void SetPicker(vtkPropPicker *picker)
    {
        this->Picker = picker;
    }
    
    void SetAnnotation(vtkCornerAnnotation *annotation)
    {
        this->Annotation = annotation;
    }
    
    void SetViewer(vtkImageViewer2 *viewer)
    {
        this->Viewer = viewer;
    }
    
    virtual void Execute(vtkObject *, unsigned long vtkNotUsed(event), void *)
    {
        //this->Viewer;
        vtkRenderWindowInteractor *interactor =
        this->Viewer->GetRenderWindow()->GetInteractor();
        vtkRenderer* renderer = this->Viewer->GetRenderer();
        vtkImageActor* actor = this->Viewer->GetImageActor();
        vtkImageData* image = this->Viewer->GetInput();
        vtkInteractorStyle *style = vtkInteractorStyle::SafeDownCast(
                                                                     interactor->GetInteractorStyle());
        
#if VTK_MAJOR_VERSION <= 5
        image->Update();
#endif
        
        // Pick at the mouse location provided by the interactor
        this->Picker->Pick( interactor->GetEventPosition()[0],
                           interactor->GetEventPosition()[1],
                           0.0, renderer );
        
        // There could be other props assigned to this picker, so
        // make sure we picked the image actor
        vtkAssemblyPath* path = this->Picker->GetPath();
        bool validPick = false;
        
        if( path )
        {
            vtkCollectionSimpleIterator sit;
            path->InitTraversal( sit );
            vtkAssemblyNode *node;
            for( int i = 0; i < path->GetNumberOfItems() && !validPick; ++i )
            {
                node = path->GetNextNode( sit );
                if( actor == vtkImageActor::SafeDownCast( node->GetViewProp() ) )
                {
                    validPick = true;
                }
            }
        }
        
        if( !validPick )
        {
            this->Annotation->SetText( 0, "Off Image" );
            interactor->Render();
            // Pass the event further on
            style->OnMouseMove();
            return;
        }
        
        // Get the world coordinates of the pick
        double pos[3];
        this->Picker->GetPickPosition( pos );
        // Fixes some numerical problems with the picking
        double *bounds = actor->GetDisplayBounds();
        int axis = this->Viewer->GetSliceOrientation();
        pos[axis] = bounds[2*axis];
        cout<<pos[0]<<pos[1]<<pos[2]<<endl;
        vtkPointData* pd = image->GetPointData();
        if( !pd )
        {
            return;
        }
        
        this->PointData->InterpolateAllocate( pd, 1, 1 );
        
        // Use tolerance as a function of size of source data
        double tol2 = image->GetLength();
        tol2 = tol2 ? tol2*tol2 / 1000.0 : 0.001;
        
        // Find the cell that contains pos
        int subId;
        double pcoords[3], weights[8];
        vtkCell* cell = image->FindAndGetCell(
                                              pos, NULL, -1, tol2, subId, pcoords, weights );
        if( cell )
        {
            // Interpolate the point data
            this->PointData->InterpolatePoint( pd, 0, cell->PointIds, weights );
            int components =
            this->PointData->GetScalars()->GetNumberOfComponents();
            double* tuple = this->PointData->GetScalars()->GetTuple( 0 );
            
            std::string message = "Location: ( ";
            message += vtkVariant( pos[0] ).ToString();
            message += ", ";
            message += vtkVariant( pos[1] ).ToString();
            message += ", ";
            message += vtkVariant( pos[2] ).ToString();
            message += " )\nValue: ( ";
            
            for( int c = 0; c < components; ++c )
            {
                message += vtkVariant( tuple[ c ] ).ToString();
                if( c != components - 1 )
                {
                    message += ", ";
                }
            }
            message += " )";
            this->Annotation->SetText( 0, message.c_str() );
            interactor->Render();
            style->OnMouseMove();
        }
    }
    
private:
    
    // Pointer to the viewer
    vtkImageViewer2 *Viewer;
    
    // Pointer to the picker
    vtkPropPicker *Picker;
    
    // Pointer to the annotation
    vtkCornerAnnotation *Annotation;
    
    // Interpolator
    vtkPointData* PointData;
};


int main ( int argc, char* argv[] )
{
   
  
    vtkSmartPointer<vtkDICOMImageReader> reader =vtkSmartPointer<vtkDICOMImageReader>::New();
    reader->SetFileName( "/Users/mac/Desktop/CT数据/肺2/YeGuangKun_04_0060_0061.dcm" );
    reader->Update();
    
    
    
    // Picker to pick pixels
    vtkSmartPointer<vtkPropPicker> propPicker =
    vtkSmartPointer<vtkPropPicker>::New();
    propPicker->PickFromListOn();
    
    // Give the picker a prop to pick
    vtkSmartPointer<vtkImageViewer2> imageViewer =
    vtkSmartPointer<vtkImageViewer2>::New();
    propPicker->AddPickList( imageViewer->GetImageActor() );
    
    // Visualize
    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
    imageViewer->SetInputConnection(reader->GetOutputPort());
    imageViewer->SetupInteractor( renderWindowInteractor );
    imageViewer->SetSize( 600, 600 );
    
    vtkRenderer* renderer = imageViewer->GetRenderer();
    renderer->ResetCamera();
    renderer->GradientBackgroundOn();
    renderer->SetBackground(0,0,0);
    renderer->SetBackground2(1,1,1);
    
    // Annotate the image with window/level and mouse over pixel information
    vtkSmartPointer<vtkCornerAnnotation> cornerAnnotation =
    vtkSmartPointer<vtkCornerAnnotation>::New();
    cornerAnnotation->SetLinearFontScaleFactor( 2 );
    cornerAnnotation->SetNonlinearFontScaleFactor( 1 );
    cornerAnnotation->SetMaximumFontSize( 20 );
    cornerAnnotation->SetText( 0, "Off Image" );
    cornerAnnotation->SetText( 3, "<window>\n<level>" );
    cornerAnnotation->GetTextProperty()->SetColor( 1,0,0);
    
    imageViewer->GetRenderer()->AddViewProp( cornerAnnotation );
    
    // Callback listens to MouseMoveEvents invoked by the interactor's style
    vtkSmartPointer<vtkImageInteractionCallback1> callback =
    vtkSmartPointer<vtkImageInteractionCallback1>::New();
    callback->SetViewer( imageViewer );
    callback->SetAnnotation( cornerAnnotation );
    callback->SetPicker( propPicker );
    
    // InteractorStyleImage allows for the following controls:
    // 1) middle mouse + move = camera pan
    // 2) left mouse + move = window/level
    // 3) right mouse + move = camera zoom
    // 4) middle mouse wheel scroll = zoom
    // 5) 'r' = reset window/level
    // 6) shift + 'r' = reset camera
    vtkInteractorStyleImage* imageStyle = imageViewer->GetInteractorStyle();
    imageStyle->AddObserver( vtkCommand::MouseMoveEvent, callback );
    
    renderWindowInteractor->Initialize();
    renderWindowInteractor->Start();
    
    return EXIT_SUCCESS;
}

 显示结果:左下角是当前鼠标指向的像素点的坐标 (如果鼠标指向窗口的地方不是像素点,左下角显示OFF)

 

 

 

还有可参考的例子:https://vtk.org/Wiki/VTK/Examples/Cxx/Images/PickPixel2

 

 

  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 25
    评论
PyQt是一个用于创建图形用户界面的Python库,而VTK(Visualization Toolkit)是一个用于可视化和处理三维数据的开源库。结合PyQt和VTK可以实现在PyQt界面显示VTK三维图像的功能。 下面是一种常见的实现方式: 1. 首先,确保已经安装了PyQt和VTK库。 2. 创建一个PyQt的窗口类,继承自QWidget或QMainWindow。 3. 在窗口创建一个QVTKRenderWindowInteractor对象,用于在PyQt界面显示VTK图像。 4. 创建一个VTK的渲染器和渲染窗口对象,并将渲染窗口对象与QVTKRenderWindowInteractor对象关联。 5. 加载或生成需要显示的三维数据,并创建一个VTK的数据源对象。 6. 创建一个VTK的Mapper对象,将数据源对象与Mapper对象关联。 7. 创建一个VTK的Actor对象,将Mapper对象与Actor对象关联。 8. 将Actor对象添加到渲染器。 9. 最后,通过调用QVTKRenderWindowInteractor对象的Start()方法来启动渲染循环,显示VTK图像在PyQt界面。 下面是一个简单的示例代码: ```python import sys from PyQt5.QtWidgets import QApplication, QMainWindow from PyQt5.QtGui import QPalette, QColor from PyQt5.QtCore import Qt import vtk from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor class MainWindow(QMainWindow): def __init__(self): super().__init__() # 创建QVTKRenderWindowInteractor对象 self.vtkWidget = QVTKRenderWindowInteractor(self) # 创建VTK渲染器和渲染窗口对象 self.ren = vtk.vtkRenderer() self.renWin = self.vtkWidget.GetRenderWindow() self.renWin.AddRenderer(self.ren) # 加载或生成需要显示的三维数据 # ... # 创建VTK数据源对象 # ... # 创建VTK Mapper对象 # ... # 创建VTK Actor对象 # ... # 将Actor对象添加到渲染器 # ... # 设置窗口背景颜色 self.setAutoFillBackground(True) pal = self.palette() pal.setColor(QPalette.Background, QColor(0, 0, 0)) self.setPalette(pal) # 设置窗口布局 layout = QVBoxLayout() layout.addWidget(self.vtkWidget) centralWidget = QWidget() centralWidget.setLayout(layout) self.setCentralWidget(centralWidget) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) ``` 这是一个简单的示例,具体的实现方式可能会根据具体需求而有所不同。你可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值