vtkContourWidget圈选ROI区域并提取像素等信息

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

最近在学习使用vtkContourWidget这个类,就简单记录下学习过程。


一、简单介绍

vtkCardinalSpline 、vtkKochenekSpline 、 vtkParametricSpline 、vtkSCurveSpline这几个都挺类似有时间挨个看一遍

二、具体实现

1.头文件widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <vtkSmartPointer.h>
#include <vtkDICOMImageReader.h>
#include <vtkImageViewer2.h>
#include <vtkImageAppend.h>
#include <vtkAutoInit.h>
#include <vtkContourWidget.h>
#include <vtkOrientedGlyphContourRepresentation.h>
#include <vtkImageActorPointPlacer.h>
#include <QVTKOpenGLWidget.h>

VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkInteractionStyle);

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void initWidget(vtkImageViewer2* imageViewer, vtkImageData* imageData, QVTKOpenGLWidget *widget);
private slots:
    void on_pbDrawContour_clicked();

    void on_pbROI_clicked();
private:
    Ui::Widget *ui;

    vtkSmartPointer<vtkImageViewer2>       m_sourceImageView;
    vtkSmartPointer<vtkImageViewer2>       m_roiImageView;

    vtkImageData* m_imageData;
    vtkSmartPointer<vtkOrientedGlyphContourRepresentation> m_rep;

    vtkSmartPointer<vtkContourWidget> m_contourWidget;
};
#endif // WIDGET_H


 

2.实现widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <vtkRenderWindow.h>
#include <QDebug>
#include <vtkImageEllipsoidSource.h>
#include <vtkImageData.h>
#include <vtkImageMask.h>
#include <vtkProperty.h>
#include <vtkPolyDataToImageStencil.h>
#include <vtkImageStencilToImage.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkJPEGReader.h>
#include <vtkDataArray.h>
#include <vtkPointData.h>
#include <vtkXMLImageDataReader.h>
#include <vtkImageShiftScale.h>
#include <vtkMetaImageWriter.h>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    vtkSmartPointer<vtkImageData> image = vtkSmartPointer<vtkImageData>::New();
    vtkSmartPointer<vtkXMLImageDataReader> reader = vtkSmartPointer<vtkXMLImageDataReader>::New();
    reader->SetFileName("test.vti");
    reader->Update();


    m_imageData = reader->GetOutput();
    m_sourceImageView = vtkSmartPointer< vtkImageViewer2 >::New();
    m_roiImageView    = vtkSmartPointer< vtkImageViewer2 >::New();

    initWidget(m_sourceImageView, m_imageData, ui->sourceWidget);
    initWidget(m_roiImageView, m_imageData, ui->roiWidget);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::initWidget(vtkImageViewer2 *imageViewer, vtkImageData *imageData, QVTKOpenGLWidget *widget)
{
    imageViewer->SetInputData(imageData);   // 加载数据

    // 设置交互对象
    imageViewer->SetupInteractor(widget->GetInteractor());

    // 设置渲染窗口actor
    imageViewer->SetRenderWindow(widget->GetRenderWindow());

    // 设置交互样式
    vtkSmartPointer<vtkInteractorStyleImage> m_style = vtkSmartPointer<vtkInteractorStyleImage>::New();
    widget->GetRenderWindow()->GetInteractor()->SetInteractorStyle(m_style);

    imageViewer->SetSliceOrientationToXY();
    imageViewer->Render();
}

void Widget::on_pbDrawContour_clicked()
{
    m_contourWidget = vtkSmartPointer<vtkContourWidget>::New();
    m_rep = vtkSmartPointer<vtkOrientedGlyphContourRepresentation>::New();
    m_rep->GetLinesProperty()->SetColor(1, 0, 0); // Set color to red
    m_rep->GetLinesProperty()->SetLineWidth(2);
    m_contourWidget->SetRepresentation(m_rep);

    vtkSmartPointer<vtkImageActorPointPlacer> p_w_picpathActorPointPlacer = vtkSmartPointer<vtkImageActorPointPlacer>::New();
    p_w_picpathActorPointPlacer->SetImageActor(m_sourceImageView->GetImageActor());
    m_rep->SetPointPlacer(p_w_picpathActorPointPlacer);

    m_contourWidget->SetInteractor(ui->sourceWidget->GetRenderWindow()->GetInteractor());
    m_contourWidget->SetEnabled(true);
    m_contourWidget->ProcessEventsOn();
}

void Widget::on_pbROI_clicked()
{
    double *spacing = m_imageData->GetSpacing();
    double *origin  = m_imageData->GetOrigin();
    int *dims        = m_imageData->GetDimensions();

    // 将 polydata 转换为 二值图像
    // 1、从 ContourWidget 提取 polydata 数据并处理
    vtkPolyData * polydata = m_rep->GetContourRepresentationAsPolyData();
    vtkSmartPointer<vtkPolyDataToImageStencil> polyDataToImageStencil = vtkSmartPointer<vtkPolyDataToImageStencil>::New();
    polyDataToImageStencil->SetInputData(polydata);
    polyDataToImageStencil->SetOutputOrigin(origin);
    polyDataToImageStencil->SetOutputSpacing(spacing);
    polyDataToImageStencil->SetOutputWholeExtent(0, dims[0] - 1, 0, dims[1] - 1, 0, 0);//设置范围
    polyDataToImageStencil->Update();

    // 2、将 polydata 转换为 二值图像
    vtkSmartPointer<vtkImageStencilToImage> imageStencilToImage = vtkSmartPointer<vtkImageStencilToImage>::New();
    imageStencilToImage->SetInputConnection(polyDataToImageStencil->GetOutputPort());
    imageStencilToImage->SetInsideValue(255);     // 封闭图像内部为白色
    imageStencilToImage->SetOutsideValue(0);      // 封闭图像外部为黑色
    imageStencilToImage->Update();

    //3、将输入图像灰度调整到0-255范围
    double ImageOriRange[2];
    m_imageData->GetScalarRange(ImageOriRange);//图像灰度范围最小值、最大值
    vtkSmartPointer<vtkImageShiftScale> shiftScaleFilter = vtkSmartPointer<vtkImageShiftScale>::New();
    shiftScaleFilter->SetInputData(m_imageData);

    shiftScaleFilter->SetShift(-1.0*ImageOriRange[0]);//用于设置偏移量Shift
    shiftScaleFilter->SetScale(255.0 / (ImageOriRange[1] - ImageOriRange[0]));//将灰度级变为0-255

    shiftScaleFilter->SetOutputScalarTypeToFloat();//>SetOutputScalarTypeToUnsignedChar();//指定其数据类型为UnsignedChar
    shiftScaleFilter->Update();

    m_imageData->DeepCopy(shiftScaleFilter->GetOutput());

    // 4、提取 ROI 区域(这里提取的ROI区域就是我们所看见的那一层图像)
    vtkNew<vtkImageMask> maskFilter;
    maskFilter->SetInputData(0, m_imageData);
    maskFilter->SetInputData(1, imageStencilToImage->GetOutput());
    maskFilter->SetMaskedOutputValue(0,0,0);
    maskFilter->Update();

    vtkSmartPointer<vtkImageData> roiImage = vtkSmartPointer<vtkImageData>::New();
    roiImage = maskFilter->GetOutput();

    //保存提取的区域(保存后可验证提取的ROI区域就是我们所看见的那一层图像)
    vtkSmartPointer<vtkMetaImageWriter> write = vtkSmartPointer<vtkMetaImageWriter>::New();
    write->SetInputData(roiImage);
    write->SetFileName("roi.mha");
    write->Write();

    //5、显示
    m_roiImageView->SetInputData(roiImage);
    m_roiImageView->Render();

    //6、计算ROI封闭区域的像素点个数,灰度均值,灰度最小值,灰度最大值
    int *dim = roiImage->GetDimensions();

    int num = 0;
    int pixelmax = 0;
    int pixelmin = 100;
    int sum = 0;

    for (int k = 0; k < dim[2]; ++k)
    {
        for (int i = 0; i < dim[1]; ++i)
        {
            for (int j = 0; j < dim[0]; ++j)
            {
                float* ptr1 = static_cast<float*>(roiImage->GetScalarPointer(i, j, k));

                if (*ptr1 > 0)
                {
                    cout << "I am not zero:" << endl;
                    num++;

                    if (*ptr1 > pixelmax)
                    {
                        pixelmax = *ptr1;
                    }

                    if (*ptr1 < pixelmin);
                    {
                        pixelmin = *ptr1;
                    }

                    sum += *ptr1;
                }

            }
        }
    }
    cout << "The pixels maximum is:" << pixelmax << endl;
    cout << "The pixels minimum is:" << pixelmin << endl;
    cout << "The total pixels num or Area is:" << num << endl;
    cout << "The mean pixels is:" << sum / num << endl;
}


感谢:lucky_sunshine的原创

参考如下:

VTK 椭圆圈取ROI区域_lucky_sunshine的博客-CSDN博客_vtk 椭圆

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值