对掩膜数据进行MPR的操作,获取切面图像,并转换为RGB图像,使用OpenCV展示;
涉及功能点:
1.使用vtkNIFTIImageReader类读取nii.gz文件;
2.使用vtkImageReslice类获取切面图像;
3.二维的unsigned char数组转换为cv::Mat;
如何使用vtkImageReslice类获取切面图像,参考笔记:
VTK笔记-计算MPR切面-vtkImageReslice类_黑山老妖的博客的博客-CSDN博客_vtk 切面MPRMPR(Multi-planar Reformation),多平面重建;多平面重建是将扫描范围内所有的轴位图像叠加起来,再对某些标线标定的重组线所指定的组织进行冠状位、矢状位、任意角度斜位图像重组。MPR的优点1.能任意产生新的断层图像,而无需重复扫描;2.原图像的密度值被忠实保持到了结果图像上。3.曲面重组能在一副图像里展开显示弯曲物体的全长。MPR的缺点1.难以表达复杂的空间结构;2.曲面重组易造成假阳性;...https://blog.csdn.net/liushao1031177/article/details/118946205详细代码如下:
// bits是input数组的类型长度:char,short,int,long,float,double等等,是sizeof(T)
void Buffer2Mat_123(const unsigned char *input, int width, int height, int bits, cv::Mat &img)
{
if (input == NULL) return;
int bytes = width * height * bits / 8;
img = cv::Mat::zeros(height, width, bits == 8 ? CV_8UC1 : CV_8UC3);
memcpy(img.data, input, bytes);
}
int main(int, char*[])
{
test_niigz_mpr();
return 0;
}
void test_niigz_mpr()
{
vtkNew reader;
reader->SetFileName("G:/Data/mask_data.nii.gz");
reader->Update();
int extent[6] = { 0 };
double spacing[3] = { 0 };
double origin[3] = { 0 };
double center[3] = { 0 };
reader->GetOutput()->GetExtent(extent);
reader->GetOutput()->GetSpacing(spacing);
reader->GetOutput()->GetOrigin(origin);
center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);
center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);
center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);
double axialElements[16] = {
1, 0.2, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
vtkNew resliceAxes;
resliceAxes->DeepCopy(axialElements);
resliceAxes->SetElement(0, 3, center[0]);
resliceAxes->SetElement(1, 3, center[1]);
resliceAxes->SetElement(2, 3, center[2]);
vtkNew reslice;
reslice->SetInputConnection(reader->GetOutputPort());
reslice->SetOutputDimensionality(2);
reslice->SetResliceAxes(resliceAxes);
//reslice->SetInterpolationModeToNearestNeighbor();
//reslice->SetInterpolationModeToLinear();
reslice->SetInterpolationModeToCubic();
reslice->Update();
unsigned char* edit_ptr = reinterpret_cast(reslice->GetOutput()->GetScalarPointer());
int length = reslice->GetOutput()->GetScalarSize();
int out_dims[3] = { 0 };
reslice->GetOutput()->GetDimensions(out_dims);
length = out_dims[0] * out_dims[1];
set ids;
for (int i = 0; i < length; i++) {
ids.insert(edit_ptr[i]);
}
unsigned char* rgb_image_buf = new unsigned char[length * 3]{ 0 };
map> color_lookup_table;
color_lookup_table.insert(make_pair(0, std::make_tuple(0, 0, 0)));
color_lookup_table.insert(make_pair(2, std::make_tuple(0, 255, 255)));
color_lookup_table.insert(make_pair(5, std::make_tuple(18, 153, 255)));
color_lookup_table.insert(make_pair(17, std::make_tuple(105, 168, 227)));
color_lookup_table.insert(make_pair(27, std::make_tuple(230, 224, 17)));
color_lookup_table.insert(make_pair(28, std::make_tuple(36, 51, 135)));
color_lookup_table.insert(make_pair(38, std::make_tuple(255, 0, 0)));
color_lookup_table.insert(make_pair(43, std::make_tuple(0, 255, 0)));
color_lookup_table.insert(make_pair(44, std::make_tuple(34, 139, 34)));
color_lookup_table.insert(make_pair(49, std::make_tuple(50, 205, 50)));
color_lookup_table.insert(make_pair(63, std::make_tuple(0, 0, 255)));
for (int i = 0 ; i < length; i++) {
auto it = color_lookup_table.find(edit_ptr[i]);
if (it != color_lookup_table.end()) {
rgb_image_buf[i * 3 + 0] = get<0>(it->second);
rgb_image_buf[i * 3 + 1] = get<1>(it->second);
rgb_image_buf[i * 3 + 2] = get<2>(it->second);
}
else {
rgb_image_buf[i * 3 + 0] = edit_ptr[i];
rgb_image_buf[i * 3 + 1] = edit_ptr[i];
rgb_image_buf[i * 3 + 2] = edit_ptr[i];
}
}
cv::Mat image;
Buffer2Mat_123(rgb_image_buf, out_dims[0], out_dims[1], 8*3, image);
cv::imshow("Image", image);
cv::waitKey(0);
}
第一张图是SetInterpolationModeToNearestNeighbor的图像;
第二张和第三张分别是SetInterpolationModeToLinear、SetInterpolationModeToCubic生成的图像: