diff --git a/Modules/PhotoacousticArtifacts/src/Algorithms/mitkPhotoacousticArtifact.cpp b/Modules/PhotoacousticArtifacts/src/Algorithms/mitkPhotoacousticArtifact.cpp index 8316022b69..7e3024dd9a 100644 --- a/Modules/PhotoacousticArtifacts/src/Algorithms/mitkPhotoacousticArtifact.cpp +++ b/Modules/PhotoacousticArtifacts/src/Algorithms/mitkPhotoacousticArtifact.cpp @@ -1,224 +1,223 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include // Methode soll von einem eingeladenen 2D mitkImage die Hauptkomponenten berechnen, und die gewünschte // Anzahl (1..n) zum Entrauschen abziehen. Mathematisch wird dabei die angegebene Anzahl der ersten // Singulärwerte Null gesetzt und dann wierder zurückgerechnet. template -static void SVDFilter2D(mitk::Image::Pointer inputImage, int svdNumber, mitk::Image::Pointer outputImage) +static void SVDFilter2D(mitk::Image::Pointer inputImage, int svdNumber, mitk::Image::Pointer outputImage) // svdNumber = numberOfZeroSVCs { //Step 1: inputImage in matrix m überführen, danach transponieren unsigned int* dimensions = inputImage->GetDimensions(); //0=x, 1=y unsigned int numberOfColums = dimensions[0]; unsigned int numberOfRows = dimensions[1]; //unsigned int zDimImmer1 = dimensions[2]; Eigen::MatrixXd m(numberOfRows, numberOfColums); mitk::ImageReadAccessor readAccessor(inputImage, inputImage->GetVolumeData()); const TPixel* data = (const TPixel*)readAccessor.GetData(); for (unsigned int i = 0; i < numberOfColums; ++i) { for (unsigned int j = 0; j < numberOfRows; ++j) { m(j, i) = (double)data[i*numberOfRows + j]; } } //m.transpose(); //Step 2: eigenvectoren der thin Matrix U berechnen & die singularValues // Compute Thin U, singularValues S and V // Set desired number of components, which should be removed/substracted to zero -> (weight are zeroed for denoising) // multiply all members (A=U*S*V(transpose)) back together again Eigen::JacobiSVD svdSolver(m.transpose(), Eigen::ComputeThinU | Eigen::ComputeThinV); Eigen::MatrixXd matrixU = svdSolver.matrixU(); //MITK_INFO << endl << "Matrix U: " << endl << matrixU << endl; Eigen::MatrixXd singularValues = svdSolver.singularValues(); // singularValues to matrix (m x m), if m < n // TODO: Fallunterscheidung: if (m > n) : SValues n x n; if (m < n) : SValues m x m !!!!!!!!!!!!!!!!!!!!!!!!!!! // TODO: optimierung mit sparse matrix eigen + // transponieren Eigen::MatrixXd singularValuesInMatrix = Eigen::MatrixXd::Zero(numberOfColums, numberOfColums); auto SVdata = singularValues.data(); - for (unsigned int i = 0; i < numberOfColums; ++i) + for (unsigned int i = svdNumber; i < numberOfColums; ++i) // i = numberOfZeroSVCs { singularValuesInMatrix(i, i) = (double)SVdata[i]; } //MITK_INFO << endl << "Singulaerwerte: " << endl << singularValuesInMatrix << endl; Eigen::MatrixXd matrixV = svdSolver.matrixV(); //MITK_INFO << endl << "Matrix V: " << endl << matrixV << endl; - //singularValuesInMatrix(0, 0) = 0.0; - //MITK_INFO << endl << "Reduzierte Singulaerwerte: " << endl << singularValuesInMatrix << endl; - Eigen::MatrixXd denoisedMatrix = matrixU*singularValuesInMatrix*matrixV.transpose(); denoisedMatrix.transposeInPlace(); //MITK_INFO << endl << "Denoised Matrix: " << endl << denoisedMatrix << endl; //Step 3: denoisedMatrix in outputImage überführen unsigned int* dimOutputImage = new unsigned int[3]; dimOutputImage[0] = dimensions[0]; dimOutputImage[1] = dimensions[1]; dimOutputImage[2] = dimensions[2]; mitk::PixelType pixelType = mitk::MakeScalarPixelType(); outputImage->Initialize(pixelType, 3, dimOutputImage); outputImage->SetSpacing(inputImage->GetGeometry()->GetSpacing()); if (numberOfColums > numberOfRows) // not sure if this checks are necessary { for (unsigned int i = 0; i < numberOfRows; ++i) { outputImage->SetImportVolume(denoisedMatrix.col(i).data(), i); } } else { for (unsigned int i = 0; i < numberOfColums; ++i) { outputImage->SetImportVolume(denoisedMatrix.col(i).data(), i); } } } // TODO: step 1 in eigene klasse extrahieren // TODO: fertige matrix übergeben, die zuvor aus einem bild überführt wurde // Methode bekommt zuvor angepasste Matrix als input, es wird die ThinU Matrix berechnet und // die Hauptkomponenten/Eigenvektoren werden zurück zum Bild konvertiert template static void ComputeThinU(mitk::Image::Pointer inputImage, int svdNumber, mitk::Image::Pointer outputImage) { //Step 1: inputImage in matrix m überführen unsigned int* dimensions = inputImage->GetDimensions(); //0=x, 1=y, 2=z unsigned int numberOfSlices = dimensions[2]; unsigned int vectorLength = dimensions[0] * dimensions[1]; Eigen::MatrixXd m(vectorLength, numberOfSlices); for (unsigned int i = 0; i < numberOfSlices; ++i) { mitk::ImageReadAccessor readAccessor(inputImage, inputImage->GetSliceData(i)); const TPixel* data = (const TPixel*)readAccessor.GetData(); for (unsigned int j = 0; j < vectorLength; ++j) { m(j, i) = (double)data[j]; } } //Step 2: eigenvectoren der thin Matrix U berechnen & die singularValues Eigen::JacobiSVD svdSolver(m, Eigen::ComputeThinU); Eigen::MatrixXd matrixU = svdSolver.matrixU(); //MITK_INFO << endl << "Matrix U: " << endl << matrixU << endl; //if (numberOfSlices > vectorLength) //{ // for (unsigned int i = 0; i < vectorLength; ++i) // { // MITK_INFO << endl << "Eigenvector " << i + 1 << ": " << endl << matrixU.col(i) << endl; // } //} //else { // for (unsigned int i = 0; i < numberOfSlices; ++i) // { // MITK_INFO << endl << "Eigenvector " << i + 1 << ": " << endl << matrixU.col(i) << endl; // } //} //MITK_INFO << endl << "Singulaerwerte: " << endl << svdSolver.singularValues() << endl; //Step 3: eigenvectors in outputImage überführen unsigned int* dimOutputImage = new unsigned int[3]; dimOutputImage[0] = dimensions[0]; dimOutputImage[1] = dimensions[1]; if (numberOfSlices > vectorLength) { dimOutputImage[2] = vectorLength; } else { dimOutputImage[2] = numberOfSlices; } mitk::PixelType pixelType = mitk::MakeScalarPixelType(); outputImage->Initialize(pixelType, 3, dimOutputImage); outputImage->SetSpacing(inputImage->GetGeometry()->GetSpacing()); if (numberOfSlices > vectorLength) { for (unsigned int i = 0; i < vectorLength; ++i) { outputImage->SetImportSlice(matrixU.col(i).data(), i); } } else { for (unsigned int i = 0; i < numberOfSlices; ++i) { outputImage->SetImportSlice(matrixU.col(i).data(), i); } } } mitk::PhotoacousticArtifact::PhotoacousticArtifact() : m_SVD(1) { this->SetPrimaryOutput(mitk::Image::New()); MITK_INFO << "Hello."; this->SetNumberOfRequiredInputs(1); this->SetNumberOfRequiredOutputs(1); } mitk::PhotoacousticArtifact::~PhotoacousticArtifact() { } void mitk::PhotoacousticArtifact::GenerateData() { mitk::Image::Pointer inputImage = this->GetInput(0); mitk::Image::Pointer outputImage = this->GetOutput(); + // TODO: switch case für jeden type //convert input from short/float to double type - //typedef itk::Image ShortImageType; - //typedef itk::Image DoubleImageType; - - //typedef itk::CastImageFilter CastFilterType; - //CastFilterType::Pointer castFilter = CastFilterType::New(); - //mitk::ImageToItk::Pointer filter = mitk::ImageToItk::New(); - //filter->SetInput(inputImage); - //filter->Update(); - //castFilter->SetInput(filter->GetOutput()); - //castFilter->Update(); - - //mitk::Image::Pointer newInputImage = mitk::Image::New(); - //auto castImage = castFilter->GetOutput(); - //newInputImage->InitializeByItk(castImage); - //newInputImage->SetVolume(castImage->GetBufferPointer()); + typedef itk::Image WhatEverImageType; + typedef itk::Image DoubleImageType; + + typedef itk::CastImageFilter CastFilterType; + CastFilterType::Pointer castFilter = CastFilterType::New(); + mitk::ImageToItk::Pointer filter = mitk::ImageToItk::New(); + filter->SetInput(inputImage); + filter->Update(); + castFilter->SetInput(filter->GetOutput()); + castFilter->Update(); + + mitk::Image::Pointer newInputImage = mitk::Image::New(); + auto castImage = castFilter->GetOutput(); + newInputImage->InitializeByItk(castImage); + newInputImage->SetVolume(castImage->GetBufferPointer()); // 3D thing //ComputeThinU(newInputImage, 1, outputImage); // 2D thing - SVDFilter2D(inputImage, 1, outputImage); + SVDFilter2D(newInputImage, 20, outputImage); }