1.vtkMarchingCubes读取骨骼和皮肤
2.代码
#include <QCoreApplication>
#include <QDebug>
#include <iostream>
#include <sstream>
#include <QtCore>
#include <QMainWindow>
#include <QWidget>
#include <QGuiApplication>
#include <QQuickView>
#include <QtQml>
#include <QQmlApplicationEngine>
//vtk
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkCylinderSource.h>
#include <vtkNamedColors.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <array>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkInteractionStyle);
//dicom
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkDICOMImageReader.h"
#include "vtkMarchingCubes.h"
#include "vtkStripper.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkSmartPointer.h"
#include "vtkProperty.h"
#include "vtkCamera.h"
#include "vtkOutlineFilter.h"
#include "vtkOBJExporter.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
vtkSmartPointer<vtkRenderer>ren=vtkSmartPointer<vtkRenderer>::New(); //设置绘制者(绘制对象指针)
vtkSmartPointer<vtkRenderWindow>renWin=vtkSmartPointer<vtkRenderWindow>::New(); //设置绘制窗口
renWin->AddRenderer(ren); //将绘制者加入绘制窗口
vtkSmartPointer<vtkRenderWindowInteractor>iren=vtkSmartPointer<vtkRenderWindowInteractor>::New();//设置绘制交互操作窗口的
iren->SetRenderWindow(renWin); //将绘制窗口添加到交互窗口
vtkSmartPointer<vtkDICOMImageReader>Reader=vtkSmartPointer<vtkDICOMImageReader>::New(); //创建读取dicom图片指针对象
Reader->SetDirectoryName("../../sunguihua/SGH"); //设置医学图像文件夹路径
Reader->SetDataByteOrderToLittleEndian();
Reader->Update();
cout<<"读取数据完成"<<endl;
//
vtkSmartPointer<vtkMarchingCubes>marchingcube=vtkSmartPointer<vtkMarchingCubes>::New(); //建立一个Marching Cubes 算法的对象
//marchingcube->SetInput((vtkDataSet *)Reader->GetOutput()); //获得所读取的数据
marchingcube->SetInputConnection(Reader->GetOutputPort()); //第二种读取数据的方法
marchingcube->SetValue(0,-700); //-700 1400 //提取出灰度值为45的东西
marchingcube->Update();
vtkSmartPointer<vtkStripper>Stripper=vtkSmartPointer<vtkStripper>::New(); //建立三角带对象
Stripper->SetInputConnection( marchingcube->GetOutputPort()); //将生成的三角片连接成三角带
vtkSmartPointer<vtkPolyDataMapper>Mapper=vtkSmartPointer<vtkPolyDataMapper>::New(); //建立一个数据映射对象
Mapper->SetInputConnection(Stripper->GetOutputPort() ); //将三角带映射为几何数据
Mapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor>actor=vtkSmartPointer<vtkActor>::New(); //建立一个代表皮肤的演员
actor->SetMapper(Mapper); //获得皮肤几何数据的属性
actor->GetProperty()->SetDiffuseColor(1, .49, .25); //设置皮肤颜色的属性//(1, .49, .25)
//actor->GetProperty()->SetDiffuseColor(1, 1, .25);
actor->GetProperty()->SetSpecular(0.3); //设置反射率
actor->GetProperty()->SetSpecularPower(20); //设置反射光强度
actor->GetProperty()->SetOpacity(1.0);
actor->GetProperty()->SetColor(1,0,0); //设置角色的颜色
actor->GetProperty()->SetRepresentationToWireframe();
vtkSmartPointer<vtkCamera>aCamera=vtkSmartPointer<vtkCamera>::New(); // 创建摄像机
aCamera->SetViewUp ( 0, 0, -1 ); //设置相机的“上”方向
aCamera->SetPosition ( 0, 1, 0 ); //位置:世界坐标系,设置相机位置
aCamera->SetFocalPoint( 0, 0, 0 ); //焦点:世界坐标系,控制相机方向
aCamera->ComputeViewPlaneNormal(); //重置视平面法向,基于当前的位置和焦点。否则会出现斜推剪切效果
///
vtkSmartPointer<vtkOutlineFilter>outlinefilter=vtkSmartPointer<vtkOutlineFilter>::New();
outlinefilter->SetInputConnection(Reader->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper>outlineMapper=vtkSmartPointer<vtkPolyDataMapper>::New();
outlineMapper->SetInputConnection(outlinefilter->GetOutputPort());
vtkSmartPointer<vtkActor>OutlineActor=vtkSmartPointer<vtkActor>::New();
OutlineActor->SetMapper(outlineMapper);
OutlineActor->GetProperty()->SetColor(0,0,0);
// 告诉绘制者将要在绘制窗口中进行显示的演员
ren->AddActor(actor);
ren->AddActor(OutlineActor);
ren->SetActiveCamera(aCamera); 设置渲染器的相机
ren->ResetCamera();
aCamera->Dolly(1.5); //使用Dolly()方法沿着视平面法向移动相机,实现放大或缩小可见角色物体
ren->SetBackground(1,1,1); //设置背景颜色
//ren->ResetCameraClippingRange();
renWin->SetSize(1000, 600);
renWin->Render();
iren->Initialize();
iren->Start();
return app.exec();
}
问题:
(1)stripple 的输出仍然是网格,没有连接成面?mapper的输入可以是marchingcube或者stripple。
(2)骨骼的灰度值是140,皮肤的灰度值是-700
3.从MarchingCube中读取点集数据,存储到.xyz文件
//获得点集
vtkSmartPointer<vtkPolyData> source =
vtkSmartPointer<vtkPolyData>::New();
source->SetPoints(marchingcube->GetOutput()->GetPoints());
char *path = "../../DCM_points/sunguihua.xyz";
std::ofstream out;
out.open(path);
std::cout<<"Export "<< path << "...\n";
for(auto i=0 ;i<source->GetNumberOfPoints();i++)
{
double test[3];
marchingcube->GetOutput()->GetPoint(i, test);
//source->GetPoint(i, test);
std::cout<<test[0]<<" "<<test[1]<<" "<<test[2]<<std::endl;
out<<test[0]<<" "<<test[1]<<" "<<test[2]<<std::endl;
}
std::cout<<source->GetNumberOfPoints()<<std::endl;
out.close();
std::cout<<"exportXYZ finished..."<<std::endl;
4.从.xyz中读取数据存储到vector中。(一行有三个数据或超过3个数据)
void RegistrationPointCloud::getVectorFieldData(std::string DataPath, std::vector<std::vector<float>> &tempMatrix)
{
std::ifstream infile_v(DataPath);
std::vector<float> temp_line;
std::string line;
tempMatrix.clear();
temp_line.clear();
float temp{};
while (getline(infile_v, line)) { //按行读取
std::stringstream lineTxt{};
lineTxt << line;
// while (lineTxt >> temp) {
// std::cout << temp << " ";
// temp_line.push_back(temp); //将数据转化为int型并存入一维vector中
// }
int count=3;
while ((lineTxt >> temp)&&(count--)) {
std::cout << temp << " ";
temp_line.push_back(temp); //将数据转化为int型并存入一维vector中
}
std::cout << endl;
tempMatrix.push_back(temp_line); //保存所有数据
temp_line.clear();
}
cout << endl << endl;
}
5.vector中的点数据,转化为VTK的polydata数据
void RegistrationPointCloud::writeDataToVtk(vtkSmartPointer<vtkPolyData> &polydata, std::vector<std::vector<float>> &tempMatrix,std::string dataOutPutPath, bool isSave)
{
//创建几何数据,没有拓扑数据
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
for(auto temp:tempMatrix)
{
points->InsertNextPoint(temp[0],temp[1],temp[2]);
}
//把几何数据(拓扑数据为空)放入到某个数据集中
polydata = vtkSmartPointer<vtkPolyData>::New();
polydata->SetPoints(points);
//将polydata类型的数据写到一个vtk文件中
if(isSave)
{
vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New();
writer->SetFileName(dataOutPutPath.c_str());
writer->SetInputData(polydata);
writer->Write();
}
}
6.VOI提取Dicm的一片区域
#include <vtkExtractVOI.h>
voi
/**
* @brief 提取体中感兴趣的某一区域块*/
vtkSmartPointer<vtkExtractVOI> extractVOI =
vtkSmartPointer<vtkExtractVOI>::New();
extractVOI->SetInputConnection(Reader->GetOutputPort());
int* dim = Reader->GetOutput()->GetDimensions();
std::cout << "Dims: " << " x: " << dim[0]
<< " y: " << dim[1]
<< " z: " << dim[2] << std::endl;
extractVOI->SetVOI(0,4.*dim[0]/4-1,3*dim[1]/4,4.*dim[1]/4.-1,0,4.*dim[2]/4-1);
extractVOI->Update();
//
vtkSmartPointer<vtkMarchingCubes>marchingcube=vtkSmartPointer<vtkMarchingCubes>::New(); //建立一个Marching Cubes 算法的对象
//marchingcube->SetInput((vtkDataSet *)Reader->GetOutput()); //获得所读取的数据
marchingcube->SetInputConnection(extractVOI->GetOutputPort()); //第二种读取数据的方法
marchingcube->SetValue(0,-700); //-500 //提取出灰度值为45的东西
marchingcube->Update();
7.对VOI做处理,去除不连续的区域,使脸部的点云数据只有一层
#include <vtkPolyDataConnectivityFilter.h>
// To remain largest region
vtkSmartPointer<vtkPolyDataConnectivityFilter> confilter =
vtkSmartPointer<vtkPolyDataConnectivityFilter>::New();
confilter->SetInputConnection(marchingcube->GetOutputPort());
confilter->SetExtractionModeToClosestPointRegion();
confilter->Update();
//获得点集
vtkSmartPointer<vtkPolyData> targ =
vtkSmartPointer<vtkPolyData>::New();
targ->SetPoints(confilter->GetOutput()->GetPoints());