实验目的:
实现图像的高斯滤波:
通过调整高斯函数的标准差(sigma)来控制平滑程度;
滤波窗口大小取为[6*sigma-1],[.]表示取整;
利用二维高斯函数的行列可分离性进行加速;
先对每行进行一维高斯滤波,再对结果的每列进行同样的一维高斯滤波
实现图像的均值滤波
滤波窗口大小通过参数来指定:
采用积分图进行加速,实现与滤波窗口大小无关的效率;
(代码在最后面)
4.1高斯滤波
1.实验要求:通过调整高斯函数的标准差(sigma)来控制平滑程度;利用二维高斯函数的行列可分离性进行加速;
2.
3.实验步骤:
(1)sigma和window之间的关系,并由此确定weight array。
给定sigma,窗口大小window的值:
window = (int)((6 * sigma - 1) / 2) * 2 + 1;
归一化weight array(累加和为1)
double* temp = new double[window];
double sum = 0;
for (int w = 0; w < window; w++)
{
int mid = w - window / 2;
temp[w] = exp(-(mid * mid) / (2 * sigma * sigma));
sum += temp[w];
}
for (int w = 0; w < window; w++)
{
temp[w] = temp[w] / sum;}
(2)行和列分别进行一维高斯滤波(以行为例)
for (int y = 0; y < cols; y++)
for (int x = 0; x < cols; x++)
for (int k = x - window / 2; k < x + window / 2; k++)
if (k >= 0 && k < img.rows)
p += (img.(k, y)) * weight
newimg.(x,y)=p;
(3)设置滑动条来进行sigma的调节,自动回调函数
createTrackbar(“sigma”, “img”, &sigma, 10, Wavefunction);
(4)边界处理:边界处理采用镜面对称的方法进行扩大,以最右侧边界为例:
out.at(i, cols+j)= out.at(i, cols-j);
(5)最后运行截图如下
初始图片:
Sigma=1:
Sigma=4:
Sigma=8:
可见随着sigma的增大,窗口也增大,图像的每一个像素点依赖于周围更多的点的加权均值,所以图像也会出现越来越模糊的情况。
4.2
快速均值滤波
- 实验要求:
实现图像的均值滤波
-滤波窗口大小通过参数来指定:
-采用积分图进行加速,实现与滤波窗口大小无关的效率;
2.加速方法——积分图
图像I的积分图S是与其大小相同的图像,S的每一像素S(u,v)存贮的是I(u,v)左上角所有像素的颜色值之和。
设设滤波窗口大小为2w+1,滤波结果为图像O,则
Z=(2w+1)*(2w+1)为像素个数
3.实验步骤
(1)设置vector数组用于存储积分:
vector<vector > a(img.rows, vector(img.cols));
(2)求取积分。
for (int i = 0; i < img.rows; i++){
int sum = 0;
for (int j = 0; j < img.cols; j++){
sum += img.at(i, j)[c];
if (i - 1 >= 0)
a[i][j] = a[i - 1][j] + sum;
else
a[i][j] = sum;}}
(3)颜色赋值:
int aa = a[i - w - 1][j - w - 1], bb = a[i - w - 1][j + w];
int cc = a[i + w][j - w - 1], dd = a[i + w][j + w];
out.at(i, j) = (dd + aa - bb - cc) / pow(2 * size + 1, 2);
(4)设置滑动条,这与高斯部分的原理相似,这里不再赘述。
(5)运行效果:
原图:
Size=1
Size=4
Size=7
可以看到随着size的增大,图像变得越来越模糊。
//高斯
#include<opencv2/core/core.hpp>
#include<opencv2/imgcodecs.hpp>
#include<opencv2/core/saturate.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
#include<cxcore.h>
#include<cmath>
#include<cv.h>
#include<highgui.h>
using namespace std;
using namespace cv;
Mat img = imread("D:\\picture\\tea2.jpg");
Mat rimg1 = Mat::zeros(img.size(), CV_8UC3);
Mat rimg2 = Mat::zeros(img.size(), CV_8UC3);
int sigma = 8;
int window;
void Waverow(Mat img, Mat &out, int window,int sigma)
{
double* temp = new double[window];
double sum = 0;
for (int w = 0; w < window; w++)
{
int mid = w - window / 2;
temp[w] = exp(-(mid * mid) / (2 * sigma * sigma)