目录
实验原理
https://zhuanlan.zhihu.com/p/76188487
在OpenCV中,cv::blur函数用于对图像进行均值滤波(Mean Filter),这是一种线性滤波技术,主要用于平滑图像和去除噪声。均值滤波是一种线性滤波技术,它通过替换每个像素值为其邻域内的平均值来平滑图像,从而减少图像中的噪声。均值滤波器对于减少高斯噪声特别有效,但它可能会模糊边缘和其他细节。
函数原型
void blur(InputArray src, OutputArray dst, Size ksize,
Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT );
参数说明
src: 输入图像,它可以是多通道图像。
dst: 处理后的图像,与输入图像具有相同的尺寸和类型。
ksize: 内核大小,指定卷积核的大小,通常是一个正方形核,指定为一个 Size 对象。例如,Size(5, 5) 表示使用一个5x5的内核进行卷积操作。
anchor: 锚点位置,即内核相对于像素的位置。默认情况下(Point(-1, -1)),锚点位于内核中心。
borderType: 边界处理方式。当内核的一部分超出图像边界时,需要对这部分进行某种处理。默认为 BORDER_DEFAULT,通常意味着使用 BORDER_REFLECT_101。
常见的边界处理方式包括:
•BORDER_CONSTANT:用指定的常数值填充边界。
•BORDER_REPLICATE:边界像素值向外扩展。
•BORDER_REFLECT:反射边界,如12345反射为45454。
•BORDER_WRAP:循环边界,如12345循环为34512。
工作原理
均值滤波器的工作原理是对图像中的每个像素应用一个卷积核(Kernel),该核中的每个元素都是相等的权重(通常是1除以核的大小)。卷积核中的所有元素值相加求平均值,然后将这个平均值赋给当前像素点。
示例代码
下面是一个使用C++和OpenCV进行均值滤波的简单示例:
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>
int main(int argc, char** argv)
{
// 加载图像
cv::Mat img = cv::imread("2B.png", cv::IMREAD_COLOR); // 读取彩色图像
if (img.empty())
{
std::cout << "Could not open or find the image" << std::endl;
return -1;
}
// 定义内核大小
int kernel_size = 5; // 5x5 的内核
cv::Size ksize(kernel_size, kernel_size);
// 创建一个空的输出图像
cv::Mat dst;
// 应用均值滤波
cv::blur(img, dst, ksize);
// 显示结果
cv::namedWindow("Original Image", cv::WINDOW_NORMAL);
cv::imshow("Original Image", img);
cv::namedWindow("Blurred Image", cv::WINDOW_NORMAL);
cv::imshow("Blurred Image", dst);
cv::waitKey(0);
return 0;
}
运行结果
去除脸上毛孔
注意事项
- 内核大小: 内核大小的选择会影响滤波的效果。较大的核可以产生更强烈的平滑效果,但可能会丢失更多的细节;较小的核则可以保留更多细节,但平滑效果较弱。
- 性能: 在处理大图像或者使用大内核时,均值滤波可能比较耗时。
- 边界效应: 在图像边界处,由于部分内核超出图像范围,因此边界上的像素可能会受到不同类型的处理,这取决于所选的边界类型。边界处理borderType参数决定了如何处理图像边缘的像素。
总结
均值滤波是一种简单有效的图像平滑方法,适用于去除图像中的噪声和平滑图像。通过调整卷积核的大小,可以控制平滑的程度。但是,它也会使图像中的边缘变得模糊,因此在某些应用中可能不是最佳选择。如果需要保留边缘细节,可以考虑使用其他类型的滤波器,如高斯滤波或者双边滤波。
实验代码
#include "pch.h"
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <stdio.h>
using namespace std;
using namespace cv;
//#pragma comment(lib, "opencv_world450d.lib") //引用引入库
//定义全局变量
Mat g_srcImage; //定义输入图像
Mat g_dstImage; //定义目标图像
const int g_nTrackbarMaxValue = 9; //定义轨迹条最大值
int g_nTrackbarValue; //定义轨迹条初始值
int g_nKernelValue; //定义kernel尺寸
void on_kernelTrackbar(int, void*); //定义回调函数
int main()
{
g_srcImage = imread("A3.jpeg");
//判断图像是否加载成功
if (g_srcImage.empty())
{
cout << "图像加载失败!" << endl;
return -1;
}
else
cout << "图像加载成功!" << endl << endl;
namedWindow("原图像", WINDOW_NORMAL); //定义窗口显示属性
imshow("原图像", g_srcImage);
g_nTrackbarValue = 1;
namedWindow("均值滤波", WINDOW_NORMAL); //定义滤波后图像显示窗口属性
//定义轨迹条名称和最大值
char kernelName[20];
sprintf(kernelName, "kernel尺寸 %d", g_nTrackbarMaxValue);
//创建轨迹条
createTrackbar(kernelName, "均值滤波", &g_nTrackbarValue, g_nTrackbarMaxValue, on_kernelTrackbar);
on_kernelTrackbar(g_nTrackbarValue, 0);
waitKey(0);
return 0;
}
void on_kernelTrackbar(int, void*)
{
//根据输入值重新计算kernel尺寸
g_nKernelValue = g_nTrackbarValue * 2 + 1;
//均值滤波函数
blur(g_srcImage, g_dstImage, Size(g_nKernelValue, g_nKernelValue));
imshow("均值滤波", g_dstImage);
}