Copy vtkImageData to cv::Mat

末鹿安然 提交于 2020-01-02 06:00:31

问题


I am trying to copy a vtkImageData* class to a cv::Mat structure [my goal is to read an MHD file into OpenCV].. The file is essentially a 3D Matrix so I want to get a vector containing all the slices of the volume. So far, I have come up with this code,

reader->SetFileName(INPUT_DATA_1.c_str());
reader->Update();
imageData_1 = reader->GetOutput();
extractVOI->SetInput(imageData_1);

int dims[3];
imageData_1->GetDimensions(dims);
extractVOI->SetVOI(0, dims[0], 0, dims[1], 75, 75); // Set it to z=75
extractVOI->GetOutput()->SetScalarTypeToSignedChar();
imageExport->SetInputConnection(extractVOI->GetOutputPort());
imageExport->Update();

cv::Mat cvMat_test(dims[0], dims[1], CV_8UC1, imageExport->GetPointerToData());

Although this is working, it is not giving me the expected output (which are highlighted below).. Any help regarding this matter would be very helpful..

Thanks in advance, Sarthak

Expected output,

The output I am getting right now,

EDIT: I realize that the images aren't the same size. This is because I have just posted a snapshot of the data from the viewer that I am using.. There is an example in the dropbox link given HERE. Hope this clarifies things a bit more..

TAGS: vtk opencv bridge, vtkopencv, vtk opencv integrate


回答1:


Okay, so the GetPointerToData() function or GetScalarPointer() function used directly on the vtkImageData class are not appropriate for allocation (at least not in a way I could figure out).. So, I devised another method,

reader->SetFileName(INPUT_DATA_1.c_str());
reader->Update();
imageData_1 = reader->GetOutput();
extractVOI->SetInput(imageData_1);

int dims[3];
imageData_1->GetDimensions(dims);
extractVOI->SetVOI(0, dims[0], 0, dims[1], 75, 75); // Set it to z=75
extractVOI->GetOutput()->SetScalarTypeToSignedChar();
cv::Mat cvMat_test(dims[0], dims[1], CV_8UC1);

for (int i=0; i<dims[0]; ++i) {
    for (int j=0; j<dims[1]; ++j) {
        cvMat_test.at<unsigned char>(cv::Point(j,i)) = *static_cast<unsigned char*>(extractVOI->GetOutput()->GetScalarPointer(i,j,vol_dim));
    }
}

I am guessing this method can be extended to include the entire volume pretty easily..

EDIT:

I extended my code to do conversions to and from vtkImageData and cv::Mat and/or cv::gpu::Mat.. I have uploaded to the code here as vtkOpenCVBridge.

Cheers.!




回答2:


First, the images are not of the same size. Even if the data is not stored properly, at least width and height of the images should be the same. This means that dims[0] and dims[1] is not really height and width of the image.

Second, are you sure that the data in vtk image is stored as array of unsigned char? I got patterns similar to yours when I tried to store image of ints in image of unsigned chars.

Third, are you sure that your vtk image is continuous in memory (you are not providing step between following rows)?

I never worked with VTK library so my answer is just a guess...




回答3:


I have come across similar issue, after spending enormous time, I realized that I have swapped the dimensions, height to width and otherwise. Reinstating the dimensions correctly did give me a better result. I haven't worked with VTK library, but i think you can recheck the dimensions declarations.



来源:https://stackoverflow.com/questions/19891341/copy-vtkimagedata-to-cvmat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!