Study-VTK:vtkWidget 分割/配准类之 放置种子点(Qt + vtkSeedWidget)

news/2024/7/24 13:33:43

vtkWidget 分割/配准类之 放置种子点(Qt + vtkSeedWidget)

    • 1 vtkSeedWidget介绍
    • 2 vtkSeedWidget 官方案例
    • 3 vtkSeedWidget常用函数
    • 4 vtkSeedWidget使用技巧
      • 4.1 开启/关闭 放置种子点交互
      • 4.2 绑定种子点增加/删除信号到Qt
      • 4.3 创建种子点增加/删除/移动 回调事件
      • 4.4 设置种子点数量,达到后只能移动无法新建
      • 4.5 初始化种子点数量和位置 QList

1 vtkSeedWidget介绍

  vtkSeedWidget 用于在场景中放置多个种子点。种子点可用于诸如连通性,分段和区域生长之类的操作。
  vtkSeedWidget默认交互操作:
     1. 鼠标点击widget上空白位置放置种子点
     2. 鼠标移入种子点(箭头变为小手),按下delete删除种子点
     3. 鼠标移入种子点(箭头变为小手),按住鼠标左键拖动可以移动种子点
  有放置对应就有拾取,如何自定义拾取每个点放在以后拾取的交互单独讲,这里只介绍vtk默认的拾取功能。

2 vtkSeedWidget 官方案例

  vtk官方提供了三个例子,用来演示如何使用vtkSeedWidget在三维/平面场景下放置种子点。且回调种子点增加、移动、删除信息。

SeedWidget
  空间场景中放置种子点。
在这里插入图片描述
SeedWidgetImage
  图片场景中放置种子点,而且增加回调信息(种子点数量、当前选择、移动坐标)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PFjTYKlx-15841
SeedWidgetWithCustomCallback
  空间场景中放置种子点,而且增加回调信息(种子点数量、当前选择、移动坐标)。
在这里插入图片描述

3 vtkSeedWidget常用函数

	void SetInteractor( vtkRenderWindowInteractor * ) override;
	// 设置交互器,如果不自定义使用默认的那么操作就是第一节介绍的vtkSeedWidget默认交互操作
	
	void SetRepresentation( vtkSeedRepresentation *rep )
	// 设置种子点,这个vtkSeedRepresentation放置和操作定义种子集合的点。
	// 这样有个好处就是,添加的种子点数据和界面是分开的(交互/实体 分开),可以多个界面展示同一组点

	void On() {this->SetEnabled(1);}
	void Off() {this->SetEnabled(0);}
	// 这一组设置vtkSeedWidget是否开启交互功能 (观察/命令 模式切换)
	//这两组对应使用实现vtkSeedWidget的开启关闭

	virtual void CompleteInteraction();
	// 设置只能移动删除种子点
	virtual void RestartInteraction();
	// 复位交互,可以增加、删除、移动种子点
	// 这两组对应使用实现vtkSeedWidget可以添加几个点

	void DeleteSeed(int n);
	// vtkSeedWidget交互/实体 分开,所以你想全部清空时候,只清空种子点模型是不行的

	int InvokeEvent(unsigned long event, void *callData);
	int InvokeEvent(const char *event, void *callData);
	// 这个就理解成Qt的信号吧,emit信号用的

4 vtkSeedWidget使用技巧

4.1 开启/关闭 放置种子点交互

  Off之后进入观察模式,只能看无法修改种子点。On之后开启种子点的交互。

void ImageSeeder::WidgetsOn() {
    if (this->seed_widget_ != nullptr) {
        this->seed_widget_->On();
    }
}

void ImageSeeder::WidgetsOff() {
    if (this->seed_widget_ != nullptr) {
        this->seed_widget_->Off();
    }
}

4.2 绑定种子点增加/删除信号到Qt

  交互/实体 分开的,其实只要清楚数量的改变就可以了,如果需要点坐标信息,去vtkSeedRepresentation里找。

if (this->connections_ == nullptr) {
            this->connections_ = vtkSmartPointer<vtkEventQtSlotConnect>::New();
            this->connections_->Connect(
                this->seed_widget_, vtkCommand::PlacePointEvent,
                this, SLOT(SlotAddSeed(vtkObject *, unsigned long,
                                       void *, void *)));
            this->connections_->Connect(
                this->seed_widget_, vtkCommand::DeletePointEvent,
                this, SLOT(SlotAddSeed(vtkObject *, unsigned long,
                                       void *, void *)));
        }
void ImageSeeder::SlotAddSeed(vtkObject *caller, unsigned long vtk_event,
                              void *client_data, void *call_data) {
    Q_UNUSED(client_data)
    Q_UNUSED(vtk_event)
    qint32 n = *static_cast<int *>(call_data);
    vtkSmartPointer<vtkSeedWidget> widget = dynamic_cast<vtkSeedWidget *>(caller);
    if (n >= 0 && widget) {
        qint32 num_seeds = widget->GetSeedRepresentation()->GetNumberOfSeeds();
        qDebug() << num_seeds;
    }
}

void ImageSeeder::SlotDeleteSeed(vtkObject *caller, unsigned long vtk_event,
                                 void *client_data, void *call_data) {
    Q_UNUSED(client_data)
    Q_UNUSED(vtk_event)
    qint32 n = *static_cast<int *>(call_data);
    vtkSmartPointer<vtkSeedWidget> widget = dynamic_cast<vtkSeedWidget *>(caller);
    if (n >= 0 && widget) {
        qint32 num_seeds = widget->GetSeedRepresentation()->GetNumberOfSeeds() - 1;
        qDebug() << num_seeds;
    }
}

4.3 创建种子点增加/删除/移动 回调事件

  如果用Qt的话,这个回调就不需要使用了。

  vtkSmartPointer<vtkSeedCallback> seedCallback =
    vtkSmartPointer<vtkSeedCallback>::New();
  seedCallback->SetRepresentation(rep);
  seedWidget->AddObserver(vtkCommand::PlacePointEvent,seedCallback);
  seedWidget->AddObserver(vtkCommand::InteractionEvent,seedCallback);
class vtkSeedCallback : public vtkCommand {
  public:
    static vtkSeedCallback *New() {
        return new vtkSeedCallback;
    }
    vtkSeedCallback() {}
    virtual void Execute(vtkObject *, unsigned long event, void *calldata) {
        if(event == vtkCommand::PlacePointEvent) {
            std::cout << "Point placed, total of: "
                      << this->SeedRepresentation->GetNumberOfSeeds() << std::endl;
        }
        if(event == vtkCommand::InteractionEvent) {
            if(calldata) {
                std::cout << "Interacting with seed : "
                          << *(static_cast< int * >(calldata)) << std::endl;
            }
        }
        std::cout << "List of seeds (Display coordinates):" << std::endl;
        for(vtkIdType i = 0; i < this->SeedRepresentation->GetNumberOfSeeds(); i++) {
            double pos[3];
            this->SeedRepresentation->GetSeedDisplayPosition(i, pos);
            std::cout << "(" << pos[0] << " "
                      << pos[1] << " " << pos[2] << ")" << std::endl;
        }
    }
    void SetRepresentation(vtkSmartPointer<vtkSeedRepresentation> rep) {
        this->SeedRepresentation = rep;
    }
  private:
    vtkSmartPointer<vtkSeedRepresentation> SeedRepresentation;
};

4.4 设置种子点数量,达到后只能移动无法新建

  4.2的槽函数修改下,达到一定数量后禁止添加。

void ImageSeeder::SlotAddSeed(vtkObject *caller, unsigned long vtk_event,
                              void *client_data, void *call_data) {
    Q_UNUSED(client_data)
    Q_UNUSED(vtk_event)
    qint32 n = *static_cast<int *>(call_data);
    if(n == max_points_sum) {
        this->WidgetDisable();
    }
    vtkSmartPointer<vtkSeedWidget> widget = dynamic_cast<vtkSeedWidget *>(caller);
    if (n >= 0 && widget) {
        qint32 num_seeds = widget->GetSeedRepresentation()->GetNumberOfSeeds();
        emit SignalSeedChanged(num_seeds);
    }
}

void ImageSeeder::SlotDeleteSeed(vtkObject *caller, unsigned long vtk_event,
                                 void *client_data, void *call_data) {
    Q_UNUSED(client_data)
    Q_UNUSED(vtk_event)
    qint32 n = *static_cast<int *>(call_data);
    if(n < max_points_sum) {
        this->seed_widget_->RestartInteraction();
    }
    vtkSmartPointer<vtkSeedWidget> widget = dynamic_cast<vtkSeedWidget *>(caller);
    if (n >= 0 && widget) {
        qint32 num_seeds = widget->GetSeedRepresentation()->GetNumberOfSeeds() - 1;
        emit SignalSeedChanged(num_seeds);
    }
}

4.5 初始化种子点数量和位置 QList<QList>

  交互/实体 分开的,只要在vtkSeedRepresentation添加点和坐标,vtkSeedWidget会自动更新的。这里的InvokeEvent()作用是发送点增加的信号,处理别的事情。

void ImageSeeder::SetSeedList(const QList<QList<double>> seed_list) {
    this->InitialSeeds();
    if (this->representation_ != nullptr) {
        for (qint32 i = 0; i < seed_list.size(); ++i) {
            double p[3] = {seed_list[i][0], seed_list[i][1], seed_list[i][2]};
            qint32 num = this->representation_->CreateHandle(p);
            vtkSmartPointer<vtkHandleWidget> handle = 
            		this->seed_widget_->CreateNewHandle();
            handle->SetEnabled(true);
            this->representation_->SetSeedWorldPosition(static_cast<quint32>(num), p);
            this->seed_widget_->InvokeEvent(vtkCommand::PlacePointEvent, &(num));
        }
    }
}

4.6 导入导出种子点 QList<QList>

  交互/实体 分开的,只要导入导出vtkSeedRepresentation就可以了,导入就是4.5的初始化。

QList<QList<double>> ImageSeeder::GetSeedList() const {
    QList<QList<double>> list;
    if (this->representation_ != nullptr) {
        qint32 num_seeds =
            this->representation_->GetNumberOfSeeds();
        for (qint32 i = 0; i < num_seeds; ++i) {
            double pos[3];
            this->representation_->GetSeedWorldPosition(static_cast<quint32>(i), pos);
            list.append({pos[0], pos[1], pos[2]});
        }
    }
    return list;
}







vtk学习教程
Study-VTK


http://www.niftyadmin.cn/n/883281.html

相关文章

redux-devtools安装 以及redux No store found. Make sure to follow the instructions.解决

插件链接 链接&#xff1a;https://pan.baidu.com/s/17ggewOjfpR_fRWhvHHUxug 提取码&#xff1a;zrch No store found. Make sure to follow the instructions 其实是缺少了 const composeEnhancers window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;原先代码 imp…

Study-VTK:安装vtk(python)

先看下deepin有没有安装python环境、以及版本。 ls /usr/bin/python* -l python2 --version python3 --versiondeepin默认装机是安装python2.7和python3.5的&#xff0c;这两个一般不要动。我之前把python3.5卸载了&#xff0c;deepin商店所有软件无法安装&#xff0c;浏览器输…

【react项目】jianshu介绍

jianshu项目功能介绍第三方库的使用和优化不足和思考项目功能介绍 项目地址https://gitee.com/thinkerwing/jianshu react-devtools https://blog.csdn.net/daddykei/article/details/119225518 搜索框功能动画及推荐和换一换功能 登录登出功能 下拉点击更多、回到顶部、详情…

Study-VTK:vtkWidget

Study-VTK&#xff1a;vtkWidgetvtk交互之 vtkWidgetvtk交互介绍vtkWidget继承关系图vtkWidget 详细使用创建Widget1. 测量类Widget  2. 标注类Widget  3. 分割/配准类Widget4. 其他Widget5. 待分类学习vtk交互之 vtkWidget vtk交互介绍 我们在与图形/图像交互时&#x…

element表单验证中rules中的message样式怎么更改,:inline-message=“true“,el-form-item__error--inline

element表单验证中rules中的message样式怎么更改&#xff0c;有很多解答都是直接定位到el-form-item__error&#xff0c;修改样式。 但是如果这么做&#xff0c;容易影响到全局&#xff0c;有些地方message的提示还是默认在input下框比较合适。代码附在最后。 效果演示 查看官…

Study-VTK:vtkWidget 标注类Widget之 在2D矩形区域周围放置边框 vtkBorderWidget

1 vtkBorderWidget介绍2 vtkBorderWidget 官方案例3 vtkBorderWidget事件绑定4 vtkBorderWidget常用函数5 vtkBorderWidget 使用技巧5.1设置左键可以拖拽5.2 获取当前坐标&#xff08;左上、右下角&#xff09;5.3 移动位置时打印坐标5.4 开启关闭1 vtkBorderWidget介绍 此类是…

Study-VTK:vtkWidget 标注类Widget之 文本显示vtkTextWidget

1 vtkTextWidget介绍2 vtkTextWidget 官方案例3 vtkTextWidget事件绑定4 vtkTextWidget常用函数5 vtkTextWidget 使用技巧5.1设置左键可以拖拽5.2 获取当前坐标&#xff08;左上、右下角&#xff09;5.3 移动位置时打印坐标5.4 开启关闭vtkTextWidget继承自vtkBorderWidget。使…

Study-VTK: vtk 9.0.0 已进入候选发布阶段!

&#xff08;20.03.16&#xff09;vtk 9.0.0 已进入候选发布阶段&#xff01; 最新版文档和安装包&#xff1a;https://vtk.org/download/#candidate   v9.0.0中与先前版本相比API更改的完整列表&#xff1a;新版本的改变内容   重要更改和新功能的预览&#xff1a; VTK的…