使用DFT进行OpenCV反卷积

时间:2014-09-18 10:52:05

标签: c# c++ opencv fft dft

我正在使用OpenCVSharp(OpenCV的C#包装)实现反卷积算法(用于DIC图像)。由于某些原因,在deltaPhiXY上使用Cv2.Dft算法(见下文)后,傅里叶变换的实部和虚部始终为零; deltaPhiXY始终在-pi / 2到pi / 2的范围内,如预期的那样(并且是必需的)。您是否有提示我无法在deltaPhiXY上计算DFT的原因?如果有人对数学理论感兴趣,那就是论文http://dare.uva.nl/document/2/3308

真的非常感谢任何帮助。

// deconvolve the frame
            int deltaX = Session.Params.ParamsPreprocessing.DeltaX;
            int deltaY = Session.Params.ParamsPreprocessing.DeltaY;
            float s = Session.Params.ParamsPreprocessing.S;
            float sigma = Session.Params.ParamsPreprocessing.Sigma;
            if (deltaX != 0 && deltaY != 0 && s != 0 && sigma != 0)
            {
                // initialize deconvolution variables
                MatOfDouble
                    deltaPhiXY = new MatOfDouble(frame.Size()),
                    realW = new MatOfDouble(frame.Size(), 0),
                    imgW = new MatOfDouble(frame.Size());

                frame.ConvertTo(frame, MatType.CV_64FC1);
                MatIndexer<double>
                    indexerFrame = (new MatOfDouble(frame)).GetIndexer(),
                    indexerDeltaPhiXY = deltaPhiXY.GetIndexer(),
                    indexerImgW = imgW.GetIndexer();

                double
                    IMax,
                    IMin;
                frame.MinMaxIdx(out IMin, out IMax);

                double
                    phi = 0,
                    G = 0,
                    SN = 0,
                    w = 0;

                // build deltaPhi (in x, y) and W (in u, v)
                for(int row = 0; row < frame.Rows; row++)
                {
                    for(int col = 0; col < frame.Cols; col++)
                    {
                        // set deltaPhi
                        phi =
                       Math.Acos
                        (
                            (2 * (indexerFrame[row, col] - IMin)
                            /
                            (IMax - IMin))
                            - 1
                        )
                        - Math.PI / 2;

                        indexerDeltaPhiXY[row, col] =
                            phi;


                        // set complex G in u, v
                        G = 
                            2*Math.Sin(Math.PI * (row * deltaX + col * deltaY));

                        // set SN in u, v (spectral distribution of the signal to noise ratio)
                        SN = 
                            s * Math.Exp(-2 * Math.PI * Math.PI * sigma * sigma * (row * row + col * col));

                        // set W in u, v
                        w = 
                            -G / (G * G + (1 / SN));

                        indexerImgW[row, col] =
                            w;

                    }
                }

                // build deltaPhi
                Mat deltaPhi = new Mat();
                Cv2.Dft(deltaPhiXY, deltaPhi, DftFlag2.Scale | DftFlag2.ComplexOutput); // here I had used other flags but the final result is always 0
                // Cv2.Merge(new Mat[] { deltaPhiXY, new Mat(deltaPhiXY.Size(), MatType.CV_64FC1, Scalar.All(0)) }, deltaPhi);
                // deltaPhi = deltaPhi.Dft();
                Mat[] planesDeltaPhi = deltaPhi.Split();
                Mat realDeltaPhi = planesDeltaPhi[0];
                Mat imgDeltaPhi = planesDeltaPhi[1];

                // get phi = W*deltaPhi (deconvolution)
                Mat
                    realPhi = -imgW.Mul(imgDeltaPhi),
                    imgPhi = imgW.Mul(realDeltaPhi);

                // get deconvolved frame (inverse Fourier's transform)
                Cv2.Merge(new Mat[] { realPhi, imgPhi }, frame);
                frame = frame.Dft(DftFlag2.Inverse | DftFlag2.RealOutput);
                frame = frame.Normalize(IMin, IMax, NormType.MinMax, MatType.CV_32FC1);

}

1 个答案:

答案 0 :(得分:0)

固定,    出于某种原因,有必要在Mat变量(至少对于上面的代码)上进行DFT(和IDFT)之前使用此片段:

          double
                min,
                max;

                toTransform.MinMaxIdx(out min, out max);
                toTransform = toTransform.Normalize(0, int.MaxValue, NormType.MinMax, MatType.CV_32SC1);
                toTransform = toTransform.Normalize(min, max, NormType.MinMax, MatType.CV_64FC1);

我不知道问题是否与我的Mat变量或OpenCV库中的值有关,但这种解决方法在我的情况下是起作用的(至少)。