Esempio n. 1
0
        private static Complex2D DoScale(Complex2D channel, int dstWidth, int dstHeight)
        {
            var wFs = channel.Width;
            var hFs = channel.Height;

            var divX = dstWidth - wFs;
            var divY = dstHeight - hFs;

            Debug.Assert(divX != 0 || divY != 0, "No resize required.");
            var xOffset = divX / 2;
            var yOffset = divY / 2;
            var xEnd    = xOffset + wFs;
            var yEnd    = yOffset + hFs;

            if (divX < 0 ||
                divY < 0)
            {
                throw new Exception("New size is smaller than the input size");
            }

            var oldData = channel.Data;

            // TODO: correct zero padding -> FFT shifted??
            return(new Complex2D(
                       dstWidth,
                       dstHeight,
                       (i, j) => i >= xOffset && i < xEnd && j >= yOffset && j < yEnd
                    ? oldData[(i - xOffset) + ((j - yOffset) * wFs)]
                    : Zero
                       ));
        }
Esempio n. 2
0
        public void Apply(Complex2D c)
        {
            var key = $"{_width}x{_height}";

            double[] window;
            if (!_winCache.TryGetValue(key, out window))
            {
                var hWin = CreateWindow1D(_width);
                var vWin = _height == _width ? hWin : CreateWindow1D(_height);

                window = new double[_width * _height];
                for (int j = 0,
                     k = 0;
                     j < _height;
                     j++)
                {
                    var fy = vWin[j];
                    for (var i = 0; i < _width; i++, k++)
                    {
                        window[k] = fy * hWin[i];
                    }
                }

                _winCache.Add(key, window);
            }

            var d = c.Data;

            // elementwise multiply
            if (c.Width == _width)
            {
                //non zero padded?
                for (var i = 0; i < window.Length; i++)
                {
                    d[i] *= window[i];
                }

                return;
            }

            //zero padded
            var lf = c.Width - _width;

            for (int i = 0,
                 j = 0;
                 i < window.Length;
                 j += lf)
            {
                for (var iLe = i + _width; i < iLe; i++, j++)
                {
                    d[j] *= window[i];
                }
            }
        }
Esempio n. 3
0
        /// <summary>
        ///   Creates a deblur filter from three channel in frequency domain.
        /// </summary>
        /// <param name="c0Freqz">channel 0 in frequency domain</param>
        /// <param name="c1Freqz">channel 1 in frequency domain</param>
        /// <param name="c2Freqz">channel 2 in frequency domain</param>
        /// <param name="normalize">
        ///   if true, each pixel c_n with 0 &lt; n &lt; N-1 will be divided by 1/sum|c_n|, c_0 will be set
        ///   to 1+j0
        /// </param>
        /// <returns></returns>
        public static DeblurFilter CreateFromFrequencies(Complex2D c0Freqz,
                                                         Complex2D c1Freqz,
                                                         Complex2D c2Freqz,
                                                         bool normalize = false)
        {
            var w = MathCV.Max(c0Freqz.Width, c1Freqz.Width, c2Freqz.Width);
            var h = MathCV.Max(c0Freqz.Height, c1Freqz.Height, c2Freqz.Height);

            var result = new DeblurFilter {
                C0                                              = c0Freqz.Width != w || c0Freqz.Height != h?DoScale(c0Freqz, w, h) : new Complex2D(c0Freqz),
                                           C1                   = c1Freqz.Width != w || c1Freqz.Height != h?DoScale(c1Freqz, w, h) : new Complex2D(c1Freqz),
                                                             C2 = c2Freqz.Width != w || c2Freqz.Height != h?DoScale(c2Freqz, w, h) : new Complex2D(c2Freqz)
            };

            if (!normalize)
            {
                return(result);
            }

            var n     = w * h;
            var d0    = result.C0.Data;
            var d1    = result.C1.Data;
            var d2    = result.C2.Data;
            var norm0 = (n - 1) / (d0.SumAbs() - d0[0].Magnitude);
            var norm1 = (n - 1) / (d1.SumAbs() - d1[0].Magnitude);
            var norm2 = (n - 1) / (d2.SumAbs() - d2[0].Magnitude);

            d0[0] = d1[0] = d2[0] = Complex.One;
            for (var i = 1; i < n; i++)
            {
                d0[i] *= norm0;
                d1[i] *= norm1;
                d2[i] *= norm2;
            }

            return(result);
        }
Esempio n. 4
0
        public Complex2D[] Complex2DRoots()
        {
            double d = Math.Pow(B, 2) - 4 * A * C;

            return(new Complex2D[] { (Complex2D.Sqrt(Math.Pow(B, 2) - 4 * A * C) - B) / (2 * A), (-Complex2D.Sqrt(Math.Pow(B, 2) - 4 * A * C) - B) / (2 * A) });
        }