计算机视觉——图像滤波

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43943977/article/details/102527426

实验目的:
实现图像的高斯滤波:
通过调整高斯函数的标准差(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
快速均值滤波

  1. 实验要求:
    实现图像的均值滤波
    -滤波窗口大小通过参数来指定:
    -采用积分图进行加速,实现与滤波窗口大小无关的效率;
    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));
		sum += temp[w];
	}

	//褰掍竴鍖栨护娉㈡牳锛屽拰涓?
	for (int w = 0; w < window; w++)
	{
		temp[w] = temp[w] / sum;
		//cout << temp[w] << endl;

	}
	for (int x = 0; x < img.rows; x++)
	{
		for (int y = 0; y < img.cols; y++)
		{
			float p[3] = {255,255,255 }; 
			int num = 0;
			for (int k = y - window / 2; k < y + window / 2; k++)
			{
				if (k>=0&&k<img.cols ) {
					num++;
					for (int z = 0; z < 3; z++)
					{
						float m = 1.0 / window;
						p[z] += (img.at<Vec3b>(x, k)[z])*temp[num];//杩欓噷娌″啓瀹?灏戜竴涓潈閲嶆暟缁?
						
						
					}
				}
				else {
					num++;
					for (int z = 0; z <3; z++)
						//p[z] = (img.at<Vec3b>(x, y)[z]);
						p[z] = saturate_cast<uchar>(0);
					continue;
				}


			}
			for (int zz = 0; zz <3; zz++)
			{
				out.at<Vec3b>(x, y)[zz] = p[zz];
			}
		}
			
	}

}


void Wavecol(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));
		sum += temp[w];
	}

	//褰掍竴鍖栨护娉㈡牳锛屽拰涓?
	for (int w = 0; w < window; w++)
	{
		temp[w] = temp[w] / sum;
		//cout << temp[w] << endl;

	}
	for (int y = 0; y < img.cols; y++)
	{
		for (int x = 0; x < img.rows; x++)
		{
			float p[3] = { 255,255,255 };
			int num = 0;
			for (int k = x - window / 2; k < x + window / 2; k++)
			{
				if (k >= 0 && k < img.rows) {
					num++;
					for (int z = 0; z < 3; z++)
					{
						float m = 1.0 / window;
						p[z] += (img.at<Vec3b>(k, y)[z]) * temp[num];//杩欓噷娌″啓瀹?灏戜竴涓潈閲嶆暟缁?


					}
				}
				else {
					num++;
					for (int z = 0; z < 3; z++)
						//p[z] = (img.at<Vec3b>(x, y)[z]);
						p[z] = saturate_cast<uchar>(0);
					continue;
				}


			}
			for (int zz = 0; zz < 3; zz++)
			{
				out.at<Vec3b>(x, y)[zz] = p[zz];
			}
		}

	}

}
//void Wave(Mat a, Mat b, int c, void*)
void Wave(int, void*)
{
    window = (int)((6 * sigma - 1) / 2) * 2 + 1;
	Waverow(img,rimg1,window,sigma);
	Wavecol(rimg1, rimg2,window,sigma );

	//resizeWindow("img2", 400, 400);
	imshow("img2", rimg2);
	waitKey(0);
}
int main()
{
	namedWindow("img2", WINDOW_AUTOSIZE);
	cout << img.channels() << endl;
	createTrackbar("sigma", "img2", &sigma, 10, Wave);
	Wave(sigma,0);
	return 0;
}
//均值
#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);
int sizee=1;
void MeanWave(Mat img, Mat& out, int size)
{
	int row = img.rows, col = img.cols;
	vector<vector<int> > a(img.rows, vector<int>(img.cols));

	for (int c = 0; c < 3; c++) {
		for (int i = 0; i < img.rows; i++)
		{
			for (int j = 0; j < img.cols; j++)
			{
				a[i][j] = 0;
			}
		}
		for (int i = 0; i < img.rows; i++)
		{
			int sum = 0;
			for (int j = 0; j < img.cols; j++)
			{
				sum += img.at<Vec3b>(i, j)[c];
				if (i - 1 >= 0)
					a[i][j] = a[i - 1][j] + sum;
				else
					a[i][j] = sum;
			}
		}
			for (int i = 0; i < img.rows; i++)
			{
				for (int j = 0; j < img.cols; j++)
				{
					int w = size;

					if (i - w - 1 >= 0 && i + w < row && j - w - 1 >= 0 && j + w < col) {
						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<Vec3b>(i, j)[c] = (dd + aa - bb - cc) / pow(2 * size + 1, 2);
					}
					else
						out.at<Vec3b>(i, j)[c] = img.at<Vec3b>(i, j)[c];
				}
			}
	

	}
	//namedWindow("img2", WINDOW_AUTOSIZE);
	//imshow("img2", out);
	//waitKey(0);
}
void Wave(int, void*)
{

	MeanWave(img,rimg1,sizee);

	//resizeWindow("img2", 400, 400);
	imshow("img2", rimg1);
	waitKey(0);
}
int main()
{
	namedWindow("img2", WINDOW_AUTOSIZE);
	cout << img.channels() << endl;
	//MeanWave(img, rimg1, sizee);
	createTrackbar("size", "img2", &sizee, 10, Wave);
	Wave(sizee, 0);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43943977/article/details/102527426