这是一个图像去模糊的小demo,用OpenCV实现。
#include
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2\highgui.hpp"
using namespace cv;
using namespace std;
int r = 10;
int snr = 60;
void deblur(cv::Mat &src, cv::Mat &dst, int r, int snr);
void calcPSF(Mat& outputImg, Size filterSize, int R);
void fftshift(const Mat& inputImg, Mat& outputImg);
void filter2DFreq(const Mat& inputImg, Mat& outputImg, const Mat& H);
void calcWnrFilter(const Mat& input_h_PSF, Mat& output_G, double nsr);
int main(void)
{
Mat src = imread("222.jpeg");
namedWindow("原图", 0);
cv::imshow("原图", src);
cv::Mat dst;
deblur(src, dst, r, snr);
namedWindow("去模糊:", 0);
imshow("去模糊:", dst);
waitKey(0);
return 0;
}
void deblur(cv::Mat &src, cv::Mat &dst, int r, int snr)
{
cv::Mat gray;
if (src.data == nullptr)
{
return;
}
if (src.channels() > 1)
{
cv::cvtColor(src, gray, CV_BGR2GRAY);
}
Rect roi = Rect(0, 0, gray.cols & -2, gray.rows & -2);
Mat Hw, h;
calcPSF(h, roi.size(), r);
calcWnrFilter(h, Hw, 1.0 / double(snr));
filter2DFreq(gray(roi), dst, Hw);
dst.convertTo(dst, CV_8U);
normalize(dst, dst, 0, 255, NORM_MINMAX);
}
void calcPSF(Mat& outputImg, Size filterSize, int R)
{
Mat h(filterSize, CV_32F, Scalar(0));
Point point(filterSize.width / 2, filterSize.height / 2);
circle(h, point, R, 255, -1, 8);
Scalar summa = sum(h);
outputImg = h / summa[0];
}
void fftshift(const Mat& inputImg, Mat& outputImg)
{
outputImg = inputImg.clone();
int cx = outputImg.cols / 2;
int cy = outputImg.rows / 2;
Mat q0(outputImg, Rect(0, 0, cx, cy));
Mat q1(outputImg, Rect(cx, 0, cx, cy));
Mat q2(outputImg, Rect(0, cy, cx, cy));
Mat q3(outputImg, Rect(cx, cy, cx, cy));
Mat tmp;
q0.copyTo(tmp);
q3.copyTo(q0);
tmp.copyTo(q3);
q1.copyTo(tmp);
q2.copyTo(q1);
tmp.copyTo(q2);
}
void filter2DFreq(const Mat& inputImg, Mat& outputImg, const Mat& H)
{
Mat planes[2] = {
Mat_<float>(inputImg.clone()), Mat::zeros(inputImg.size(), CV_32F) };
Mat complexI;
merge(planes, 2, complexI);
dft(complexI, complexI, DFT_SCALE);
Mat planesH[2] = {
Mat_<float>(H.clone()), Mat::zeros(H.size(), CV_32F) };
Mat complexH;
merge(planesH, 2, complexH);
Mat complexIH;
mulSpectrums(complexI, complexH, complexIH, 0);
idft(complexIH, complexIH);
split(complexIH, planes);
outputImg = planes[0];
}
void calcWnrFilter(const Mat& input_h_PSF, Mat& output_G, double nsr)
{
Mat h_PSF_shifted;
fftshift(input_h_PSF, h_PSF_shifted);
Mat planes[2] = {
Mat_<float>(h_PSF_shifted.clone()), Mat::zeros(h_PSF_shifted.size(), CV_32F) };
Mat complexI;
merge(planes, 2, complexI);
dft(complexI, complexI);
split(complexI, planes);
Mat denom;
pow(abs(planes[0]), 2, denom);
denom += nsr;
divide(planes[0], denom, output_G);
}