图像处理之双边滤波效果(Bilateral Filtering for Gray and Color Image)

本文主要是介绍图像处理之双边滤波效果(Bilateral Filtering for Gray and Color Image),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

- created by gloomyfish

图像处理之双边滤波效果(Bilateral Filtering for Gray and Color Image)

基本介绍:

普通的时空域的低通滤波器,在像素空间完成滤波以后,导致图像的边缘部分也变得不那么明显,

整张图像都变得同样的模糊,图像边缘细节丢失。双边滤波器(ABilateral Filter)可以很好的保

留边缘的同时消除噪声。双边滤波器能做到这些原因在于它不像普通的高斯/卷积低通滤波,只考

虑了位置对中心像素的影响,它还考虑了卷积核中像素与中心像素之间相似程度的影响,根据位置

影响与像素值之间的相似程度生成两个不同的权重表(WeightTable),在计算中心像素的时候加以

考虑这两个权重,从而实现双边低通滤波。据说AdobePhotoshop的高斯磨皮功能就是应用了

双边低通滤波算法实现。






程序效果:


看我们的美女lena应用双边滤镜之后



程序关键代码解释:

建立距离高斯权重表(Weight Table)如下:

private void buildDistanceWeightTable() {  int size = 2 * radius + 1;  cWeightTable = new double[size][size];  for(int semirow = -radius; semirow <= radius; semirow++) {  for(int semicol = - radius; semicol <= radius; semicol++) {  // calculate Euclidean distance between center point and close pixels  double delta = Math.sqrt(semirow * semirow + semicol * semicol)/ds;  double deltaDelta = delta * delta;  cWeightTable[semirow+radius][semicol+radius] = Math.exp(deltaDelta * factor);  }  }  
}  




程序效果:


看我们的美女lena应用双边滤镜之后



程序关键代码解释:

建立距离高斯权重表(Weight Table)如下:


建立RGB值像素度高斯权重代码如下:
private void buildSimilarityWeightTable() {  sWeightTable = new double[256]; // since the color scope is 0 ~ 255  for(int i=0; i<256; i++) {  double delta = Math.sqrt(i * i ) / rs;  double deltaDelta = delta * delta;  sWeightTable[i] = Math.exp(deltaDelta * factor);  }  
}  




程序效果:


看我们的美女lena应用双边滤镜之后



程序关键代码解释:

建立距离高斯权重表(Weight Table)如下:

private void buildDistanceWeightTable() {  int size = 2 * radius + 1;  cWeightTable = new double[size][size];  for(int semirow = -radius; semirow <= radius; semirow++) {  for(int semicol = - radius; semicol <= radius; semicol++) {  // calculate Euclidean distance between center point and close pixels  double delta = Math.sqrt(semirow * semirow + semicol * semicol)/ds;  double deltaDelta = delta * delta;  cWeightTable[semirow+radius][semicol+radius] = Math.exp(deltaDelta * factor);  }  }  
}  

完成权重和计算与像素×权重和计算代码如下

for(int semirow = -radius; semirow <= radius; semirow++) {  for(int semicol = - radius; semicol <= radius; semicol++) {  if((row + semirow) >= 0 && (row + semirow) < height) {  rowOffset = row + semirow;  } else {  rowOffset = 0;  }  if((semicol + col) >= 0 && (semicol + col) < width) {  colOffset = col + semicol;  } else {  colOffset = 0;  }  index2 = rowOffset * width + colOffset;  ta2 = (inPixels[index2] >> 24) & 0xff;  tr2 = (inPixels[index2] >> 16) & 0xff;  tg2 = (inPixels[index2] >> 8) & 0xff;  tb2 = inPixels[index2] & 0xff;  csRedWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tr2 - tr))];  csGreenWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tg2 - tg))];  csBlueWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tb2 - tb))];  csSumRedWeight += csRedWeight;  csSumGreenWeight += csGreenWeight;  csSumBlueWeight += csBlueWeight;  redSum += (csRedWeight * (double)tr2);  greenSum += (csGreenWeight * (double)tg2);  blueSum += (csBlueWeight * (double)tb2);  }  
}  

完成归一化,得到输出像素点RGB值得代码如下:

tr = (int)Math.floor(redSum / csSumRedWeight);  
tg = (int)Math.floor(greenSum / csSumGreenWeight);  
tb = (int)Math.floor(blueSum / csSumBlueWeight);  
outPixels[index] = (ta << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);  

关于什么卷积滤波,请参考:

http://blog.csdn.net/jia20003/article/details/7038938

关于高斯模糊算法,请参考:
http://blog.csdn.net/jia20003/article/details/7234741


最后想说,不给出源代码的博文不是好博文,基于Java完成的双边滤波速度有点慢

可以自己优化,双边滤镜完全源代码如下:

package com.gloomyfish.blurring.study;  
/** *  A simple and important case of bilateral filtering is shift-invariant Gaussian filtering *  refer to - http://graphics.ucsd.edu/~iman/Denoising/ *  refer to - http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html *  thanks to cyber */  
import java.awt.image.BufferedImage;  public class BilateralFilter extends AbstractBufferedImageOp {  private final static double factor = -0.5d;  private double ds; // distance sigma  private double rs; // range sigma  private int radius; // half length of Gaussian kernel Adobe Photoshop   private double[][] cWeightTable;  private double[] sWeightTable;  private int width;  private int height;  public BilateralFilter() {  this.ds = 1.0f;  this.rs = 1.0f;  }  private void buildDistanceWeightTable() {  int size = 2 * radius + 1;  cWeightTable = new double[size][size];  for(int semirow = -radius; semirow <= radius; semirow++) {  for(int semicol = - radius; semicol <= radius; semicol++) {  // calculate Euclidean distance between center point and close pixels  double delta = Math.sqrt(semirow * semirow + semicol * semicol)/ds;  double deltaDelta = delta * delta;  cWeightTable[semirow+radius][semicol+radius] = Math.exp(deltaDelta * factor);  }  }  }  /** * for gray image * @param row * @param col * @param inPixels */  private void buildSimilarityWeightTable() {  sWeightTable = new double[256]; // since the color scope is 0 ~ 255  for(int i=0; i<256; i++) {  double delta = Math.sqrt(i * i ) / rs;  double deltaDelta = delta * delta;  sWeightTable[i] = Math.exp(deltaDelta * factor);  }  }  public void setDistanceSigma(double ds) {  this.ds = ds;  }  public void setRangeSigma(double rs) {  this.rs = rs;  }  @Override  public BufferedImage filter(BufferedImage src, BufferedImage dest) {  width = src.getWidth();  height = src.getHeight();  //int sigmaMax = (int)Math.max(ds, rs);  //radius = (int)Math.ceil(2 * sigmaMax);  radius = (int)Math.max(ds, rs);  buildDistanceWeightTable();  buildSimilarityWeightTable();  if ( dest == null )  dest = createCompatibleDestImage( src, null );  int[] inPixels = new int[width*height];  int[] outPixels = new int[width*height];  getRGB( src, 0, 0, width, height, inPixels );  int index = 0;  double redSum = 0, greenSum = 0, blueSum = 0;  double csRedWeight = 0, csGreenWeight = 0, csBlueWeight = 0;  double csSumRedWeight = 0, csSumGreenWeight = 0, csSumBlueWeight = 0;  for(int row=0; row<height; row++) {  int ta = 0, tr = 0, tg = 0, tb = 0;  for(int col=0; col<width; col++) {  index = row * width + col;  ta = (inPixels[index] >> 24) & 0xff;  tr = (inPixels[index] >> 16) & 0xff;  tg = (inPixels[index] >> 8) & 0xff;  tb = inPixels[index] & 0xff;  int rowOffset = 0, colOffset = 0;  int index2 = 0;  int ta2 = 0, tr2 = 0, tg2 = 0, tb2 = 0;  for(int semirow = -radius; semirow <= radius; semirow++) {  for(int semicol = - radius; semicol <= radius; semicol++) {  if((row + semirow) >= 0 && (row + semirow) < height) {  rowOffset = row + semirow;  } else {  rowOffset = 0;  }  if((semicol + col) >= 0 && (semicol + col) < width) {  colOffset = col + semicol;  } else {  colOffset = 0;  }  index2 = rowOffset * width + colOffset;  ta2 = (inPixels[index2] >> 24) & 0xff;  tr2 = (inPixels[index2] >> 16) & 0xff;  tg2 = (inPixels[index2] >> 8) & 0xff;  tb2 = inPixels[index2] & 0xff;  csRedWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tr2 - tr))];  csGreenWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tg2 - tg))];  csBlueWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tb2 - tb))];  csSumRedWeight += csRedWeight;  csSumGreenWeight += csGreenWeight;  csSumBlueWeight += csBlueWeight;  redSum += (csRedWeight * (double)tr2);  greenSum += (csGreenWeight * (double)tg2);  blueSum += (csBlueWeight * (double)tb2);  }  }  tr = (int)Math.floor(redSum / csSumRedWeight);  tg = (int)Math.floor(greenSum / csSumGreenWeight);  tb = (int)Math.floor(blueSum / csSumBlueWeight);  outPixels[index] = (ta << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);  // clean value for next time...  redSum = greenSum = blueSum = 0;  csRedWeight = csGreenWeight = csBlueWeight = 0;  csSumRedWeight = csSumGreenWeight = csSumBlueWeight = 0;  }  }  setRGB( dest, 0, 0, width, height, outPixels );  return dest;  }  public static int clamp(int p) {  return p < 0 ? 0 : ((p > 255) ? 255 : p);  }  public static void main(String[] args) {  BilateralFilter bf = new BilateralFilter();  bf.buildSimilarityWeightTable();  }  
}  



这篇关于图像处理之双边滤波效果(Bilateral Filtering for Gray and Color Image)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1055563

相关文章

Open3D 基于法线的双边滤波

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 输入参数: 输出参数: 参数影响: 2.2完整代码 三、实现效果 3.1原始点云 3.2滤波后点云 Open3D点云算法汇总及实战案例汇总的目录地址: Open3D点云算法与点云深度学习案例汇总(长期更新)-CSDN博客 一、概述         基于法线的双边

防近视护眼台灯什么牌子好?五款防近视效果好的护眼台灯推荐

在家里,灯具是属于离不开的家具,每个大大小小的地方都需要的照亮,所以一盏好灯是必不可少的,每个发挥着作用。而护眼台灯就起了一个保护眼睛,预防近视的作用。可以保护我们在学习,阅读的时候提供一个合适的光线环境,保护我们的眼睛。防近视护眼台灯什么牌子好?那我们怎么选择一个优秀的护眼台灯也是很重要,才能起到最大的护眼效果。下面五款防近视效果好的护眼台灯推荐: 一:六个推荐防近视效果好的护眼台灯的

6.4双边滤波

目录 实验原理 示例代码1 运行结果1 实验代码2 运行结果2 实验原理 双边滤波(Bilateral Filtering)是一种非线性滤波技术,用于图像处理中去除噪声,同时保留边缘和细节。这种滤波器结合了空间邻近性和像素值相似性的双重加权,从而能够在去噪(平滑图像)的同时保留图像的边缘细节。双边滤波器能够在的同时,保持边缘清晰,因此非常适合用于去除噪声和保持图像特征。在Op

lvgl8.3.6 控件垂直布局 label控件在image控件的下方显示

在使用 LVGL 8.3.6 创建一个垂直布局,其中 label 控件位于 image 控件下方,你可以使用 lv_obj_set_flex_flow 来设置布局为垂直,并确保 label 控件在 image 控件后添加。这里是如何步骤性地实现它的一个基本示例: 创建父容器:首先创建一个容器对象,该对象将作为布局的基础。设置容器为垂直布局:使用 lv_obj_set_flex_flow 设置容器

三色标记(Tri-color marking)

维基百科部分 原文 https://en.wikipedia.org/wiki/Tracing_garbage_collection#TRI-COLOR Because of these performance problems, most modern tracing garbage collectors implement some variant of the tri-color ma

参会邀请 | 第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)

第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)将于2024年9月13日-15日在中国张家口召开。 MVIPIT 2024聚焦机器视觉、图像处理与影像技术,旨在为专家、学者和研究人员提供一个国际平台,分享研究成果,讨论问题和挑战,探索前沿技术。诚邀高校、科研院所、企业等有关方面的专家学者参加会议。 9月13日(周五):签到日 9月14日(周六):会议日 9月15日(周日

【Godot4.3】多边形的斜线填充效果基础实现

概述 图案(Pattern)填充是一个非常常见的效果。其中又以斜线填充最为简单。本篇就探讨在Godot4.3中如何使用Geometry2D和CanvasItem的绘图函数实现斜线填充效果。 基础思路 Geometry2D类提供了多边形和多边形以及多边形与折线的布尔运算。按照自然的思路,多边形的斜线填充应该属于“多边形与折线的布尔运算”范畴。 第一个问题是如何获得斜线,这条斜线应该满足什么样

UniApp实现漂亮的音乐歌词滚动播放效果

在现代的音乐播放应用中,歌词的展示和滚动播放已经成为了一个非常常见的功能。今天,我们将通过UniApp来实现一个漂亮的歌词滚动播放功能。我们将使用UniApp提供的组件和API来完成这个任务。 页面结构 在页面的模板部分,我们需要创建一个音频播放器和歌词展示区域。使用<scroll-view>组件来实现歌词的滚动效果。 <template><view class="audio-co

6.3中值滤波

目录 实验原理 示例代码1 运行结果1 示例代码2 运行结果2 实验原理 中值滤波(Median Filtering)是一种非线性滤波技术,常用于图像处理中去除噪声,特别是在保留边缘的同时减少椒盐噪声(salt-and-pepper noise)。OpenCV中的cv::medianBlur函数可以实现中值滤波。 函数原型 void medianBlur( InputAr