前言
本文将是一篇为图像处理的初学者准备的滤波算法的入门文章。理论在前,代码在后。
算法
高斯滤波算法
一维高斯函数
G ( x ) = 1 2 π e − x 2 2 σ 2 G(x) = \frac{1}{\sqrt{2\pi }}e^{-\frac{x^{2}}{2\sigma ^{2}}} G(x)=2π1e−2σ2x2
在图像处理中,选定X方向上长度为3的窗口,令δ=1,中心坐标为1,由上述公式,其卷积核(Xa,X,Xb)可以如下计算:
Xa = exp(-1*(0-1)(0-1)/(2*1*1))= 0.606530659712633
X = exp(-1*(1-1)(1-1)/(2*1*1))= 1
Xb = exp(-1*(2-1)(2-1)/(2*1*1))= 0.606530659712633
进行归一化操作可得
Sum = Xa + X + Xb = 2.2130613194252668
Xa = Xa/Sum = 0.274068619061197
X = X/Sum = 0.451862761877606
Xb = Xb/Sum = 0.274068619061197
当然你不需要手动计算,opencv提供了这样一个接口
import cv2 as cv
_kernel = cv.getGaussianKernel(3,1)
print(_kernel)
那么二维卷积的计算?(3,1)*(1,3)矩阵即得(3,3)
import cv2 as cv
import numpy as np
_kernel_x = cv.getGaussianKernel(3,1)
_kernel_y = cv.getGaussianKernel(3,1)
_kernel = _kernel_x*np.transpose(_kernel_y)
print(_kernel)
输出结果如下:
[[0.07511361 0.1238414 0.07511361]
[0.1238414 0.20417996 0.1238414 ]
[0.07511361 0.1238414 0.07511361]]
滤波前
滤波后
代码
高斯滤波算法
python代码(也是文本实例中使用的)
# -*- coding: utf-8 -*-
import cv2 as cv
if __name__ == "__main__":
img = cv.imread("Noise.bmp",1)
img = cv.GaussianBlur(img,(5,5),0.8)
#cv.imshow("godness",img)
cv.imwrite("liuyifei.bmp",img)
相关C++代码
#include <cmath>
#include <limits>
#include <cstdlib>
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <string>
using namespace cv;
using namespace std;
//生成高斯噪声
double generateGaussianNoise(double mu, double sigma)
{
//定义小值
const double epsilon = numeric_limits<double>::min();
static double z0, z1;
static bool flag = false;
flag = !flag;
//flag为假构造高斯随机变量X
if (!flag)
return z1 * sigma + mu;
double u1, u2;
//构造随机变量
do
{
u1 = rand() * (1.0 / RAND_MAX);
u2 = rand() * (1.0 / RAND_MAX);
} while (u1 <= epsilon);
//flag为真构造高斯随机变量
z0 = sqrt(-2.0*log(u1))*cos(2 * CV_PI*u2);
z1 = sqrt(-2.0*log(u1))*sin(2 * CV_PI*u2);
return z0 * sigma + mu;
}
//为图像添加高斯噪声
Mat addGaussianNoise(Mat &srcImag)
{
Mat dstImage = srcImag.clone();
int channels = dstImage.channels();
int rowsNumber = dstImage.rows;
int colsNumber = dstImage.cols*channels;
//判断图像的连续性
if (dstImage.isContinuous())
{
colsNumber *= rowsNumber;
rowsNumber = 1;
}