Classe vtkProbeFiltervtkProbeFilter class
vtkProbeFilter
La classe peut échantillonner la valeur de données à la position de point spécifiée et peut filtrer les données scalaires (valeur scalaire, valeur vectorielle) des données source à la position de point spécifiée. Il s'agit d'une classe de filtre ; la classe prend en charge deux types d'entrée, y compris la géométrievtkProbeFilter
du filtre d'entrée et les données source à filtrer ; lors du calcul de la valeur de la position de point spécifiée, l'algorithme d'interpolation sera utilisé ; la classe copie les données source de chaque position de point spécifiée dans la sortie. La classe peut filtrer les données source transmises par un plan dans les données de volume tridimensionnelles, similaire à la fonction MPR ; la classe peut également rééchantillonner les données ou convertir un ensemble de données en un autre . Par exemple : Les grilles non structurées ( ) peuvent être sondées à l'aide de volumes (3D ) et les résultats visualisés à l'aide de techniques de rendu de volume. Ou sondez les données avec une ligne ou une courbe pour générer un tracé xy le long de cette ligne ou courbe. S'il s'agit d'une projection de surface de reconstruction de courbe, c'est la fonction de CPR ;vtkProbeFilter
vtkProbeFilter
vtkProbeFilter
DataSet
DataSet
vtkImageData
vtkUnstructuredGrid
vtkProbeFilter
Les classes peuvent effectuer une reconstruction de section et une reconstruction de surface. Il convient de noter que vtkProbeFilter
la sortie de la classe n'est pas vtkImageData
mais vtkDataSet
; si vtkProbeFilter
une classe reçoit un plan, elle produira le vtkImageReslice
même effet de rendu que la classe, si elle reçoit un ensemble de points irrégulier + topologie , il va générer une reconstruction de surface irrégulière ;
exemple
Exemple de site Web officiel CurvedReformation
namespace {
vtkSmartPointer<vtkPolyData> SweepLine(vtkPolyData* line, double direction[3],
double distance, unsigned int cols);
}
int main(int, char*[])
{
vtkNew<vtkNamedColors> colors;
// Parse arguments
std::string volumeFileName = "G:\\Data\\HeadMRVolume.mhd";
std::string polyDataFileName = "G:\\Data\\polyline.vtk";;
unsigned int resolution = 100;
// Read the volume data
vtkNew<vtkImageReader2Factory> imageFactory;
vtkSmartPointer<vtkImageReader2> imageReader;
imageReader.TakeReference(imageFactory->CreateImageReader2(volumeFileName.c_str()));
imageReader->SetFileName(volumeFileName.c_str());
imageReader->Update();
// Read the Polyline
vtkNew<vtkPolyDataReader> polyLineReader;
polyLineReader->SetFileName(polyDataFileName.c_str());
polyLineReader->Update();
vtkNew<vtkSplineFilter> spline;
spline->SetInputConnection(polyLineReader->GetOutputPort());
spline->SetSubdivideToSpecified();
spline->SetNumberOfSubdivisions(resolution);
// Sweep the line to form a surface
double direction[3];
direction[0] = 0.0;
direction[1] = 0.0;
direction[2] = 1.0;
double distance = 164;
spline->Update();
auto surface = SweepLine(spline->GetOutput(), direction, distance, 100);
// Probe the volume with the extruded surface
vtkNew<vtkProbeFilter> sampleVolume;
sampleVolume->SetInputData(1, imageReader->GetOutput());
sampleVolume->SetInputData(0, surface);
// Compute a simple window/level based on scalar range
vtkNew<vtkWindowLevelLookupTable> wlLut;
double range = imageReader->GetOutput()->GetScalarRange()[1] -
imageReader->GetOutput()->GetScalarRange()[0];
double level = (imageReader->GetOutput()->GetScalarRange()[1] +
imageReader->GetOutput()->GetScalarRange()[0]) / 2.0;
wlLut->SetWindow(range);
wlLut->SetLevel(level);
// Create a mapper and actor.
vtkNew<vtkDataSetMapper> mapper;
mapper->SetInputConnection(sampleVolume->GetOutputPort());
mapper->SetLookupTable(wlLut);
mapper->SetScalarRange(0, 255);
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
// Create a renderer, render window, and interactor
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetWindowName("CurvedReformation");
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(renderWindow);
// Add the actors to the scene
renderer->AddActor(actor);
renderer->SetBackground(colors->GetColor3d("DarkSlateGray").GetData());
// Set the camera for viewing medical images
renderer->GetActiveCamera()->SetViewUp(0, 0, 1);
renderer->GetActiveCamera()->SetPosition(0, 0, 0);
renderer->GetActiveCamera()->SetFocalPoint(0, 1, 0);
renderer->ResetCamera();
// Render and interact
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
namespace {
vtkSmartPointer<vtkPolyData> SweepLine(vtkPolyData* line, double direction[3],
double distance, unsigned int cols)
{
unsigned int rows = line->GetNumberOfPoints();
double spacing = distance / cols;
vtkNew<vtkPolyData> surface;
// Generate the points
cols++;
unsigned int numberOfPoints = rows * cols;
unsigned int numberOfPolys = (rows - 1) * (cols - 1);
vtkNew<vtkPoints> points;
points->Allocate(numberOfPoints);
vtkNew<vtkCellArray> polys;
polys->Allocate(numberOfPolys * 4);
double x[3];
unsigned int cnt = 0;
for (unsigned int row = 0; row < rows; row++) {
for (unsigned int col = 0; col < cols; col++) {
double p[3];
line->GetPoint(row, p);
x[0] = p[0] + direction[0] * col * spacing;
x[1] = p[1] + direction[1] * col * spacing;
x[2] = p[2] + direction[2] * col * spacing;
points->InsertPoint(cnt++, x);
}
}
// Generate the quads
vtkIdType pts[4];
for (unsigned int row = 0; row < rows - 1; row++) {
for (unsigned int col = 0; col < cols - 1; col++) {
pts[0] = col + row * (cols);
pts[1] = pts[0] + 1;
pts[2] = pts[0] + cols + 1;
pts[3] = pts[0] + cols;
polys->InsertNextCell(4, pts);
}
}
surface->SetPoints(points);
surface->SetPolys(polys);
return surface;
}
} // namespace
Si l'affichage SweepLine
retourné vtkPolygonData
est affiché sous forme de ligne, cela aura l'effet suivant :
vtkNew<vtkExtractEdges> extract;
extract->SetInputData(surface);
extract->Update();
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputData(extract->GetOutput());
Après avoir affiché l'entrée polyline.vtk
, on constate que la grille blanche est générée par une courbe rouge dans une direction ;
lecture de codes
fonction principale
1. Utilisez vtkImageReader2
la classe et vtkPolyDataReader
la classe pour interpréter respectivement le fichier HeadMRVolume.mhd/HeadMRVolume.raw
et le fichierpolyline.vtk
; HeadMRVolume.mhd/HeadMRVolume.raw
à l'intérieur se trouve un ensemble de séquences CT et le fichier polyline.vtk
est le contenu de la structure géométrique de la polyligne ;
2. Utilisez vtkSplineFilter
l'interpolation de la polyligne pour générer une courbe ;
3 . La méthode d'utilisation SweepLine
est à partir de la courbe précédente , pour générer un vtkPolyData
objet de surface, tel que la grille illustrée dans la figure ci-dessus ;
4. Définissez vtkProbeFilter
deux entrées : l'entrée 0 est vtkPolyData
l'objet de surfacesurface
; l'entrée 1 est la source de donnéesimageReader->GetOutput()
; 5. Définir la classe de table de mappage
en fonction de la plage des données de la source de données et ; 6. Définir et ; 7. Entrez le pipeline de rendu ; ----------------------- ------------- ------------------------------------- ------------- ------------------------------------- ------------- -------------------- Méthode SweepLine 1. Calculer le nombre de lignes à générer comme le nombre de points sur la courbe , et obtenez la direction de la colonne en fonction de la somme deimageReader->GetOutput()
vtkWindowLevelLookupTable
SetWindow
SetLevel
vtkDataSetMapper
SetLookupTable
SetScalarRange(0, 255)
surface
line->GetNumberOfPoints()
distance
cols
spacing
;
2. Calculer surface
le nombre de points internes numberOfPoints
sous la forme rows * cols
, et le nombre d'unités sous la forme (rows - 1) * (cols - 1)
;
3. Générer vtkPoints
des objets de classe points
et vtkCellArray
des objets de classe polys
;
4. Traverser et générer les coordonnées des points de chaque ligne et colonne, et les placer dans points
; chacun des quatre points adjacents constituent une unitéInsertNextCell(4, pts)
;
5. Définir la somme surface
de l'objet ; 6. Renvoyez l'objet ; il balaye de la courbe dans une direction. S'il balaye de la courbe aux deux extrémités, le résultat est similaire à la fonction de CPR, mais le le résultat doit être placé sur un plan. Image dimensionnelle ; convertir le résultat en un jeu de résultats, car la méthode utilise la courbe comme ligne Ligne et étend la colonne Col dans la direction ; selon les données 1, convertir le jeu de données ;SetPoints(points)
SetPolys(polys)
surface
SweepLine
vtkProbeFilter
vtkImageData
SweepLine
direction
vtkSmartPointer<vtkPolyData> final_poly = sampleVolume->GetPolyDataOutput();
vtkSmartPointer<vtkImageData> final_image = vtkSmartPointer<vtkImageData>::New();
final_image->SetDimensions(resolution + 1, resolution + 1, 1);
final_image->AllocateScalars(VTK_DOUBLE, 1);
final_image->SetSpacing(1, 1, 0);
int *dims = final_image->GetDimensions();
for (int y = 0; y < dims[1]; y++) {
for (int x = 0; x < dims[0]; x++) {
double *pixel = static_cast<double *>(final_image->GetScalarPointer(x, y, 0));
double value = final_poly->GetPointData()->GetScalars()->GetTuple1(dims[0] * y + x);
pixel[0] = value;
}
}
L'image résultante est inclinée vers la droite ;
Exemple de site Web officiel TissueLens
#include <vtkSphere.h>
#include <vtkClipDataSet.h>
#include <vtkCylinder.h>
int main(int, char*[])
{
vtkNew<vtkNamedColors> colors;
std::array<unsigned char, 4> skinColor{
{
240, 184, 160, 255} };
colors->SetColor("SkinColor", skinColor.data());
std::array<unsigned char, 4> backColor{
{
255, 229, 200, 255} };
colors->SetColor("BackfaceColor", backColor.data());
std::array<unsigned char, 4> bkg{
{
51, 77, 102, 255} };
colors->SetColor("BkgColor", bkg.data());
// Read the volume data
vtkNew<vtkMetaImageReader> reader;
reader->SetFileName("G:\\Data\\vtk-examples-master\\src\\Testing\\Data\\FullHead.mhd");
reader->Update();
// An isosurface, or contour value of 500 is known to correspond to the
// skin of the patient.
#ifdef USE_FLYING_EDGES
vtkNew<vtkFlyingEdges3D> skinExtractor;
#else
vtkNew<vtkMarchingCubes> skinExtractor;
#endif
skinExtractor->SetInputConnection(reader->GetOutputPort());
skinExtractor->SetValue(0, 1000);
// Define a spherical clip function to clip the isosurface
vtkNew<vtkSphere> clipFunction;
clipFunction->SetRadius(50);
clipFunction->SetCenter(73, 52, 15);
// Clip the isosurface with a sphere
vtkNew<vtkClipDataSet> skinClip;
skinClip->SetInputConnection(skinExtractor->GetOutputPort());
skinClip->SetClipFunction(clipFunction);
skinClip->SetValue(0);
skinClip->GenerateClipScalarsOn();
skinClip->Update();
vtkNew<vtkDataSetMapper> skinMapper;
skinMapper->SetInputConnection(skinClip->GetOutputPort());
skinMapper->ScalarVisibilityOff();
vtkNew<vtkActor> skin;
skin->SetMapper(skinMapper);
skin->GetProperty()->SetDiffuseColor(colors->GetColor3d("SkinColor").GetData());
vtkNew<vtkProperty> backProp;
backProp->SetDiffuseColor(colors->GetColor3d("BackfaceColor").GetData());
skin->SetBackfaceProperty(backProp);
// Define a model for the "lens". Its geometry matches the implicit
// sphere used to clip the isosurface
vtkNew<vtkSphereSource> lensModel;
lensModel->SetRadius(50);
lensModel->SetCenter(73, 52, 15);
lensModel->SetPhiResolution(100);
lensModel->SetThetaResolution(100);
// Sample the input volume with the lens model geometry
vtkNew<vtkProbeFilter> lensProbe;
lensProbe->SetInputConnection(lensModel->GetOutputPort());
lensProbe->SetSourceConnection(reader->GetOutputPort());
// Clip the lens data with the isosurface value
vtkNew<vtkClipDataSet> lensClip;
lensClip->SetInputConnection(lensProbe->GetOutputPort());
lensClip->SetValue(500);
lensClip->GenerateClipScalarsOff();
lensClip->Update();
// Define a suitable grayscale lut
vtkNew<vtkLookupTable> bwLut;
bwLut->SetTableRange(-600, 2048);
bwLut->SetSaturationRange(0, 0);
bwLut->SetHueRange(0, 0);
bwLut->SetValueRange(0, 1);
bwLut->Build();
vtkNew<vtkDataSetMapper> lensMapper;
lensMapper->SetInputConnection(lensClip->GetOutputPort());
lensMapper->SetScalarRange(lensClip->GetOutput()->GetScalarRange());
lensMapper->SetLookupTable(bwLut);
vtkNew<vtkActor> lens;
lens->SetMapper(lensMapper);
// It is convenient to create an initial view of the data. The FocalPoint
// and Position form a vector direction. Later on (ResetCamera() method)
// this vector is used to position the camera to look at the data in
// this direction.
vtkNew<vtkCamera> aCamera;
aCamera->SetViewUp(0, 0, -1);
aCamera->SetPosition(0, -1, 0);
aCamera->SetFocalPoint(0, 0, 0);
aCamera->ComputeViewPlaneNormal();
aCamera->Azimuth(30.0);
aCamera->Elevation(30.0);
// Create the renderer, the render window, and the interactor. The renderer
// draws into the render window, the interactor enables mouse- and
// keyboard-based interaction with the data within the render window.
//
vtkNew<vtkRenderer> aRenderer;
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(aRenderer);
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
// Actors are added to the renderer. An initial camera view is created.
// The Dolly() method moves the camera towards the FocalPoint,
// thereby enlarging the image.
aRenderer->AddActor(lens);
aRenderer->AddActor(skin);
aRenderer->SetActiveCamera(aCamera);
aRenderer->ResetCamera();
aCamera->Dolly(1.5);
// Set a background color for the renderer and set the size of the
// render window (expressed in pixels).
aRenderer->SetBackground(colors->GetColor3d("BkgColor").GetData());
renWin->SetSize(640, 480);
renWin->SetWindowName("TissueLens");
// Note that when camera movement occurs (as it does in the Dolly()
// method), the clipping planes often need adjusting. Clipping planes
// consist of two planes: near and far along the view direction. The
// near plane clips out objects in front of the plane; the far plane
// clips out objects behind the plane. This way only what is drawn
// between the planes is actually rendered.
aRenderer->ResetCameraClippingRange();
// Initialize the event loop and then start it.
renWin->Render();
iren->Initialize();
iren->Start();
return EXIT_SUCCESS;
}
lecture de codes
Lorsque le paramètre lensClip
est SetValue
défini sur 0, l'échelle de gris complète de l'hémisphère peut être affichée complètement. Lorsqu'il est défini sur 500, la valeur inférieure à 500 sera effacée ;
Lorsqu'un plan est composé de points et d'unités, une image plane en niveaux de gris + effet de rendu polygonal peut être générée, la limite inférieure de la valeur CT scalaire est contrainte
;vtkClipDataSet
#include <vtkSphere.h>
#include <vtkClipDataSet.h>
#include <vtkCylinder.h>
int main(int, char*[])
{
vtkNew<vtkNamedColors> colors;
std::array<unsigned char, 4> skinColor{
{
240, 184, 160, 255} };
colors->SetColor("SkinColor", skinColor.data());
std::array<unsigned char, 4> backColor{
{
255, 229, 200, 255} };
colors->SetColor("BackfaceColor", backColor.data());
std::array<unsigned char, 4> bkg{
{
51, 77, 102, 255} };
colors->SetColor("BkgColor", bkg.data());
// Read the volume data
vtkNew<vtkMetaImageReader> reader;
reader->SetFileName("G:\\Data\\vtk-examples-master\\src\\Testing\\Data\\FullHead.mhd");
reader->Update();
// An isosurface, or contour value of 500 is known to correspond to the
// skin of the patient.
#ifdef USE_FLYING_EDGES
vtkNew<vtkFlyingEdges3D> skinExtractor;
#else
vtkNew<vtkMarchingCubes> skinExtractor;
#endif
skinExtractor->SetInputConnection(reader->GetOutputPort());
skinExtractor->SetValue(0, 1000);
// Define a spherical clip function to clip the isosurface
vtkNew<vtkSphere> clipFunction;
clipFunction->SetRadius(50);
clipFunction->SetCenter(73, 52, 15);
// Clip the isosurface with a sphere
vtkNew<vtkClipDataSet> skinClip;
skinClip->SetInputConnection(skinExtractor->GetOutputPort());
skinClip->SetClipFunction(clipFunction);
skinClip->SetValue(0);
skinClip->GenerateClipScalarsOn();
skinClip->Update();
vtkNew<vtkDataSetMapper> skinMapper;
skinMapper->SetInputConnection(skinClip->GetOutputPort());
skinMapper->ScalarVisibilityOff();
vtkNew<vtkActor> skin;
skin->SetMapper(skinMapper);
skin->GetProperty()->SetDiffuseColor(
colors->GetColor3d("SkinColor").GetData());
vtkNew<vtkProperty> backProp;
backProp->SetDiffuseColor(colors->GetColor3d("BackfaceColor").GetData());
skin->SetBackfaceProperty(backProp);
vtkSmartPointer<vtkPoints> gridPoints = vtkSmartPointer<vtkPoints>::New();
vtkNew<vtkCellArray> polys;
for (unsigned int x = 0; x < 200; x++)
{
for (unsigned int y = 0; y < 200; y++)
{
gridPoints->InsertNextPoint(30 + x, 30 + y, 15 + 0);
}
}
vtkIdType pts[4];
for (unsigned int row = 0; row < 200 - 1; row++) {
for (unsigned int col = 0; col < 200 - 1; col++) {
pts[0] = col + row * (200);
pts[1] = pts[0] + 1;
pts[2] = pts[0] + 200 + 1;
pts[3] = pts[0] + 200;
polys->InsertNextCell(4, pts);
}
}
// Create a dataset from the grid points
vtkSmartPointer<vtkPolyData> gridPolyData = vtkSmartPointer<vtkPolyData>::New();
gridPolyData->SetPoints(gridPoints);
gridPolyData->SetPolys(polys);
// Sample the input volume with the lens model geometry
vtkNew<vtkProbeFilter> lensProbe;
lensProbe->SetInputData(gridPolyData);
lensProbe->SetSourceConnection(reader->GetOutputPort());
// Clip the lens data with the isosurface value
vtkNew<vtkClipDataSet> lensClip;
lensClip->SetInputConnection(lensProbe->GetOutputPort());
lensClip->SetValue(500);
lensClip->GenerateClipScalarsOff();
lensClip->Update();
// Define a suitable grayscale lut
vtkNew<vtkLookupTable> bwLut;
bwLut->SetTableRange(0, 2048);
bwLut->SetSaturationRange(0, 0);
bwLut->SetHueRange(0, 0);
bwLut->SetValueRange(0, 1);
bwLut->Build();
vtkNew<vtkDataSetMapper> lensMapper;
lensMapper->SetInputConnection(lensClip->GetOutputPort());
lensMapper->SetScalarRange(lensClip->GetOutput()->GetScalarRange());
lensMapper->SetLookupTable(bwLut);
vtkNew<vtkActor> lens;
lens->SetMapper(lensMapper);
// It is convenient to create an initial view of the data. The FocalPoint
// and Position form a vector direction. Later on (ResetCamera() method)
// this vector is used to position the camera to look at the data in
// this direction.
vtkNew<vtkCamera> aCamera;
aCamera->SetViewUp(0, 0, -1);
aCamera->SetPosition(0, -1, 0);
aCamera->SetFocalPoint(0, 0, 0);
aCamera->ComputeViewPlaneNormal();
aCamera->Azimuth(30.0);
aCamera->Elevation(30.0);
// Create the renderer, the render window, and the interactor. The renderer
// draws into the render window, the interactor enables mouse- and
// keyboard-based interaction with the data within the render window.
//
vtkNew<vtkRenderer> aRenderer;
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(aRenderer);
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
// Actors are added to the renderer. An initial camera view is created.
// The Dolly() method moves the camera towards the FocalPoint,
// thereby enlarging the image.
aRenderer->AddActor(lens);
aRenderer->AddActor(skin);
aRenderer->SetActiveCamera(aCamera);
aRenderer->ResetCamera();
aCamera->Dolly(1.5);
// Set a background color for the renderer and set the size of the
// render window (expressed in pixels).
aRenderer->SetBackground(colors->GetColor3d("BkgColor").GetData());
renWin->SetSize(640, 480);
renWin->SetWindowName("TissueLens");
// Note that when camera movement occurs (as it does in the Dolly()
// method), the clipping planes often need adjusting. Clipping planes
// consist of two planes: near and far along the view direction. The
// near plane clips out objects in front of the plane; the far plane
// clips out objects behind the plane. This way only what is drawn
// between the planes is actually rendered.
aRenderer->ResetCameraClippingRange();
// Initialize the event loop and then start it.
renWin->Render();
iren->Initialize();
iren->Start();
return EXIT_SUCCESS;
}
Les références
1. Tranche de reconstruction bidimensionnelle vtk II
2. CurvedReformation
3. Référence de classe vtkProbeFilter
4. TissueLens