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;
}
相关推荐
byte轻骑兵4 分钟前
【BlueZ】 log 模块:日志系统的实现与自定义日志输出配置
linux·人工智能·bluez·电脑蓝牙·嵌入式蓝牙
AI码农小姐姐20 分钟前
AI漫剧推文短视频动态镜头实现:FFmpeg zoompan 与 Ken Burns 效果实践
人工智能·音视频·ai工具·ai漫剧
技灵AI27 分钟前
ChatGPT Images 2.5 深度解读:延迟减半、Sketch 草图与 Flare/Sunburst 双模型 API
人工智能·gpt·aigc·音视频·images2.5
Geek-Chow30 分钟前
12. 完整重演:一句话请求的完整旅程 + 动手练习
人工智能
m0_7345717630 分钟前
深入理解人工智能chatGPT 外部工具与知识增强层 (Tools & RAG Layer)
人工智能·chatgpt
智能运维指南32 分钟前
2026年企业自动化运维平台选型:四类架构的差异与决策逻辑
运维·人工智能·嘉为蓝鲸
user_admin_god33 分钟前
第 01 篇:OpenAI 兼容 API 初探 —— 用 curl 跑通第一次对话
java·人工智能·spring boot·语言模型·devops
梦帮科技34 分钟前
RNS 代币架构:ERC20 五件套扩展与六钱包分配
人工智能·sql·区块链·database·合成复用原则·加密货币
林澈在路上41 分钟前
游戏场景背景音乐定制AI软件哪款好 2026对比推荐
大数据·人工智能·aigc·音视频
xxwxx__1 小时前
C++ STL set 与 map 全套详解:关联式容器、红黑树底层、代码坑点、刷题实战
数据结构·c++