簡體   English   中英

如何將cv :: Mat轉換為vtkImageData?

[英]How to convert cv::Mat to vtkImageData?

如何在C ++中有效地從cv::Mat轉換為vtkImageData 我搜索適用於BW和COLOR圖像的方法。

vtkSmartPointer<vtkImageData> OpenCVToVtkConverter::convertCVMatToVtkImageData(const cv::Mat &sourceCVImage, bool flipOverXAxis) {
  vtkSmartPointer<vtkImageData> outputVtkImage = vtkSmartPointer<vtkImageData>::New();
  double spacing[3] = {1, 1, 1};
  double origin[3] = {0, 0, 0};
  int extent[6] = {0, sourceCVImage.cols - 1, 0, sourceCVImage.rows - 1, 0, 0};
  auto numOfChannels = sourceCVImage.channels();
  outputVtkImage->SetSpacing(spacing);
  outputVtkImage->SetOrigin(origin);
  outputVtkImage->SetExtent(extent);
  outputVtkImage->SetDimensions(sourceCVImage.cols, sourceCVImage.rows, 1);
  outputVtkImage->AllocateScalars(VTK_UNSIGNED_CHAR, numOfChannels);

  cv::Mat tempCVImage;
  if(flipOverXAxis){ // Normaly you should flip the image!
    cv::flip(sourceCVImage, tempCVImage, 0);
  }
  else {
    tempCVImage = sourceCVImage;
  }
  for (int imgHeightPos = 0; imgHeightPos < sourceCVImage.rows; ++imgHeightPos) {
    for (int imgWidthPos = 0; imgWidthPos < sourceCVImage.cols; ++imgWidthPos){
      switch(numOfChannels){
        case 1:{
          auto pixel = tempCVImage.at<unsigned char>(imgHeightPos, imgWidthPos);
          outputVtkImage->SetScalarComponentFromDouble(imgWidthPos, imgHeightPos, 0, 0, pixel); //red
          break;
        }
        case 3: {
          auto pixel2 = tempCVImage.at<cv::Vec3b>(imgHeightPos, imgWidthPos);
          outputVtkImage->SetScalarComponentFromDouble(imgWidthPos, imgHeightPos, 0, 0, pixel2[2]); //red
          outputVtkImage->SetScalarComponentFromDouble(imgWidthPos, imgHeightPos, 0, 1, pixel2[1]); //green
          outputVtkImage->SetScalarComponentFromDouble(imgWidthPos, imgHeightPos, 0, 2, pixel2[0]); //blue
          break;
        }
        case 4:{
          auto pixel3 = tempCVImage.at<cv::Vec4b>(imgHeightPos, imgWidthPos);
          outputVtkImage->SetScalarComponentFromDouble(imgWidthPos, imgHeightPos, 0, 0, pixel3[2]); //red
          outputVtkImage->SetScalarComponentFromDouble(imgWidthPos, imgHeightPos, 0, 1, pixel3[1]); //green
          outputVtkImage->SetScalarComponentFromDouble(imgWidthPos, imgHeightPos, 0, 2, pixel3[0]); //blue
          outputVtkImage->SetScalarComponentFromDouble(imgWidthPos, imgHeightPos, 0, 3, pixel3[3]); //alpha
          break;
        }
        default:
          std::cout << "unknown number of channels" << std::endl;
      }
    }
  }
  outputVtkImage->Modified();
  return outputVtkImage;
}

以下是@lucasahli上面答案的簡化版本。 它使用高效的memcpy而不是double for循環。

注意 :對於彩色圖像,您可能需要將圖像通道從bgr翻轉到rgb排序,我使用mixChannels來實現。

vtkSmartPointer<vtkImageData> OpenCVToVtkConverter::convertCVMatToVtkImageData(const cv::Mat &sourceCVImage, bool flipOverXAxis) {
  vtkSmartPointer<vtkImageData> outputVtkImage = vtkSmartPointer<vtkImageData>::New();

  int numOfChannels = sourceCVImage.channels();

  // dimension set to 1 for z since it's 2D
  outputVtkImage->SetDimensions(sourceCVImage.cols, sourceCVImage.rows, 1);

  // NOTE: if your image isn't uchar for some reason you'll need to change this type
  outputVtkImage->AllocateScalars(VTK_UNSIGNED_CHAR, numOfChannels);

  // the flipped image data gets put into tempCVImage
  cv::Mat tempCVImage;
  if(flipOverXAxis){ // Normally you should flip the image!
    cv::flip(sourceCVImage, tempCVImage, 0);
  }
  else {
    tempCVImage = sourceCVImage;
  }

  // the number of byes in the cv::Mat, assuming the data type is uchar
  size_t byte_count = sourceCVImage.cols * sourceCVImage.rows * numOfChannels * sizeof(unsigned char);

  // copy the internal cv::Mat data into the vtkImageData pointer
  memcpy(outputVtkImage->GetScalarPointer(), tempCVImage.data, byte_count);

  outputVtkImage->Modified();
  return outputVtkImage;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM