双边滤波原理和实现

这篇具有很好参考价值的文章主要介绍了双边滤波原理和实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

双边滤波原理

         双边滤波(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 memory
		unsigned 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 exchange
		for (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];
			}
		}

		//filtering
		bilateral_filter_ys(image_src_rgb, image_dst_rgb, 5, channels, cols, rows, 50, 50);

		//matrix 2 Mat

		for (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 memory
		unsigned 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 exchange
		for (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);
				
			}
		}

		//filtering

		bilateral_filter_ys1(image_src_gray, image_dst_gray, 5, channels, cols, rows, 50, 50);

		//matrix 2 Mat

		for (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双边滤波结果图做差值产生的。这段代码有点长但是很简单。

双边滤波原理和实现

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

 双边滤波原理和实现文章来源地址https://www.toymoban.com/news/detail-478498.html

到了这里,关于双边滤波原理和实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于FPGA的图像双边滤波实现,包括tb测试文件和MATLAB辅助验证

    目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 双边滤波数学模型 4.2 双边滤波的特性 4.3 FPGA实现架构 5.算法完整程序工程 将FPGA数据导入到matlab对比测试: vivado2019.2 matlab2022a           双边滤波是一种非线性滤波方法,它能够在平滑图像

    2024年01月22日
    浏览(50)
  • 中值滤波,均值滤波,高斯滤波,双边滤波,联合双边滤波介绍

    看GAMES202相关课程发现闫老师讲的太好了,所以记录一下。当然文中涉及的PPT也来自闫老师的课程PPT,欢迎交流。 首先这几种都是空域的滤波方式,用于抑制图像中的噪声。它们采用的原理基本都是通过滤波核 K K K 处理含噪图像 C ~ widetilde{C} C ,得到干净的输出图 C ‾ ove

    2024年02月09日
    浏览(39)
  • OpenCV图像模糊:高斯滤波、双边滤波

    1.高斯滤波原理 图像处理中,高斯滤波主要可以使用两种方法实现。一种是离散化窗口滑窗卷积,另一种方法是通过傅里叶变化。离散化窗口划船卷积时主要利用的是高斯核, 高斯核的大小为奇数 ,因为高斯卷积会在其覆盖区域的中心输出结果。常用的高斯模板有如下几种

    2024年02月07日
    浏览(44)
  • OpenCV 入门教程:中值滤波和双边滤波

    在图像处理和计算机视觉领域,中值滤波和双边滤波是两种常见的滤波方法,用于平滑图像、去除噪声等。 OpenCV 提供了中值滤波和双边滤波的实现函数,使得图像处理更加灵活和高效。本文将以中值滤波和双边滤波为中心,为你介绍使用 OpenCV 进行滤波操作的基本步骤和实例

    2024年02月13日
    浏览(32)
  • opencv-双边滤波

    双边滤波(Bilateral Filter)是非线性滤波中的一种。这是一种结合图像的空间邻近度与像素值相似度的处理办法。在滤波时,该滤波方法同时考虑空间临近信息与颜色相似信息,在滤除噪声、平滑图像的同时,又做到边缘保存。 双边滤波采用了两个高斯滤波的结合。一个负责

    2024年02月06日
    浏览(30)
  • 图像处理:双边滤波算法

    今天主要是回顾一下双边滤波,我曾经在这篇——图像处理:推导五种滤波算法中推导过它,其中包含了我自己写的草稿图。 目录 双边滤波算法原理 (1)空间域核  (2)值域核 理解双边滤波 空域权重​编辑和值域权重​编辑的意义 Opencv实现双边滤波 双边滤波代码实现

    2024年02月02日
    浏览(45)
  • OpenCV-24双边滤波

    双边滤波对于图像的边缘信息能够更好的保存。其原理为一个与 空间距离 相关的高斯函数与一个 灰度距离 相关的高斯函数相乘。 空间距离 :指的是当前点与中心点的欧式距离。空间域的高斯函数及其数学形式为: 其中(xi,yi)为当前点的位置,(xc,yc)为中心点位置,

    2024年01月17日
    浏览(33)
  • OpenCV——双边滤波

    OpenCV——双边滤波由CSDN点云侠原创。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。    双边滤波是一种综合考虑滤波器内图像空域信息和滤波器内图像像素灰度值相似性的滤波算法,可以实现在保留区域信息的基础上实现对噪声的去除、对局

    2024年01月18日
    浏览(67)
  • Opencv之图像滤波:6.双边滤波(cv2.bilateralFilter)

            前面我们介绍的滤波方法都会对图像造成模糊,使得边缘信息变弱或者消失,因此需要一种能够对图像边缘信息进行保留的滤波算法,双边滤波是综合考虑空间信息和色彩信息的滤波方式,在滤波过程中能够有效地保护 图像内的边缘信息。         之前介绍的

    2024年02月05日
    浏览(48)
  • python --opencv图像处理滤波详解(均值滤波、2D 图像卷积、方框滤波、 高斯滤波、中值滤波、双边滤波)

    第一件事情还是先做名词解释,图像平滑到底是个啥? 从字面意思理解貌似图像平滑好像是在说图像滑动。 emmmmmmmmmmmmmmm。。。。 其实半毛钱关系也没有,图像平滑技术通常也被成为图像滤波技术(这个名字看到可能大家会有点感觉)。 每一幅图像都包含某种程度的噪声,

    2024年02月04日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包