用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;
}
}
}
最后效果与参数设置关系很大!多试验