山东大学数字图像处理实验(四) 计算机学院(2020级)

本实验为计算机科学与技术学院计算机专业大四上限选课,2023-2024-1年度课程实验,较以往实验内容发生较大变化
本实验使用vs2019,c++语言,需要提前安装opencv,具体方法请自行搜索。

实验4:图像滤波

实现一个双边滤波(Bilateral Filter),并与高斯滤波比较保持图像边缘的效果,与cv::bilateralFilter比较效果和速度

#include <opencv2/opencv.hpp>  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc.hpp>  
#include <iostream>  
#include <vector>
#include <time.h>
using namespace std;
using namespace cv;

Mat src, dst, dst2, blurred, kernel;

int windowSize = 5;
int sigma_r = 300;
int sigma_s = 10;
clock_t startTime, endTime;



void on_Trackbar(int, void*)
{
	//Gaussian();//与高斯滤波比较保持图像边缘的效果
	startTime = clock();
	bilateralFilter(src, dst2, windowSize*2, sigma_r, sigma_s);
	imshow("Bilateral_Img", dst2);
	endTime = clock();
	cout << "使用库函数bilateralFilter的时间为   " << endTime - startTime << "   " << endl;
	startTime = clock();
	// 使用双边滤波器对源图像进行滤波,将结果保存在dst2中,窗口大小为windowSize,分别有sigma_r和sigma_s控制空间域和灰度域的滤波强度  
	//dst2.convertTo(dst, src.type());
	//imshow("My_algorithm", dst);
	// 将经过双边滤波后的图像转换为与源图像相同的类型,并保存结果在dst中  
	//imshow("My_algorithm", dst);
	int windowSize_2 = windowSize;
	Mat src_tmp, dst_tmp;
	// 使用copyMakeBorder函数为源图像添加边界,边界大小为windowSize_2,复制边界像素填充新边界,新边界的类型为BORDER_REPLICATE
	copyMakeBorder(src, src_tmp, windowSize_2, windowSize_2, windowSize_2, windowSize_2, BORDER_REPLICATE);
	// 将源图像数据转换为CV_64FC3类型(64位浮点数3通道),并缩放像素值到[0,1]范围(归一化)
	src_tmp.convertTo(src_tmp, CV_64FC3, 1.0 / 255.0);
	dst_tmp = Mat::zeros(src.size(), src_tmp.type());
	// 获取源图像的行数和列数  
	int rows = src_tmp.rows, cols = src_tmp.cols;
	//imshow("My_algorithm", dst);
	//cout << rows << "   " << cols <<"   "<<windowSize_2<< endl;
	//cout << "ss" << endl;
	// 循环处理图像的每个像素(三通道颜色) 
	for (int k = 0; k < 3; ++k)
	{
		// 对图像的每一行进行循环(除去窗口大小的边缘像素) 
		for (int i = windowSize_2; i < rows - windowSize_2; ++i)
		{
			//列

			for (int j = windowSize_2; j < cols - windowSize_2; ++j)
			{
				//cout << i - windowSize_2 << "  " << j - windowSize_2 << endl;
				//cout << j << endl;
				double sum = 0, sum1 = 0, sum2 = 0;
				// 对以当前像素为中心的窗口内的每个像素进行循环(包括边缘像素)

				for (int x = i - windowSize_2; x <= i + windowSize_2; ++x)
				{
					//cout << "x= " << x << endl;
					for (int y = j - windowSize_2; y <= j + windowSize_2; ++y)
					{
						//cout << "y= " << y << endl;
						double g_s = exp(-(pow(x - i, 2) + pow(y - j, 2) / (2.0 * pow(sigma_s, 2))));//计算空间域
						double g_r = exp(-pow(src_tmp.at<Vec3d>(i, j)[k] - src_tmp.at<Vec3d>(x, y)[k], 2) / (2 * pow(sigma_r, 2)));//计算像素域
						sum1 += g_s * g_r * src_tmp.at<Vec3d>(x, y)[k];
						sum2 += g_s * g_r;
					}
				}
				//cout << sum2 << endl;
				dst_tmp.at<Vec3d>(i - windowSize_2, j - windowSize_2)[k] = sum1 / sum2;
				//cout << "{{{{" << endl;
			}
		}
	}
	//dst_tmp.convertTo(dst, src.type(), 255);//对应之前的归一化
	endTime = clock();
	//imshow("Bilateral_Img", dst2);
	cout << "使用自己实现的双边滤波的时间为   " << endTime - startTime << "   " << endl;
	imshow("My_algorithm", dst_tmp);
}

int main()
{
	src = imread("C:/Users/13441/Desktop/数字图像/back.png");
	//namedWindow("sec_image", WINDOW_AUTOSIZE);
	imshow("src_image", src);
	dst = Mat::zeros(src.size(), src.type());
	dst2 = Mat::zeros(src.size(), src.type());
	//namedWindow("My_algorithm", WINDOW_AUTOSIZE);
	namedWindow("Bilateral_Img", WINDOW_AUTOSIZE);
	//createTrackbar("窗口大小", "Bilateral_Img", &windowSize, 50, on_Trackbar);
	createTrackbar("Sigma_r", "Bilateral_Img", &sigma_r, 500, on_Trackbar);
	createTrackbar("Sigma_s", "Bilateral_Img", &sigma_s, 20, on_Trackbar);
	waitKey(0);
	return 0;
}

实现的双边滤波:

cv::bilateralFilter函数:

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值