双边滤波原理和实现

article/2025/10/25 23:00:13

双边滤波原理

         双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。

双边滤波器之所以能够做到在平滑去噪的同时还能够很好的保存边缘(Edge Preserve),是由于其滤波器的核由两个函数生成:

 

 

 

 

 

 一个函数由像素欧式距离决定滤波器模板的系数,另一个函数由像素的灰度差值决定滤波器的系数

 众所周知,高斯滤波器它仅仅是欧式距离进行滤波,这种对于边缘处理不是很好,而双边滤波结合了高斯滤波以及均值滤波的特点。很明显他效果要更好。

上述三个公式就是双边滤波的全部了,我给大家简单介绍一下他的参数含义,就很容易明白他到底是如何实现的了。

首先第一个公式,很明显他是一个指数形式下,某两个点之间的差值的平方,如下图:因为图像的基础单位是像素,所以每一个坐标中就存储着一个值或者三个值(也就是灰度图像和彩色图像的区别)。(k,l)就是模板中心坐标,比如下图(0,0)就是这个3*3模块窗口的中心,(i,j)就是模板窗口其他点,这里的σ是高斯函数的标准差。补充一句,这里面求的是像素差值

(-1,-1)(0,-1)
(0,0)(1,0)
(1,1)

第二个公式是距离模板。同样(k,l)是模板窗口中心点坐标,(i,j)是其他点坐标,这里求得是距离的平方。

第一个公式和第二个公式相乘就得到了我们最重要的权重。

 如上式,G(i,j)就是最终输出图像的每个位置的像素值。

双边滤波器的实现

 我们通常实现双边滤波器,其实只要调用opencv的API就可,里面帮我们封装好了函数。

std::string filePath_1 = "tmp.jpg";cv::Mat src0 = cv::imread(filePath_1, 0);
cv::Mat dst;bilateralFilter(src0, dst, 5, 50, 50);

实现起来还是蛮简单的,但是既然我们了解了它的原理不妨自己写一下试试:

我这里使用的是c语言写的 ,最后封装静态库。

代码如下: 

void bilateral_filter_ys(unsigned int* src, unsigned int* dst, int ksize, int channels, int cols, int rows, double space_sigma, double color_sigma)
{//Assert(channels == 1 || channels == 3);//这部分是定义灰度值模板系数的。double space_coeff = -0.5 / (space_sigma * space_sigma);double color_coeff = -0.5 / (color_sigma * color_sigma);int radius = ksize / 2;double color_weight[256 * 3] = { 0 };double space_weight[49] = { 0 };//本文使用的方法是查表法,首先将距离模板和像素模板写入数组。之后再读取这些数据。这样可以节约时间成本,不需要定义较大的数组for (int i = 0; i < channels * 256; i++)//像素模板{color_weight[i] = exp(i * i * color_coeff);}int L = 0;for (int i = -radius; i < radius; i++)//距离模板{for (int j = -radius; j < radius; j++){double distance = -sqrt(i * i + j * j);space_weight[L] = exp(distance * distance * space_coeff);L++;}}//开始滤波,滤波部分if (channels == 3) {for (int i = radius; i < rows - radius; i++){for (int j = radius; j < cols - radius; j++){double sumb = 0, sumg = 0, sumr = 0, wsum = 0;int b0 = src[(i*cols + j) * 3 + 0];int g0 = src[(i*cols + j) * 3 + 1];int r0 = src[(i*cols + j) * 3 + 2];for (int p = i - radius; p <= i + radius; p++){for (int q = j - radius; q <= j + radius; q++){int b = src[(p * cols + q) * 3 + 0];int g = src[(p * cols + q) * 3 + 1];int r = src[(p * cols + q) * 3 + 2];double space_w = space_weight[(p + radius - i) * ksize + (q + radius - j)];double color_w = color_weight[abs(b - b0) + abs(g - g0) + abs(r - r0)];double weight = space_w * color_w;sumb += b * weight;sumg += g * weight;sumr += r * weight;wsum += weight;}}dst[(i * cols + j) * 3 + 0] = round(sumb/ wsum);//像素要取整dst[(i * cols + j) * 3 + 1] = round(sumg / wsum);dst[(i * cols + j) * 3 + 2] = round(sumr / wsum);}}}}

上述是一个三通道双线性滤波,我实现之后和opencv自带的对比。下述是实现过程,第一张代码图主要是转换成Mat类型,所以看着可能有点复杂,但其实只是在转换而已。

第二张是主函数的实现

void S(cv::Mat image_src,cv::Mat image_dst){//cv::copyMakeBorder(image_src, image_src, 2, 2, 2, 2, cv::BorderTypes::BORDER_REFLECT);int cols = image_src.cols;int rows = image_src.rows;int channels = image_src.channels();if (channels == 3){//define matrix space memoryunsigned int* image_src_rgb = (unsigned int*)malloc(rows * cols * sizeof(unsigned int) * 3);unsigned int* image_dst_rgb = (unsigned int*)malloc(rows * cols * sizeof(unsigned int) * 3);//value exchangefor (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){image_src_rgb[(i * cols + j) * 3 + 0] = image_src.at<cv::Vec3b>(i, j)[2];image_src_rgb[(i * cols + j) * 3 + 1] = image_src.at<cv::Vec3b>(i, j)[1];image_src_rgb[(i * cols + j) * 3 + 2] = image_src.at<cv::Vec3b>(i, j)[0];}}//filteringbilateral_filter_ys(image_src_rgb, image_dst_rgb, 5, channels, cols, rows, 50, 50);//matrix 2 Matfor (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){image_dst.at<cv::Vec3b>(i, j)[2] = image_dst_rgb[(i * cols + j) * 3 + 0];image_dst.at<cv::Vec3b>(i, j)[1] = image_dst_rgb[(i * cols + j) * 3 + 1];image_dst.at<cv::Vec3b>(i, j)[0] = image_dst_rgb[(i * cols + j) * 3 + 2];}}}if (channels == 1) {//define matrix space memoryunsigned char* image_src_gray = (unsigned char*)malloc(rows * cols * sizeof(unsigned char) );unsigned char* image_dst_gray= (unsigned char*)malloc(rows * cols * sizeof(unsigned char));//value exchangefor (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){image_src_gray[i*cols + j] = image_src.at<uchar>(i,j);}}//filteringbilateral_filter_ys1(image_src_gray, image_dst_gray, 5, channels, cols, rows, 50, 50);//matrix 2 Matfor (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){image_dst.at<uchar>(i,j) = image_dst_gray[i * cols + j];}}}}
int main()
{std::string filePath_1 = "tmp.jpg";cv::Mat src0 = cv::imread(filePath_1, 1);cv::Mat dst1(src0.size(), src0.type());S(src0,dst1);cv::Mat dst;bilateralFilter(src0, dst, 5, 50, 50);}

 图像使用的是这张图。

在经过像素值的对比,得到以下结果。这是与opencv双边滤波结果图做差值产生的。这段代码有点长但是很简单。

单通道说实话实现效果要差一些,这里我就不放了代码了,看一下结果吧 

 


http://chatgpt.dhexx.cn/article/6XUqx88H.shtml

相关文章

双边滤波

1 双边滤波简介 双边滤波&#xff08;Bilateral filter&#xff09;是一种非线性的滤波方法&#xff0c;是结合图像的空间邻近度和像素值相似度的一种折衷处理&#xff0c;同时考虑空域信息和灰度相似性&#xff0c;达到保边去噪的目的。具有简单、非迭代、局部的特点。 双边滤…

数字图像处理(九)双边滤波

文章目录 一、何为双边滤波&#xff1f;二、为什么要使用双边滤波&#xff1f;三、双边滤波原理1.空间域核2.值域核3.模板相乘 四、 w d w_d wd​和 w r w_r wr​和 σ \sigma σ的理解五、C代码实现1.opencv中Mat的一点小知识2.关于边界的处理3.双边滤波代码 一、何为双边滤波…

双边滤波(Bilateral Filtering)

双边滤波&#xff08;Bilateral Filtering&#xff09; 1、基本思路 双边滤波&#xff08;Bilateral Filtering&#xff09;的基本思路是同时考虑像素点的空域信息和值域信息。即先根据像素值对要用来进行滤波的邻域做一个分割或分类&#xff0c;再给该点所属的类别相对较高的…

三种经典图像滤波方法介绍——双边滤波(Bilateral filter)、导向滤波(Guided Fliter)、滚动导向滤波(RollingGuidedFilter)

文章目录 一、前言二、双边滤波(Bilateral filter)2.1 双边滤波的理论介绍及公式推导2.2 双边滤波的matlab程序实现 三、导向滤波(Guided Fliter)3.1 导向滤波的理论介绍及公式推导3.2 导向滤波matlab代码实现 四、滚动导向滤波(RollingGuidedFilter)4.1 滚动导向滤波的理论介绍…

图像处理:双边滤波算法

今天主要是回顾一下双边滤波&#xff0c;我曾经在这篇——图像处理&#xff1a;推导五种滤波算法中推导过它&#xff0c;其中包含了我自己写的草稿图。 目录 双边滤波算法原理 &#xff08;1&#xff09;空间域核 &#xff08;2&#xff09;值域核 理解双边滤波 空域权重​…

Bilateral Filters(双边滤波算法)的超简单原理,学不会你打我。

摘要&#xff1a; 双边滤波(Bilateral Filters)是非常常用的一种滤波&#xff0c;它可以达到保持边缘、降噪平滑的效果。和其他滤波原理一样&#xff0c;双边滤波也是采用加权平均的方法&#xff0c;用周边像素亮度值的加权平均代表某个像素的强度&#xff0c;所用的加权平均基…

jQuery源码分析理解

1&#xff1a; 首先我们先来看一下jquery代码的整体结构 代码从16行开始为真正的jquery源码&#xff0c;我们看到Jquery源码第一个()中是定义了一个匿名function( window, undefined ) {}&#xff1b;接着末尾有个(window)&#xff0c;就表示执行这个匿名function&#xff0c;…

jQuery源码分析(一)

jQuery源码分析&#xff08;一&#xff09; 我们知道在jQuery中在使用选择器或者给元素绑定事件的时候都是通过$来操作的。那么基于JavaScript面向对象的思想&#xff0c;我们可以把jQuery看做一个函数或者对象&#xff0c;它里边存储了大量的方法&#xff0c;是一个类库。 $代…

jQuery源码阅读(一)---jQuery源码整体架构

之前用jQuery库写了两个小例子&#xff08;结合Apache、PHP实现的简易聊天室以及音乐播放器&#xff09;&#xff0c;详见我的上两篇博客jQuery aJax技术以及PHP实现简单聊天室、 利用jQuery实现音乐播放器。为了更加深入了解jQuery库的架构以及巩固原生JS的基础和深度&#xf…

jquery源码解析

(function(a,b){})() JQuery源码的开头 (function(a,b){})(window)通常(function(){})()用来封装一些私有成员或者公共成员的导出。 1. 定义一个匿名函数&#xff0c;创建了一个“私有”的命名空间&#xff0c;该命名空间的变量和方法&#xff0c;不会破坏全局的命名空间。确…

jQuery源码下载和编译

下载 git clone https://github.com/jquery/jquery.git编译 下载完成后&#xff0c;进入jquery文件夹&#xff0c;运行如下命令&#xff1a; npm run build最后全部编译完成&#xff0c;生成的文件在目录dist文件夹下&#xff1a; 有兴趣的就可以开始研究源码了。

jQuery源码阅读

1. 立即执行函数 简化后的代码就是这样 (function(global, factory) {... })(window, function () {}); Q&#xff1a;采用立即执行函数的好处是什么呢&#xff1f; A: 通过定义一个匿名函数&#xff0c;创建了一个新的函数作用域&#xff0c;相当于创建了一个私有的命名空…

jQuery -- jQuery源码(一):核心功能

一、jQuery无new构建实例 1、$就是jQuery的别称 可以在$和jQuery对象挂在在window中&#xff0c;实现全局引用。 给Windows对象扩展一个$的属性&#xff0c;让它拿到jQuery构造函数的引用 可以用$访问到jQuery的构造函数 // jQuery.js (function(root) {var jQuery functio…

制作一个游戏编辑器玩玩(1)

今天准备着手例用空闲时间制作一个游戏编辑器&#xff0c;一是因为这些年来积累了不少的算法和制作经验&#xff0c;它们是分散的&#xff0c;零乱的&#xff0c;想搞一次规整。二是自己一起想做一个简单点的游戏编辑器&#xff0c;可以让自己的小朋友把自己的想法在上面实现&a…

游戏策划的软件与工具

游戏策划的软件与工具 UXplayer https://www.jianshu.com/p/ceddde705933 gongjutitle.png 本文修改自前公司的一份交接文档&#xff0c;分享了工作中一些常用的软件。 Axure 界面示意图/流程图制作软件 大前提&#xff1a;Windows系统、无法直连外网 Mac系统的话&#xff0c;…

Tiled游戏地图编辑器

下载 软件是免费的,直接官网下载就好了 下载链接:https://www.mapeditor.org/ 新建地图 左上角 >> 文件 >> 创建新地图 快捷键:ctrln 根据你的需求设置地图大小 导入素材新建图块集 左上角 >> 文件 >> 新图块 新建你的图集文件.png 如果你已…

Android游戏开发之地图编辑器的使用以及绘制地图 (四)

雨松MOMO带你走进游戏开发的世界之地图编辑器的使用以及绘制地图 雨松MOMO原创文章如转载&#xff0c;请注明&#xff1a;转载至我的独立域名博客雨松MOMO程序研究院&#xff0c;原文地址:http://www.xuanyusong.com/archives/211 Mappy中文地图编辑器的使用说明下载地址&#…

编辑器

问题描述 你现在要实现一个针对于数字序列的编辑器。 初始的时候&#xff0c;序列是空的。 在之后&#xff0c;有以下五种操作&#xff1a; I x 在光标之后插入x D 删除光标之前的数字 L 将光标向左移动&#xff0c;如果已经在最左&#xff0c;则不移动 R 将光标向右移动&#…

代码编辑器

文章来源&#xff1a;几款非常优秀且常用的代码编辑器 ... VS CodeSource InsightVimUltraEditeclipseUnderstandAtomSublime Text 对于软件开发人员&#xff0c;代码编辑器好用与否直接影响代码编辑的效率。软件开发&#xff0c;基本上都有集成开发环境&#xff08;IDE&#x…

Unity的编辑器

1大部分人Unity编辑器是vistual 2.变量 2.1新建C#文件 鼠标点击Assets-->再点击create-->点击C#Sprite 2.2先用鼠标点击游戏物体(Cube)将c#文件拖拽到Inspector下&#xff0c;双击C#文件可以进入编写代码 2.3变量 public 变量类型 变量; //公有属性在Inspector下可…