本实验为计算机科学与技术学院计算机专业大四上限选课,2023-2024-1年度课程实验,较以往实验内容发生较大变化
本实验使用vs2019,c++语言,需要提前安装opencv,具体方法请自行搜索。
实验三:图像滤波
•
实现高斯滤波,基于行列可分离性进行加速,并与没有加速的情况进行速度和效果的对比。
•
•
与
OpenCV
的
GaussianBlur
函数比较计算速度,并分析导致速度差异的原因。
#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;
int ksize = 1; //声明并初始化ksize变量,用于控制高斯核的大小
Mat src, dst, blurred, kernel;
clock_t startTime, endTime;
//高斯滤波函数,参数包括ksize和void指针(此处未使用)
void Gaussian(int, void*) {
int GaussianKernel = 6 * ksize - 1; //计算高斯核的大小
cout << "高斯核大小为: " << GaussianKernel << endl;
startTime = clock();
// 使用库文件自带的高斯滤波函数
GaussianBlur(src, blurred, Size(GaussianKernel, GaussianKernel), 0, 0);
imshow("Blurred Image", blurred);
endTime = clock();
cout << "使用库函数GaussianBlur的时间为 " << endTime - startTime << " " << endl;
startTime = clock();
kernel = getGaussianKernel(GaussianKernel, ksize).t(); //生成一维高斯核并转置
double* matrix = kernel.ptr<double>(0); //获取一维高斯核的数据指针
int GaussianKernel_2 = GaussianKernel / 2; //计算高斯核半径
Mat src_Extended;
//对源图像进行边界扩展,扩展方式为复制
copyMakeBorder(src, src_Extended, GaussianKernel_2, GaussianKernel_2, GaussianKernel_2, GaussianKernel_2, BORDER_REPLICATE);
const int row = src_Extended.rows; //获取扩展后图像的行列数
const int col = src_Extended.cols;
Mat dst_tmp = src_Extended.clone(); //复制扩展后的图像到临时目标图像
//除以255进行归一化
dst_tmp.convertTo(dst_tmp, CV_64FC3, 1 / 255.0);
//水平方向的高斯滤波
for (int i = GaussianKernel_2; i < row - GaussianKernel_2; i++) { //行循环
for (int j = GaussianKernel_2; j < col - GaussianKernel_2; j++) {
for (int k = 0; k < 3; ++k) { //通道循环
double sum = 0.0;
//计算每一个像素点周围矩形区域内所有像素点的累加和
for (int x = 0; x < GaussianKernel; x++) {
sum += src_Extended.at<Vec3b>(i, j - GaussianKernel_2 + x)[k] / 255.0 * matrix[x];
}
dst_tmp.at<Vec3d>(i, j)[k] = sum; //将累加和保存到临时目标图像中
}
}
}
//竖直方向的高斯滤波
dst = Mat(src.size(), src.type());
for (int i = GaussianKernel_2; i < row - GaussianKernel_2; i++) {
for (int j = GaussianKernel_2; j < col - GaussianKernel_2; j++) {
for (int k = 0; k < 3; ++k) {
double sum = 0.0;
// 计算每一个像素点周围矩形区域内所有像素点的累加和
for (int y = 0; y < GaussianKernel; y++) {
sum += dst_tmp.at<Vec3d>(i - GaussianKernel_2 + y, j)[k] * matrix[y];
}
dst.at<Vec3b>(i - GaussianKernel_2, j - GaussianKernel_2)[k] = (uchar)(sum * 255.0 + 0.5); // 将累加和乘以255并四舍五入
}
}
}
imshow("Dst_img", dst); // 显示目标图像
endTime = clock();
cout << "使用自己实现的高斯滤波的时间为 " << endTime - startTime << " " << endl << endl;
}
int main()
{
src = imread("C:/Users/13441/Desktop/数字图像/a.png");
namedWindow("Dst_img", WINDOW_AUTOSIZE);
createTrackbar("Sigma:", "Dst_img", &ksize, 20, Gaussian);
//Mat blurred;
// 使用库文件自带的高斯滤波函数
//GaussianBlur(src, blurred, cv::Size(29, 29), 0, 0);
//imshow("Blurred Image", blurred);
waitKey(0);
return 0;
}
自己实现和自带的对比: