Advertisement

山东大学数字图像处理实验(四) 计算机学院(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;
    
 }
    
    
    
    
    cpp
    
    
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-17/VakE18DoCK5WvMAIw4PZly3nJhXz.png)

实现的双边滤波:

cv::bilateralFilter函数:

全部评论 (0)

还没有任何评论哟~