Hello,
I am writing code in C++ to do some mathematical operations on matrices that contain complex numbers. I am using vtk to accomplish this, primarily because the data I am working with needs to be resliced, resized, transformed with FFT, etc. The vtkImageReslice and other image-related classes work nicely for this.
One operation I am trying to perform on a vtkImageData object is exponentiation. In other words, I want to do exp(X) where X is a vtkImageData object. The image data consists of complex numbers which I have stored in two components in the vtkImageData object. vtkImageMathematics class has an exp() operation, but I don’t think it was designed to work with complex numbers. Is this correct? For complex numbers in the form z = x + iy, the complex exponential is defined as: e^z = e^x(cosy + isiny).
To accomplish this with vtkImageMathematics and other classes, the code looks kind of ugly. I must be doing something wrong. Is there a better way? Is vtk even the right tool to be using? This must be accomplished in C++, not Python. So numpy is not an option.
Thanks in advance,
Michelle
// filters for extracting real and imaginary components of complex image
vtkSmartPointer<vtkImageExtractComponents> extractRealFilter = vtkSmartPointer<vtkImageExtractComponents>::New();
extractRealFilter->SetComponents(0);
vtkSmartPointer<vtkImageExtractComponents> extractImaginaryFilter = vtkSmartPointer<vtkImageExtractComponents>::New();
extractImaginaryFilter->SetComponents(1);
// extract the real component from my complex numbers image
extractRealFilter->SetInputData(complexImage);
extractRealFilter->Update();
// e^x
vtkSmartPointer<vtkImageMathematics> exponentFilter = vtkSmartPointer<vtkImageMathematics>::New();
exponentFilter->SetOperationToExp();
exponentFilter->SetInput1Data(extractRealFilter->GetOutput());
exponentFilter->Update();
// extract the imaginary component from my complex number image
extractImaginaryFilter->SetInputData(complexImage);
extractImaginaryFilter->Update();
// cosy
vtkSmartPointer<vtkImageMathematics> cosFilter = vtkSmartPointer<vtkImageMathematics>::New();
cosFilter->SetOperationToCos();
cosFilter->SetInput1Data(extractImaginaryFilter->GetOutput());
cosFilter->Update();
// siny
vtkSmartPointer<vtkImageMathematics> sinFilter = vtkSmartPointer<vtkImageMathematics>::New();
sinFilter->SetOperationToSin();
sinFilter->SetInput1Data(extractImaginaryFilter->GetOutput());
sinFilter->Update();
// e^x * cosy
vtkSmartPointer<vtkImageMathematics> cosMultFilter = vtkSmartPointer<vtkImageMathematics>::New();
cosMultFilter->SetOperationToMultiply();
cosMultFilter->SetInput1Data(exponentFilter->GetOutput());
cosMultFilter->SetInput2Data(cosFilter->GetOutput());
cosMultFilter->Update();
// e^x * siny
vtkSmartPointer<vtkImageMathematics> sinMultFilter = vtkSmartPointer<vtkImageMathematics>::New();
sinMultFilter->SetOperationToMultiply();
sinMultFilter->SetInput1Data(exponentFilter->GetOutput());
sinMultFilter->SetInput2Data(sinFilter->GetOutput());
sinMultFilter->Update();
// fill a new vtkImageData object with the resulting real and imaginary components
vtkSmartPointer<vtkImageData> expImage = vtkSmartPointer<vtkImageData>::New();
expImage->SetSpacing(1, 1, 1);
expImage->SetExtent(0, complexImage->GetDimensions()[0] - 1, 0, complexImage->GetDimensions()[1] - 1, 0, 0);
expImage->AllocateScalars(VTK_DOUBLE, 2); // complex numbers, two components
for (int row = 0; row < complexImage->GetDimensions()[1]; row++)
{
for (int col = 0; col < complexImage->GetDimensions()[0]; col++)
{
double* realPix = static_cast<double*> (cosMultFilter->GetOutput()->GetScalarPointer(col, row, 0));
double* imaginaryPix = static_cast<double*> (sinMultFilter->GetOutput()->GetScalarPointer(col, row, 0));
double* complexExpPix = static_cast<double*> (expImage->GetScalarPointer(col, row, 0));
complexExpPix[0] = realPix[0];
complexExpPix[1] = imaginaryPix[0];
}
}