void PyramidDenoiser::DenoiseLevelBivariate(int level) { if (level < (int)(mpPyramid->GetNumberOfScales() - 1)) { PyramidLevel<double>* pBandSetCurrent; PyramidLevel<double>* pBandSetParent; if (level != -1) { pBandSetCurrent = mpPyramid->GetRecursiveScale(level); pBandSetParent = mpPyramid->GetRecursiveScale(level+1); } else { pBandSetCurrent = mpPyramid->GetResidualScale(); pBandSetParent = mpPyramid->GetRecursiveScale(0); } double avgVariance = 0.0; double scaleNoiseVariance = mSigmaNoise / GetScaledNoiseVarianceFactor( level ); double scaleParentChildFactor = GetScaledParentChildFactor( level); for (int orientationIndex = 0; orientationIndex < pBandSetCurrent->GetNumberOfOrientations(); orientationIndex++) { ArrayGrid<double>* pBandCurrent = pBandSetCurrent->GetOrientedBand( orientationIndex); ArrayGrid<double>* pBandParent = pBandSetParent->GetOrientedBand( orientationIndex); double meanVal = GridStatistics<double>::GetGridMean( pBandCurrent ); double varianceVal = GridStatistics<double>::GetGridVariance( pBandCurrent, meanVal ); #ifdef DEBUG cout << "Denoising level " << level << " and orientationIndex " << orientationIndex << ", variance is " << varianceVal << " and scaled noise variance = " << scaleNoiseVariance << endl << flush; #endif avgVariance += varianceVal; for (int y = 0; y < pBandCurrent->GetHeight(); y++) { for (int x = 0; x < pBandCurrent->GetWidth(); x++) { double sigmaSignal = EstimateSigmaSignal( pBandCurrent, x, y, mSigmaNoise, mWindowSize ); double w1 = pBandCurrent->GetValue(x,y); double w2 = pBandParent->GetValue(x/2,y/2) / scaleParentChildFactor; double shrinkageFactor = ComputeBivariateShrinkagefactor(w1, w2, sigmaSignal, scaleNoiseVariance ); pBandCurrent->SetValue(x,y, shrinkageFactor * w1); } } } #ifdef DEBUG cout << "Average variance at scale level = " << (avgVariance) / (double)(pBandSetCurrent->GetNumberOfOrientations()) << endl << flush; #endif } else { std::cerr << "PyramidDenoiser::DenoiseLevelBivariate: Cannot denoise level " << level << " since top level is " << mpPyramid->GetNumberOfScales() << std::endl << std::flush; } }
void PyramidDenoiser::DenoiseLevelLaplacian(int level) { if (level < (int)(mpPyramid->GetNumberOfScales() - 1)) { PyramidLevel<double>* pBandSet; if (level != -1) { pBandSet = mpPyramid->GetRecursiveScale(level); } else { pBandSet = mpPyramid->GetResidualScale(); } for (int orientationIndex = 0; orientationIndex < pBandSet->GetNumberOfOrientations(); orientationIndex++) { ArrayGrid<double>* pBand = pBandSet->GetOrientedBand( orientationIndex); for (int y = 0; y < pBand->GetHeight(); y++) { for (int x = 0; x < pBand->GetWidth(); x++) { double sigmaSignal = EstimateSigmaSignal( pBand, x, y, mSigmaNoise, mWindowSize ); double w1 = pBand->GetValue(x,y); double shrinkageFactor = ComputeLaplacianShrinkagefactor(w1, sigmaSignal, mSigmaNoise); mpPyramid->GetRecursiveScale( level)->GetOrientedBand( orientationIndex)->SetValue(x,y, shrinkageFactor * w1); } } } } else { std::cerr << "PyramidDenoiser::DenoiseLevelLaplacian: Cannot denoise level " << level << " since top level is " << mpPyramid->GetNumberOfScales() << std::endl << std::flush; } }
ArrayGrid<double>* WienerDeconvolve::RunSingleband( ArrayGrid<double>* pInGrid, ArrayGrid<double>* pInPSF, double noiseLevel ) { int width = pInGrid->GetWidth(); int height = pInGrid->GetHeight(); FFTBand* pFFTInputGrid = new FFTBand( pInGrid ); FFTBand* pFFTPSFGrid = new FFTBand( pInPSF ); FFTBand* pWienerOut = new FFTBand( pInGrid ); pFFTInputGrid->ApplyForwardTransform(); pFFTPSFGrid->ApplyForwardTransform(); ArrayGrid<double>* pEstimatedIdealSpectrum = EstimateIdealSpectrum( pFFTInputGrid, pFFTPSFGrid, noiseLevel ); double fourierNoiseLevel = width * height * noiseLevel * noiseLevel; pFFTPSFGrid->Conjugate(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { complex<double> wienerEstimate = ( ( pFFTPSFGrid->GetValue(x, y) * pFFTInputGrid->GetValue(x, y) ) / ( POWER2( abs( pFFTPSFGrid->GetValue( x, y ) ) ) + ( fourierNoiseLevel / pEstimatedIdealSpectrum->GetValue(x, y) ) ) ); wienerEstimate /= (width * height); pWienerOut->SetValue( x, y, wienerEstimate ); } } pWienerOut->ApplyInverseTransform(); ArrayGrid<double>* pRestoredGrid = pWienerOut->ConvertToRealGrid(); delete pEstimatedIdealSpectrum; delete pFFTInputGrid; delete pFFTPSFGrid; delete pWienerOut; return pRestoredGrid; }
Image* AnisotropicDiffusion::Run() { for (int bandNr = 0; bandNr < mpSourceImage->GetNumberOfBands(); bandNr++) { cout << "Processing band nr " << bandNr << endl << flush; for (int iterationNr = 0; iterationNr < mMaxNumberOfIterations; iterationNr++) { cout << "\t\t iteration nr " << iterationNr << flush; ArrayGrid<double>* pPreviousIterationGrid = mpSourceImage->GetBands()[bandNr]->Clone(); double flowConstant = DetermineMeanGradient( pPreviousIterationGrid ) * mFlowFactor; cout << "\t\t FlowConstant = " << flowConstant << endl << flush; for (int y = 1; y < mpSourceImage->GetHeight()-1; y++) { for (int x=1; x < mpSourceImage->GetWidth()-1 ; x++) { double deltaIxu, deltaIxl, deltaIyu, deltaIyl; double cxu, cxl, cyu, cyl, deltaI, ttmp; deltaIxu = pPreviousIterationGrid->GetValue(x+1, y) - pPreviousIterationGrid->GetValue(x, y); deltaIxl = pPreviousIterationGrid->GetValue(x, y) - pPreviousIterationGrid->GetValue(x-1, y); deltaIyu = pPreviousIterationGrid->GetValue(x, y+1) - pPreviousIterationGrid->GetValue(x, y); deltaIyl = pPreviousIterationGrid->GetValue(x, y) - pPreviousIterationGrid->GetValue(x, y-1); cxu = 1.0 / (1.0 + pow( ( abs( deltaIxu) / flowConstant ), (1.8) ) ); cxl = 1.0 / (1.0 + pow( ( abs( deltaIxl) / flowConstant ), (1.8) ) ); cyu = 1.0 / (1.0 + pow( ( abs( deltaIyu) / flowConstant ), (1.8) ) ); cyl = 1.0 / (1.0 + pow( ( abs( deltaIyl) / flowConstant ), (1.8) ) ); deltaI= (cxu*deltaIxu-cxl*deltaIxl)+(cyu*deltaIyu-cyl*deltaIyl); ttmp = pPreviousIterationGrid->GetValue(x,y) + mDeltaT * deltaI; mpSourceImage->GetBands()[bandNr]->SetValue(x,y,ttmp); } //for x }//for y delete pPreviousIterationGrid; } //for iterationNr } // for bandNr return mpSourceImage; }
bool CriticallySubsampledTransform::Reconstruct( double threshold ) { ArrayGrid<double>* pRecursiveInput = mpPyramid->GetLowpassResidual( ); for ( mCurrentScale = mNrScales-1; mCurrentScale >= 0; mCurrentScale-- ) { int width = pRecursiveInput->GetWidth(); int height = pRecursiveInput->GetHeight(); int upScaledWidth = width * 2; int upScaledHeight = height * 2; bool needsInitialisation = true; double initialValue = 0.0; ArrayGrid<double>* pLLGrid = new ArrayGrid<double>( upScaledWidth, upScaledHeight, needsInitialisation, initialValue ); for (int y = 0; y < upScaledHeight; y+=2) { for (int x = 0; x < upScaledWidth; x+=2) { int halfX = x/2; int halfY = y/2; double x00 = pRecursiveInput->GetValue( halfX, halfY ); double x01 = mpPyramid->GetRecursiveScale( mCurrentScale )->GetOrientedBand( 0 )->GetValue( halfX, halfY ); double x10 = mpPyramid->GetRecursiveScale( mCurrentScale )->GetOrientedBand( 1 )->GetValue( halfX, halfY ); double x11 = mpPyramid->GetRecursiveScale( mCurrentScale )->GetOrientedBand( 2 )->GetValue( halfX, halfY ); pLLGrid->SetValue( x , y , (x00 + x01 + x10 + x11) / 2.0 ); pLLGrid->SetValue( x , y+1, (x00 + x01 - x10 - x11) / 2.0 ); pLLGrid->SetValue( x+1, y , (x00 - x01 + x10 - x11) / 2.0 ); pLLGrid->SetValue( x+1, y+1, (x00 - x01 - x10 + x11) / 2.0 ); } } pRecursiveInput = pLLGrid->Clone(); delete pLLGrid; } mpDecomposeReconstructGrid = pRecursiveInput; return true; }
ArrayGrid<bool>* StegerLineDetector::Run( ArrayGrid<double>* pGridIn, double sigmaSmooth, double lowerThreshold, double higherThreshold, bool isModeLight ) { int width = pGridIn->GetWidth(); int height = pGridIn->GetHeight(); OrientationGrid* pOrientationGrid = new OrientationGrid(width, height); // NOT initialized at construction; values are set below ArrayGrid<bool>* pLineGrid = new ArrayGrid<bool>(width, height); // NOT initialized at construction; values are set below pLineGrid->SetGridValues( false ); ArrayGrid<double>* pGx = GaussConvolve::DerivativeConvolveFFT( pGridIn, sigmaSmooth, sigmaSmooth, GaussConvolve::DERIVATIVE_X ); ArrayGrid<double>* pGy = GaussConvolve::DerivativeConvolveFFT( pGridIn, sigmaSmooth, sigmaSmooth, GaussConvolve::DERIVATIVE_Y ); ArrayGrid<double>* pGxx = GaussConvolve::DerivativeConvolveFFT( pGridIn, sigmaSmooth, sigmaSmooth, GaussConvolve::DERIVATIVE_XX ); ArrayGrid<double>* pGyy = GaussConvolve::DerivativeConvolveFFT( pGridIn, sigmaSmooth, sigmaSmooth, GaussConvolve::DERIVATIVE_YY ); ArrayGrid<double>* pGxy = GaussConvolve::DerivativeConvolveFFT( pGridIn, sigmaSmooth, sigmaSmooth, GaussConvolve::DERIVATIVE_XY ); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { double eigenValue1, eigenValue2, eigenValue; common::Point<double> eigenVector1; common::Point<double> eigenVector2; EigenValueComputation( pGxx->GetValue(x, y), pGyy->GetValue(x, y), pGxy->GetValue(x, y), eigenValue1, eigenValue2, eigenVector1, eigenVector2); if (isModeLight == true) { eigenValue = -eigenValue1; } else { eigenValue = eigenValue1; } if (eigenValue > 0.0) { double n1 = eigenVector1.x; double n2 = eigenVector1.y; double a = pGxx->GetValue(x, y) * n1 * n1 + 2.0 * pGxy->GetValue(x, y) * n1 * n2 + pGyy->GetValue(x, y) * n2 * n2; double b = pGx->GetValue(x, y) * n1 + pGy->GetValue(x, y) * n2; double linearSolution; if ( MathUtils::SolveLinearEquation( a, b, linearSolution ) == true ) { double p1 = linearSolution * n1; double p2 = linearSolution * n2; if ((fabs (p1) <= EDGE_THRESHOLD) && (fabs (p2) <= EDGE_THRESHOLD)) { int xx = (int)(x + p1 + 0.5); int yy = (int)(y + p2 + 0.5); if ( (xx >= 0) && (xx < width) && (yy >=0) && (yy < height)) { if (eigenValue >= lowerThreshold) { if (eigenValue >= higherThreshold) { pLineGrid->SetValue(xx, yy, true); } } else { pLineGrid->SetValue(xx, yy, false); } } } } pOrientationGrid->SetAngle( x, y, MathUtils::ComputeArgument( eigenVector1.x, eigenVector1.y ) ); pOrientationGrid->SetMagnitude( x, y, eigenValue1); } } } //pOrientationGrid->ExportMagnitudeImage( string("StegerMagnitude.pgm") ); //pOrientationGrid->ExportOrientationImage( string("StegerOrientation.pgm"), -100000.0 ); delete pGx; delete pGy; delete pGxx; delete pGyy; delete pGxy; delete pOrientationGrid; return pLineGrid; }
bool CriticallySubsampledTransform::Decompose( image::ArrayGrid<double>* pSourceGrid, int nrScales ) { Initialize( pSourceGrid, nrScales ); ArrayGrid<double>* pRecursiveInput = pSourceGrid; for ( mCurrentScale = 0; mCurrentScale < mNrScales; mCurrentScale++) { int width = pRecursiveInput->GetWidth(); int height = pRecursiveInput->GetHeight(); int downScaledWidth = width / 2; int downScaledHeight = height / 2; bool needsInitialisation = true; double initialValue = 0.0; ArrayGrid<double>* pLLGrid = new ArrayGrid<double>( downScaledWidth, downScaledHeight, needsInitialisation, initialValue ); ArrayGrid<double>* pLHGrid = new ArrayGrid<double>( downScaledWidth, downScaledHeight, needsInitialisation, initialValue ); ArrayGrid<double>* pHLGrid = new ArrayGrid<double>( downScaledWidth, downScaledHeight, needsInitialisation, initialValue ); ArrayGrid<double>* pHHGrid = new ArrayGrid<double>( downScaledWidth, downScaledHeight, needsInitialisation, initialValue ); // to be sure that (x+1) and (y+1) won't exceed width and height int limitWidth = (width / 2 ) * 2; int limitHeight = (height / 2 ) * 2; #ifdef DEBUG cout << "Width = " << width << ", height = " << height << endl << flush; cout << "limitWidth = " << limitWidth << ", limitHeight = " << limitHeight << endl << flush; #endif for (int y = 0; y < limitHeight; y+=2) { for (int x = 0; x < limitWidth; x+=2) { int halfX = x/2; int halfY = y/2; #ifdef DEBUG //cout << "Width = " << width << ", height = " << height << endl << flush; if ((x+1) > width) {cout << (x+1) << " goes out of bounds." << endl << flush;} if ((y+1) > height) {cout << (y+1) << " goes out of bounds." << endl << flush;} assert ((x+1) < width); assert ((y+1) < height); #endif double x00 = pRecursiveInput->GetValue( x, y ); double x01 = pRecursiveInput->GetValue( x, y+1 ); double x10 = pRecursiveInput->GetValue( x+1, y ); double x11 = pRecursiveInput->GetValue( x+1, y+1 ); pLLGrid->SetValue( halfX, halfY, ( (x00 + x01 + x10 + x11) / 2.0) ); pLHGrid->SetValue( halfX, halfY, ( (x00 + x01 - x10 - x11) / 2.0) ); pHLGrid->SetValue( halfX, halfY, ( (x00 - x01 + x10 - x11) / 2.0) ); pHHGrid->SetValue( halfX, halfY, ( (x00 - x01 - x10 + x11) / 2.0) ); } } mpPyramid->GetRecursiveScale( mCurrentScale )->AddOrientedBand( pLHGrid ); // in on index 0 mpPyramid->GetRecursiveScale( mCurrentScale )->AddOrientedBand( pHLGrid ); // in on index 1 mpPyramid->GetRecursiveScale( mCurrentScale )->AddOrientedBand( pHHGrid ); // in on index 2 mpPyramid->SetLowpassResidual( pLLGrid ); pRecursiveInput = mpPyramid->GetLowpassResidual( ); } return true; }