Imagen tridimensional para lograr cortes en cualquier dirección y tamaño

Study-VTK: Realice el corte de cualquier plano

0 背景:
1 案例:
2切割类介绍
    3.0 vtkExtractVOI
    3.1 vtkImageReslice
3 案例实现
    1.1 切割的实现:
    1.2 计算焦点点:
    1.3 一般输入影像都是dcm,需要保存成vti:

0 Antecedentes:

Hay dos tipos de vtk para la extracción de imágenes en 3D (imagen), vtkExtractVOI y vtkImageReslice. El uso razonable de estos dos puede realizar cortes de imágenes en 3D de cualquier tamaño y dirección.
  Documento de doxygen: vtkExtractVOI, vtkImageReslice
1 Caso:

En la demostración implementada con estas dos clases, primero use vtkImageReslice para pasar por el centro de la imagen y corte la imagen con el sistema de coordenadas del proceso. Luego calcule la distancia desde los cuatro puntos al centro y conviértala a las coordenadas correspondientes en la nueva imagen, y luego use vtkExtractVOI para cortar. Realice el corte del modelo en cualquier dirección y tamaño. Este método solo puede tener dos ejes a la vez, así que repítelo de nuevo (la segunda vez, xey son exactamente opuestos). El espacio no se puede ignorar al calcular, de lo contrario, el nuevo corte se deformará.

process x轴:长轴(鼠标选的前两个点)方向;
process y轴:original 的Z轴方向;
process z轴:鼠标选的后两个点方向。

La selección de cuatro puntos usa vtkBiDimensionalWidget

Agregue una descripción de la imagen Agregue una descripción de la imagen
2 Introducción a la clase de corte
3.0 vtkExtractVOI

vtkExtractVOI es un filtro que se utiliza para seleccionar una parte del conjunto de datos de puntos estructurados de entrada o una submuestra del conjunto de datos de entrada. (La parte de interés seleccionada se denomina volumen de interés o VOI). La salida de este filtro es un conjunto de datos de puntos estructurados. Este filtro procesa datos de entrada de cualquier tamaño topológico (es decir, punto, línea, imagen o volumen) y puede generar datos de salida de cualquier tamaño topológico.
  Para usar este filtro, configure VOI ivar, que son índices mínimos / máximos ijk, que se usan para especificar un área rectangular en los datos. (Tenga en cuenta que se trata de compensaciones 0). También puede especificar la frecuencia de muestreo para submuestrear los datos.
  Las aplicaciones típicas de este filtro son extraer cortes de un volumen para el procesamiento de imágenes, submuestrear un gran volumen para reducir el tamaño de los datos o utilizar los datos de interés para extraer un área de volumen.
  uso:

virtual void SetVOI (int [6])
// Extrae las coordenadas diagonales de roi en el sistema de coordenadas de la imagen original
virtual void SetSampleRate (int, int, int)
// frecuencia de muestreo en los tres ejes de xyz

1
2
3
4

3.1 vtkImageReslice

Recorte el volumen a lo largo de un nuevo conjunto de ejes.
  vtkImageReslice es la navaja suiza de filtros de geometría de imagen: puede reemplazar, rotar, voltear, escalar, volver a muestrear, deformar y rellenar datos de imagen en cualquier combinación con una eficiencia muy alta.
  uso:

SetOutputDimensionality (int);
// 设置输出 结果是几维的 1/2/3
SetResliceAxes (vtkMatrix4x4 *);
// 设置变换矩阵
SetInterpolationModeToLinear();
// 设置采样方法

1
2
3
4
5
6

La matriz de transformación tiene muchas entradas de interfaz
. Inserte la descripción de la imagen aquí.
  Método de remuestreo: lineal, lineal cúbico, vecino más cercano
. Inserte la descripción de la imagen aquí.
3 Realización del caso
1.1 Realización del corte:

Calcule el nuevo sistema de coordenadas y corte con vtkImageReslice

QList<QList<double>>points = original_bidimensional_->GetDisplayPosition();
QList<double> center = vti_original_widget_->GetCenter();
QList<double> origin = vti_original_widget_->GetOrigin();
QList<double> spacing = vti_original_widget_->GetSpacing();
QList<qint32> extent = vti_original_widget_->GetExtent();
double k = (points.at(0).at(1) - points.at(1).at(1)) /
           (points.at(0).at(0) - points.at(1).at(0));
double jiaodu = atan(k);
double axialElements[16] = {
    cos(jiaodu), 0, cos(jiaodu + 1.57), 0,
    sin(jiaodu), 0,  sin(jiaodu + 1.57), 0,
    0, 1, 0, 0,
    0, 0, 0, 1
};
vtkNew<vtkMatrix4x4> resliceAxes ;
resliceAxes->DeepCopy(axialElements);
resliceAxes->SetElement(0, 3, center.at(0));
resliceAxes->SetElement(1, 3, center.at(1));
resliceAxes->SetElement(2, 3, center.at(2));
vtkNew<vtkImageReslice> reslice;
reslice->SetInputData(vti_original_widget_->GetVtkImageData());
reslice->SetOutputDimensionality(3);
reslice->SetResliceAxes(resliceAxes);
reslice->SetInterpolationModeToLinear();
reslice->Update();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

Calcule la distancia y extráigala con vtkExtractVOI.

int atenúa [3];
reslice-> GetOutput () -> GetDimensions (atenúa);
vtkNew extract_voi;
extract_voi-> SetInputData (reslice-> GetOutput ());
qint32 nuevo_z1, nuevo_z2, nuevo_y1, nuevo_y2;
{ doble b = centro.at (1) - centro.at (0) * k; doble línea_a, línea_b, línea_c; line_a = k; line_b = -1; line_c = b; doble longitud1, longitud2; longitud1 = abs (línea_a * puntos.at (2) .at (0) + línea_b * puntos.at (2) .at (1) + línea_c) / sqrt (línea_a * línea_a + línea_b * línea_b); longitud2 = abs (línea_a * puntos.at (3) .at (0) + línea_b * puntos.at (3) .at (1) + línea_c) / sqrt (línea_a * línea_a + línea_b * línea_b); new_z1 =















static_cast (0.5 * (extensión.at (1) - extensión.at (0)) - longitud1 / espaciado.at (0));
new_z2 =
static_cast (0.5 * (extensión.at (1) - extensión.at (0)) + longitud2 / espaciado.at (0));
}
{ doble b = centro.at (1) - centro.at (0) * (-1 / k); doble línea_a, línea_b, línea_c; line_a = -1 / k; line_b = -1; line_c = b; doble longitud1, longitud2; longitud1 = abs (línea_a * puntos.at (1) .at (0) + línea_b * puntos.at (1) .at (1) + línea_c) / sqrt (línea_a * línea_a + línea_b * línea_b); longitud2 = abs (línea_a * puntos.at (0) .at (0) + línea_b * puntos.at (0) .at (1) + línea_c) / sqrt (línea_a * línea_a + línea_b * línea_b); new_y1 =















static_cast (0.5 * (extensión.at (3) - extensión.at (2)) -
(longitud1 / espaciado.at (0)));
new_y2 =
static_cast (0.5 * (extensión.at (3) - extensión.at (2)) +
(longitud2 / espaciado.at (0)));
}
extract_voi-> SetVOI (
nuevo_y1> nuevo_y2? nuevo_y2: nuevo_y1,
nuevo_y1> nuevo_y2? nuevo_y1: nuevo_y2,
0, atenúa [1],
nuevo_z1> nuevo_z2? nuevo_z2: nuevo_z1,
nuevo_z1> nuevo_z2? nuevo_z1
);
extract_voi-> Actualizar ();
vti_process_widget _-> SetVtkImageData (extract_voi-> GetOutput ());
vti_process_widget _-> BuildView ();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

1.2 Calcule el punto focal:

vtkBiDimensionalRepresentation2D parece tener sólo cuatro puntos de coordenadas mundiales y coordenadas locales y dos longitudes de línea recta. No hay un foco central, por lo que debe encontrarlo usted mismo.

QList <QList> ImageBiDimensional :: GetDisplayPosition () const { double p1 [3]; representación _-> GetPoint1WorldPosition (p1); doble p2 [3]; representación _-> GetPoint2WorldPosition (p2); doble p3 [3]; representación _-> GetPoint3WorldPosition (p3); doble p4 [3]; representación _-> GetPoint4WorldPosition (p4); Puntos QList <QList>; QList punto1, punto2, punto3, punto4, punto5; punto1 << p1 [0] << p1 [1] << p1 [2]; punto2 << p2 [0] << p2 [1] << p2 [2]; punto3 << p3 [0] << p3 [1] << p3 [2]; punto4 << p4 [0] << p4 [1] << p4 [2]; puntos << punto1 << punto2 << punto3 << punto4; doble p5 [2]; doble a1 = p2 [1] - p1 [1];

















doble b1 = p1 [0] - p2 [0];
doble c1 = p1 [0] * p2 [1] - p2 [0] * p1 [1];
doble a2 = p4 [1] - p3 [1];
doble b2 = p3 [0] - p4 [0];
doble c2 = p3 [0] * p4 [1] - p4 [0] * p3 [1];
det doble = a1 * b2 - a2 * b1;
p5 [0] = (c1 * b2 - c2 * b1) / det;
p5 [1] = (a1 * c2 - a2 * c1) / det;
punto5 << p5 [0] << p5 [1];
puntos << punto5;
puntos de retorno;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

1.3 Generalmente, las imágenes de entrada son dcm y deben guardarse como vti:

Parece que vtkDICOMXXXXX es difícil de usar, por lo que las imágenes dcm y nii se leen y escriben con itk y luego se convierten a vti. mhd se puede leer y escribir directamente con vtk.

IntensityWindowingImageFilterType::Pointer intensityFilter =
    IntensityWindowingImageFilterType::New();
ReaderType::Pointer reader = ReaderType::New();
ImageIOType::Pointer dicomIO = ImageIOType::New();
reader->SetImageIO(dicomIO);
NamesGeneratorType::Pointer nameGenerator = NamesGeneratorType::New();
nameGenerator->SetUseSeriesDetails(true);
nameGenerator->SetDirectory("/home/yx/Pictures/影像/Deeplv_测试影像/75%");
using SeriesIdContainer = std::vector< std::string >;
const SeriesIdContainer &seriesUID = nameGenerator->GetSeriesUIDs();
auto seriesItr = seriesUID.begin();
auto seriesEnd = seriesUID.end();
using FileNamesContainer = std::vector< std::string >;
FileNamesContainer fileNames ;
std::string seriesIdentifier;
while (seriesItr != seriesEnd) {
    seriesIdentifier = seriesItr->c_str();
    fileNames = nameGenerator->GetFileNames(seriesIdentifier);
    ++seriesItr;
}
reader->SetFileNames(fileNames);
try {
    reader->Update();
} catch (itk::ExceptionObject &ex) {
    Q_UNUSED(ex)
    qWarning() << "read error";
}
intensityFilter->SetInput(reader->GetOutput());
intensityFilter->SetWindowMinimum(-200);
intensityFilter->SetWindowMaximum(400);
intensityFilter->SetOutputMinimum(0);
intensityFilter->SetOutputMaximum(1);
intensityFilter->Update();
typedef itk::ImageToVTKImageFilter< ImageType> itkTovtkFilterType;
itkTovtkFilterType::Pointer itkTovtkImageFilter = itkTovtkFilterType::New();
itkTovtkImageFilter->SetInput(intensityFilter->GetOutput());
itkTovtkImageFilter->Update();
vtkSmartPointer<vtkImageData> double_image_;
if (double_image_ == nullptr) {
    double_image_ = vtkSmartPointer<vtkImageData>::New();
}
double_image_->DeepCopy(itkTovtkImageFilter->GetOutput());
qint32 extent[6];
double spacing[3];
double origin[3];
double_image_->GetExtent(extent);
double_image_->GetSpacing(spacing);
double_image_->GetOrigin(origin);
qDebug() << extent[0] << extent[1] << extent[2] << extent[3] << extent[4] << extent[5];
qDebug() << spacing[0] << spacing[1] << spacing[2];
qDebug() << origin[0] << origin[1] << origin[2];
vtkNew<vtkXMLImageDataWriter> writer;
writer->SetInputData(double_image_);
writer->SetFileName("/home/yx/Desktop/original.vti");
writer->Write();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

Tutorial de aprendizaje de vtk
Study-VTK

Este código de caso:
https://gitee.com/yaoxin001/WorkDemo

Página de inicio del blog personal
http://118.25.63.144/

Supongo que te gusta

Origin blog.csdn.net/qq_23158477/article/details/113091620
Recomendado
Clasificación