OpenCVSharp 4.5 去离焦模糊

用OpenCVSharp 4.5 跑一遍 OpenCV 官方教程

原官方教程链接:OpenCV: Out-of-focus Deblur Filter

using System;
using OpenCvSharp;


namespace ConsoleApp1
{
    class tutorial30 : ITutorial
    {
        public void Run()
        {
            int R = 6   ; //计算PSF参数:R(半径)
            double snr = 500; //维纳滤波器参数
            
           Mat imgIn = Cv2.ImRead("I:\\csharp\\images\\original.jpg", ImreadModes.Grayscale);
            if (imgIn.Empty()) //check whether the image is loaded or not
            {
                Console.WriteLine("ERROR : Image cannot be loaded..!!");
                return;
            }
            Mat imgOut = new Mat();
            // it needs to process even image only
            Rect roi = new Rect(0, 0, imgIn.Cols & -2, imgIn.Rows & -2);
            //Hw calculation (start)
            Mat Hw = new Mat();
            Mat h = new Mat();
            calcPSF(out h, roi.Size, R);
            calcWnrFilter(h, out Hw, 1.0 / snr);
            //Hw calculation (stop)
            // filtering (start)
            filter2DFreq( imgIn[roi], out imgOut, Hw);
            // filtering (stop)
            imgOut.ConvertTo(imgOut, MatType.CV_8U);
            Cv2.Normalize(imgOut, imgOut, 0, 255, NormTypes.MinMax);
            Cv2.ImShow("result.jpg", imgOut);
            Cv2.WaitKey();
        }

        private void calcPSF(out Mat outputImg, Size filterSize, int R)
        {
            Mat h = Mat.Zeros(filterSize, MatType.CV_32F);
            Point point = new Point(filterSize.Width / 2, filterSize.Height / 2);
            Cv2.Circle(h, point.X, point.Y, R, 255, -1, LineTypes.Link8);
            Scalar summa = Cv2.Sum(h);
            outputImg = h / summa[0];
        }


        private void filter2DFreq(Mat inputImg, out Mat outputImg, Mat H)
        {
            inputImg.Clone().ConvertTo(inputImg,MatType.CV_32F);
            
            Mat[] planes = { inputImg, Mat.Zeros(inputImg.Size(), MatType.CV_32F) };

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

            H.Clone().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 fftshift(Mat inputImg, out Mat outputImg)
        {
            outputImg = inputImg.Clone();
            int cx = outputImg.Cols / 2;
            int cy = outputImg.Rows / 2;
            Mat q0 = new Mat(outputImg, new Rect(0, 0, cx, cy));
            Mat q1 = new Mat(outputImg, new Rect(cx, 0, cx, cy));
            Mat q2 = new Mat(outputImg, new Rect(0, cy, cx, cy));
            Mat q3 = new Mat(outputImg, 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);
        }


        private void calcWnrFilter(Mat input_h_PSF, out Mat output_G, double nsr)
        {
            Mat h_PSF_shifted = new Mat();
            fftshift(input_h_PSF, out h_PSF_shifted);

            Mat[] planes = { h_PSF_shifted.Clone(), Mat.Zeros(h_PSF_shifted.Size(), MatType.CV_32F) };
            Mat complexI = new Mat();
            Cv2.Merge(planes, complexI);
            Cv2.Dft(complexI, complexI);
            Cv2.Split(complexI, out planes);
            Mat denom = new Mat();
            Cv2.Pow(Cv2.Abs(planes[0]), 2, denom);
            denom += nsr;
            Mat output = new Mat();
            Cv2.Divide(planes[0], denom, output);
            output_G = output;
        }
    }
}

 

最后效果与参数设置关系很大!多试验

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值