VTK example--use vtkNIFTIImageReader to read unsigned char nii.gz file and use vtkImageReslice to display RGB

Function

        Perform MPR operation on the mask data, obtain the sliced ​​image, and convert it to an RGB image, and use OpenCV to display it;

Involved function points:

        1. Use the vtkNIFTIImageReader class to read the nii.gz file;

        2. Use the vtkImageReslice class to obtain sliced ​​images;

        3. Convert the two-dimensional unsigned char array to cv::Mat;

        How to use the vtkImageReslice class to obtain sliced ​​images, refer to notes:

VTK Notes-Calculation of MPR slices-vtkImageReslice class , and then perform coronal, sagittal, and oblique image reconstruction at any angle on the tissue designated by the reconstruction line marked by some reticle. Advantages of MPR 1. New tomographic images can be generated arbitrarily without repeated scanning; 2. The density value of the original image is faithfully maintained on the resulting image. 3. Surface reconstruction can display the full length of a curved object in one image. Disadvantages of MPR 1. It is difficult to express complex spatial structures; 2. Surface reorganization is easy to cause false positives;... https://blog.csdn.net/liushao1031177/article/details/118946205 The detailed code is as follows:

// 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<vtkNIFTIImageReader> 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<vtkMatrix4x4> resliceAxes;
    resliceAxes->DeepCopy(axialElements);
    resliceAxes->SetElement(0, 3, center[0]);
    resliceAxes->SetElement(1, 3, center[1]);
    resliceAxes->SetElement(2, 3, center[2]);

    vtkNew<vtkImageReslice> 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<unsigned char*>(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<unsigned char> 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<unsigned char, std::tuple<unsigned char, unsigned char, unsigned char>> 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);
}

The first picture is the image of SetInterpolationModeToNearestNeighbor;

The second and third are the images generated by SetInterpolationModeToLinear and SetInterpolationModeToCubic respectively:

Guess you like

Origin blog.csdn.net/liushao1031177/article/details/124847587