Example #1
0
        public void InverseT(UMat reIn, UMat imIn, UMat magOut, UMat phOut)
        {
            ///accepts real and imaginary parts, inverse (fourier) Transforms
            ///converts real and imaginary output parts to magnitude and
            ///phase, returns magnitude and phase parts.
            ///Refer to ForwardT() for more info on why I code like this.
            ///Reference: https://stackoverflow.com/questions/16812950/how-do-i-compute-dft-and-its-reverse-with-emgu

            VectorOfUMat vec = this.vec;

            vec.Push(reIn);
            vec.Push(imIn);
            UMat cImg = this.img32f2c;

            CvInvoke.Merge(vec, cImg);            //because Dft method accepts and outputs 2-channel image
            CvInvoke.Dft(cImg, cImg, DxtType.Inverse, 0);
            //new objects put into vec, vec[0] is reOut, vec[1] is imOut.
            CvInvoke.Split(cImg, vec);
            //convert output of inverse Transform to magnitude and polar
            CvInvoke.CartToPolar(vec[0], vec[1], magOut, phOut);
            vec.Clear();
        }
Example #2
0
        public void ProcessForwardT(UMat inImg, UMat outMagT, UMat outPhT, bool zeroPad = false, bool switchQuadrants = true)
        {
            ///Accepts a 1-channel image, updates outMagT and outPhT.
            ///magnitude and phase, cause I can't think of why you
            ///would wanna look at real and imaginary Transforms.
            ///Also can't think of how you can get complex-valued images.
            ///Quadrant rearranging doesn't support odd rows or cols.
            ///T stuff, reference: https://docs.opencv.org/master/d8/d01/tutorial_discrete_fourier_transform.html
            //convert image to 32bit float because spacial frequency
            //domain values are way bigger than spatial domain values.
            UMat re = outMagT;            //32-bit float real image, use memory from

            //outMagT cause it's gonna be updated anyway
            inImg.ConvertTo(re, DepthType.Cv32F);
            if (zeroPad)
            {
                //zero pad for faster dft
                ZeroPadImage(re);
            }
            //create imaginary image of zeros of same depthType
            //and size as image representing real plane
            UMat im = outPhT;                                           //imaginary

            im.Create(re.Rows, re.Cols, re.Depth, re.NumberOfChannels); //allocate memory so you can set it to zero array
            //if memory hasn't already been allocated for it
            im.SetTo(new MCvScalar(0));

            /// Quick exerpt about VectorOfUMat:
            /// if you create a VectorOfUMat vec, only if the first UMat variable
            /// to store the object is the vector node, like
            /// VectorOfUMat vec = new VectorOfUmat(new Umat(), new Umat());
            /// vec.Push(someUMat.Clone());
            /// then vec.Dispose/Clear actually disposes all the objects referenced
            /// to by the UMats in vec. In this case, if you did:
            /// VectorOfUMat vec = new VectorOfUMat(inImg.Clone(), inImg.Clone());
            /// UMat one = vec[0];
            /// one.Dispose();
            /// one.Dispose actually does nothing.
            /// Otherwise, if
            /// UMat one = new UMat();
            /// UMat two = new UMat();
            /// VectorOfUMat vec = new VectorOfUmat(one);
            /// vec.Push(two);
            /// calling vec.Dispose() doesn't dispose the objects.
            /// you have to call one.Dispose and two.Dispose.
            /// Note: no matter whether the UMat's first variable stored
            /// in is in a vector node or not, calling vec[index].Dispose
            /// does NOTHING.
            /// The situation is the same for vec.Clear, except Clear doesn't
            /// dispose of vec itself, it just disposes the objects the UMats in
            /// it reference to.
            //Dft accepts 2-channel images, so we use Merge to merge
            //our 2 1-channel images into a single 2-channel image.
            //Merge accepts object arrays, so we create a VectorOfUMat
            //of our 2 images to feed into Merge.

            VectorOfUMat vec  = this.vec;
            UMat         cImg = this.img32f2c;

            vec.Push(re);
            vec.Push(im);            //vec[0] = re, vec[1] = im
            ;
            CvInvoke.Merge(vec, cImg);
            CvInvoke.Dft(cImg, cImg, DxtType.Forward, 0);            //use back the same memory
            //switch quadrants while images are still combined
            if (switchQuadrants)
            {
                SwitchQuadrants(cImg);
            }
            //make the 2-channel array into 2 1-channel arrays
            CvInvoke.Split(cImg, vec); //vec[0] is reT, vec[1] is imT, they are new objects.
            CvInvoke.CartToPolar(vec[0], vec[1], outMagT, outPhT);
            vec.Clear();               //dispose reT and imT.TODO: find a way to get rid of allocating memory for reT and imT.
        }