OpenCV计算机视觉开发入门与实践<二十三>:图像平滑之非线性滤波

1. 中值滤波

摘要 :本文介绍 OpenCV 中两种常用的空域平滑滤波方法------中值滤波与双边滤波。中值滤波通过取邻域灰度中值去除椒盐噪声,适合消除孤立噪点;双边滤波在加权平均中同时考虑空间距离与灰度差异,能够在降噪的同时较好地保留图像边缘。文中分别给出 medianBlur()bilateralFilter() 的接口说明及完整 C++ 示例代码。

  中值滤波用像素点领域灰度值的中值来代替该像素点的灰度值,也就是说用一片区域的中间值来代替所有值,这可以除去最大值和最小值。中值滤波对除去斑点噪声和椒盐噪声很有用,缺点是中值滤波花费的时间在均值滤波的5倍以上。

  中值平滑也有核,但并不进行卷积计算,而是对核中所有像素值排序得到中间值,用该中间值来代替锚点值。中值滤波在数字图像处理中属于空域平滑滤波的内容。

  在OpenCV中,利用medianBlur()来进行中值平滑,其声明如下:

cpp 复制代码
void cv::medianBlur ( InputArray src, OutputArray dst, int ksize );

  其中参数src表示输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个。对于较大孔径尺寸的图片,图像深度只能是CV_8U。dst表示输出图像,尺寸和类型与输入图像一致,可以使用Mat::Clone以原图像为模板来初始化输出图像。ksize表示滤波模板的尺寸大小,必须是大于1的奇数,如

3、5、7......

【例6.3】实现中值滤波

在代码中,我们对图片进行了孔径为7的中值滤波。

cpp 复制代码
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
int main()
{
	Mat image = imread("lady.png");	// 载入原图
	namedWindow("src");	//创建窗口
	namedWindow("median filtering");//命名窗口
	//显示原图
	imshow("src", image);
	//进行中值滤波操作
	Mat out;
	medianBlur(image, out, 7);//输入,输出,孔径为7
	//显示效果图
	imshow("median filtering", out);//显示中值滤波效果图
	waitKey(0);
}

2. 双边滤波

  当前介绍的滤波器都是为了平滑图像,问题是有些时候这些滤波器不仅削弱了噪声,还把边缘也给磨掉了。为了避免这样的情形(至少在一定程度上),我们可以使用双边滤波。类似于高斯滤波器,双边滤波器也给每一个邻域像素分配一个加权系数。这些加权系数包含两部分:第一部分的加权方式与高斯滤波一样,第二部分的权重取决于该邻域像素与当前像素的灰度差值。

  双边滤波是一种非线性滤波器,它可以达到保持边缘、降噪平滑的效果。和其他滤波原理一样,双边滤波也采用加权平均的方法,用周边像素亮度值的加权平均代表某个像素的强度,所用的加权平均基于高斯分布。最重要的是,在计算中心像素的时候,双边滤波的权重不仅考虑了像素的欧氏距离(如普通的高斯低通滤波,只考虑了位置对中心像素的

影响),还考虑了像素范围域中的辐射差异(如卷积核中像素与中心像素之间的相似程

度、颜色强度、深度距离等)。

  与高斯滤波相比,双边滤波能够更好地保存图像的边缘信息。其原理为一个与空间距离相关的高斯函数与一个与灰度距离相关的高斯函数相乘。

  下面来看一个例子,使用4种不同的滤波器读取一幅图像,并显示平滑图像。

【例6.4】使用4种不同的滤波器读取并显示平滑图像

cpp 复制代码
#include <iostream>
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace std;
using namespace cv;
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;
Mat src; Mat dst;
char window_name[] = "Smoothing Demo";
int display_caption(const char* caption);
int display_dst(int delay);

int main(int argc, char** argv)
{
	namedWindow(window_name, WINDOW_AUTOSIZE);
	const char* filename = argc >= 2 ? argv[1] : "lena.png";
	src = imread(samples::findFile(filename), IMREAD_COLOR);
	if (src.empty())
	{
		printf(" Error opening image\n");
		printf(" Usage:\n %s [image_name-- default lena.jpg] \n", argv[0]);
		return EXIT_FAILURE;
	}

	if (display_caption("Original Image") != 0)
	{
		return 0;
	}

	dst = src.clone();
	if (display_dst(DELAY_CAPTION) != 0)
	{
		return 0;
	}

	if (display_caption("Homogeneous Blur") != 0)
	{
		return 0;
	}

	for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2)
	{
		blur(src, dst, Size(i, i), Point(-1, -1));
		if (display_dst(DELAY_BLUR) != 0)
		{
			return 0;
		}
	}

	if (display_caption("Gaussian Blur") != 0)
	{
		return 0;
	}

	for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2)
	{
		GaussianBlur(src, dst, Size(i, i), 0, 0);
		if (display_dst(DELAY_BLUR) != 0)
		{
			return 0;
		}
	}

	if (display_caption("Median Blur") != 0)
	{
		return 0;
	}

	for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2)
	{
		medianBlur(src, dst, i);
		if (display_dst(DELAY_BLUR) != 0)
		{
			return 0;
		}
	}

	if (display_caption("Bilateral Blur") != 0)
	{
		return 0;
	}

	for (int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2)
	{
		bilateralFilter(src, dst, i, i * 2, i / 2);
		if (display_dst(DELAY_BLUR) != 0)
		{
			return 0;
		}
	}

	display_caption("Done!");

	return 0;
}
int display_caption(const char* caption)
{
	dst = Mat::zeros(src.size(), src.type());
	putText(dst, caption, Point(src.cols / 4, src.rows / 2), FONT_HERSHEY_COMPLEX, 1,
		Scalar(255, 255, 255));
	return display_dst(DELAY_CAPTION);
}

int display_dst(int delay)
{
	imshow(window_name, dst);
	int c = waitKey(delay);
	if (c >= 0) { return -1; }
	return 0;
}
相关推荐
飞Link1 小时前
阿里千问 PC 端语音功能实测:大模型交互如何解决程序员的“腱鞘炎”?
人工智能
国科安芯1 小时前
星载CANFD总线通信网络中抗辐射微控制器MCU的失效机理与容错设计研究
网络·人工智能·分布式·单片机·嵌入式硬件·架构·抗辐射加固
xier_ran1 小时前
【infra之路】矩阵乘法(GEMM) Tiling 复用机制总结
人工智能·深度学习
zlinear数据采集卡1 小时前
FRAM铁电存储器原理深度解析:D223校准参数的“永久保险箱“
arm开发·人工智能·stm32·单片机·fpga开发·开源
poiu12346571 小时前
海同科技可信吗?客观拆解职坐标平台背景与教学体系
人工智能
阿图灵1 小时前
OpenCV 算术运算四件套:NOT/AND/OR 位运算与图像混合
图像处理·人工智能·python·opencv·计算机视觉·位运算
这张生成的图像能检测吗1 小时前
(综述)基于遗传神经网络的不平衡故障诊断技术综述
人工智能·生成对抗网络·故障诊断
我叫张土豆1 小时前
在 OpenClaw Java 对话框输入一句话后,系统是如何运行的?
java·开发语言·人工智能
边吃番茄边敲代码1 小时前
企业智能助手Agent 安全测试,包含Prompt Injection 和越权工具调用
人工智能·python·功能测试·ai·单元测试·prompt·模块测试