OpenCVSharp 4.5 去除周期性噪声

用OpenCVSharp 4.5 跑一遍OpenCV官方教程

原官方教程链接:OpenCV: Periodic Noise Removing Filter

原作者有意埋了坑,完全照抄是不行的....... 

using System;
using OpenCvSharp;
namespace ConsoleApp1
{
    class tutorial33 : ITutorial
    {
        public void Run()
        {
            Mat imgIn = Cv2.ImRead("I:\\csharp\\images\\period_input.jpg", ImreadModes.Grayscale);
            if (imgIn.Empty()) //check whether the image is loaded or not
            {
                Console.Write("ERROR : Image cannot be loaded..!!");
                return;
            }
            imgIn.ConvertTo(imgIn, MatType.CV_32F);
            // it needs to process even image only
            Rect roi = new Rect(0, 0, imgIn.Cols & -2, imgIn.Rows & -2);
            imgIn = imgIn[roi];
            // PSD calculation (start)
            Mat imgPSD = new Mat();
            calcPSD(imgIn, out imgPSD);
            //fftshift(imgPSD, out imgPSD);
            Cv2.Normalize(imgPSD, imgPSD, 0, 255, NormTypes.MinMax);
            // PSD calculation (stop)

            //H calculation (start)
            Mat H = Mat.Ones(roi.Size, MatType.CV_32F);
            int r = 21;            
            synthesizeFilterH(ref H, new Point(143, 67), r);
            synthesizeFilterH(ref H, new Point(286, 0), r);
            synthesizeFilterH(ref H, new Point(0, 135), r);
            Mat imgHPlusPSD = imgPSD + H * 50;
            Cv2.Normalize(imgHPlusPSD, imgHPlusPSD, 0, 255, NormTypes.MinMax);
            imgHPlusPSD.ConvertTo(imgHPlusPSD, MatType.CV_8U);

            //H calculation (stop)
            // filtering (start)
            Mat imgOut = new Mat();
            filter2DFreq(imgIn, out imgOut, H);
            // filtering (stop)
            
            imgOut.ConvertTo(imgOut, MatType.CV_8U);
            Cv2.Normalize(imgOut, imgOut, 0, 255, NormTypes.MinMax);
            Cv2.ImShow("result.jpg", imgOut);
            Cv2.ImShow("filter", H);
            Cv2.ImShow("PSD", imgPSD);
            Cv2.WaitKey();
        }
        private void fftshift(Mat inputImg, out Mat outputImg)
        {
            Mat output = inputImg.Clone();
            int cx = output.Cols / 2;
            int cy = output.Rows / 2;
            Mat q0 = new Mat(output, new Rect(0, 0, cx, cy));
            Mat q1 = new Mat(output, new Rect(cx, 0, cx, cy));
            Mat q2 = new Mat(output, new Rect(0, cy, cx, cy));
            Mat q3 = new Mat(output, new Rect(cx, cy, cx, cy));
            Mat tmp = new Mat();
            q0.CopyTo(tmp);
            q3.CopyTo(q0);
            tmp.CopyTo(q3);
            q1.CopyTo(tmp);
            q2.CopyTo(q1);
            tmp.CopyTo(q2);
            outputImg = output;
        }

        private void filter2DFreq(Mat inputImg, out Mat outputImg, Mat H)
        {
            Mat m1 = inputImg.Clone();
            m1.ConvertTo(m1, MatType.CV_32F);

            Mat m2 = Mat.Zeros(inputImg.Size(), MatType.CV_32F);

            Mat[] planes = { m1, m2 };
            Mat complexI = new Mat();
            Cv2.Merge(planes, complexI);
            Cv2.Dft(complexI, complexI, DftFlags.Scale);
            
            H.ConvertTo(H, MatType.CV_32F);
            Mat[] planesH = { H, Mat.Zeros(H.Size(), MatType.CV_32F) };

            Mat complexH = new Mat();
            Cv2.Merge(planesH, complexH);

            Mat complexIH = new Mat();
            Cv2.MulSpectrums(complexI, complexH, complexIH, 0);
            Cv2.Idft(complexIH, complexIH);
            Cv2.Split(complexIH, out planes);
            outputImg = planes[0];
        }
        private void synthesizeFilterH(ref Mat inputOutput_H, Point center, int radius)
        {            
            Point c2 = center, c3 = center, c4 = center;
            c2.Y = inputOutput_H.Rows - center.Y;
            c3.X = inputOutput_H.Cols - center.X;
            c4 = new Point(c3.X, c2.Y);
            Cv2.Circle(inputOutput_H, (int)center.X, (int)center.Y, radius, new Scalar(0), Cv2.FILLED, LineTypes.Link8);
            Cv2.Circle(inputOutput_H, (int)c2.X, (int)c2.Y, radius, new Scalar(0), Cv2.FILLED, LineTypes.Link8);
            Cv2.Circle(inputOutput_H, (int)c3.X, (int)c3.Y, radius, new Scalar(0), Cv2.FILLED, LineTypes.Link8);
            Cv2.Circle(inputOutput_H, (int)c4.X, (int)c4.Y, radius, new Scalar(0), Cv2.FILLED, LineTypes.Link8);
        }
        // Function calculates PSD(Power spectrum density) by fft with two flags
        // flag = 0 means to return PSD
        // flag = 1 means to return log(PSD)
        private void calcPSD(Mat inputImg, out Mat outputImg, int flag=0)    
        {
            Mat m1 = inputImg.Clone();
            m1.ConvertTo(m1, MatType.CV_32F);

            Mat m2 = Mat.Zeros(inputImg.Size(), MatType.CV_32F);

            Mat[] planes = { m1, m2 };


            Mat complexI = new Mat();
            Cv2.Merge(planes, complexI);

            Cv2.Dft(complexI, complexI);
            Cv2.Split(complexI, out planes);
            // planes[0] = Re(DFT(I)), planes[1] = Im(DFT(I))
            planes[0].At<float>(0) = 0;
            planes[1].At<float>(0) = 0;

            // compute the PSD = sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)^2
            Mat imgPSD = new Mat();
            Cv2.Magnitude(planes[0], planes[1], imgPSD);        //imgPSD = sqrt(Power spectrum density)
            Cv2.Pow(imgPSD, 2, imgPSD);                         //it needs ^2 in order to get PSD
            outputImg = imgPSD;
            // logPSD = log(1 + PSD)
            if (flag > 0)
            {
                Mat imglogPSD;
                imglogPSD = imgPSD + 1;
                Cv2.Log(imglogPSD, imglogPSD);
                outputImg = imglogPSD;
            }
        }
    }
}

 原图

局部放大

去除周期性噪声后结果

period_output.jpg

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
去除周期性噪声,我们可以使用几种方法。首先,我们可以通过频域滤波来消除这种噪声。频域滤波是一种在频域对信号进行处理的技术。我们可以使用傅里叶变换将信号从时域转换到频域,然后通过滤波器去除频谱中的周期性噪声成分,最后再通过傅里叶反变换将信号转换回时域。这种方法可以有效地去除周期性噪声,但需要在频域上进行处理,对信号的频谱有一定的要求。 另外一种方法是使用滑动平均滤波器。滑动平均滤波器是一种对信号进行平滑处理的方法。它通过对信号的一系列连续采样值进行平均,从而减小噪声的影响。对于周期性噪声,我们可以选择合适的滑动窗口大小,使其能够覆盖噪声周期的整数倍,并通过计算窗口内的平均值来减小噪声的影响。 另外,我们还可以使用自适应滤波器来去除周期性噪声。自适应滤波器是一种能够根据信号的统计特性自动调整滤波器参数的滤波器。它能够根据输入信号的变化情况自动调整自身的滤波器系数,以最小化输出信号与期望信号之间的误差。对于周期性噪声,我们可以通过训练自适应滤波器,使其能够自动识别和去除周期性噪声的成分。 总而言之,去除周期性噪声可以使用频域滤波、滑动平均滤波器和自适应滤波器等多种方法。根据实际情况选择适当的方法,可以有效地去除周期性噪声,提高信号的质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值