图像处理之积分图应用二(快速边缘保留滤波算法)

简介: 图像处理之积分图应用二(快速边缘保留滤波算法)

图像处理之积分图应用二(快速边缘保留滤波算法)

一:基本原理

传统的图像边缘保留滤波算法-如高斯双边模糊、Mean-Shift模糊等计算复杂、效率比较低,虽然有各种手段优化或者快速计算方法,当时算法相对一般码农来说理解起来比较费劲,不是一个的选择,而通过积分图像实现局部均方差的边缘保留模糊算法,计算简单而且可以做到计算量跟半径无关、跟上面提到两种边缘保留滤波(EPF)算法效率高很多。首先局部均方差滤波中计算局部均值的公式如下:

当边缘很弱的时候系数K趋近于0、该点的矫正之后的像素值就接近平均值。而当边缘很强的时候系数K趋近于1、该点的模糊之后的像素值就接近等于输入像素值。上述计算中最中意的是窗口内像素的均值与方差,计算均值可以根据积分图像很容易得到,而计算方差根据一系列的数学推导可以得到如下:

就是说可以根据积分图像通过常量次数的计算得到局部的均值与方差,让这种情况下的滤波变成一个常量时间完成的操作与窗口半径大小无关。

二:算法流程

1. 根据输入的图像计算得到积分图像,参见《图像处理之积分图像算法》

2. 根据输入的半径大小计算窗口内像素均值与方差、计算得到每个像素新的像素值

3. 循环每个个像素,重复第2步计算,得到最终的局部均方差滤波图像

三:代码实现

package com.gloomyfish.ii.demo;
 
import java.awt.image.BufferedImage;
 
/**
 * fast edge preserve filter algorithm base on integral image
 * @author zhigang jia
 * @E-mail:bfnh1998@hotmail.com
 *
 */
public class FastEPFilter extends AbstractImageOptionFilter {
  // 窗口半径大小
  private int xr;
  private int yr;
  private float sigma;
  public FastEPFilter() {
  }
  
  public void setWinsize(int radius) {
    this.xr = radius;
    this.yr = radius;
  }
 
  public float getSigma() {
    return sigma;
  }
 
  public void setSigma(float sigma) {
    this.sigma = sigma;
  }
 
  @Override
  public BufferedImage process(BufferedImage image) {
    long time = System.currentTimeMillis();
    int width = image.getWidth();
    int height = image.getHeight();
    // get image data
    int[] pixels = new int[width * height];
    int[] outPixels = new int[width * height];
    getRGB(image, 0, 0, width, height, pixels);
    int size = (xr * 2 + 1) * (yr * 2 + 1);
    int r = 0, g = 0, b = 0;
    float sigma2 = sigma*sigma;
    
    // per-calculate integral image
    byte[] R = new byte[width*height];
    byte[] G = new byte[width*height];
    byte[] B = new byte[width*height];
    getRGB(width, height, pixels, R, G, B);
    IntIntegralImage rii = new IntIntegralImage();
    rii.setImage(R);
    rii.process(width, height);
    IntIntegralImage gii = new IntIntegralImage();
    gii.setImage(G);
    gii.process(width, height);
    IntIntegralImage bii = new IntIntegralImage();
    bii.setImage(B);
    bii.process(width, height);
    int index = 0;
    
    for (int row = yr; row < height - yr; row++) {
      for (int col = xr; col < width - xr; col++) {
        index = row * width + col;
        r = ((pixels[index] >> 16) & 0xff);
        g = (pixels[index] >> 8) & 0xff;
        b = (pixels[index] & 0xff);
        
        int sr = rii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));
        int sg = gii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));
        int sb = bii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1));
        
        float vr = rii.getBlockSquareSum(col, row, (yr * 2 + 1), (xr * 2 + 1));
        float vg = gii.getBlockSquareSum(col, row, (yr * 2 + 1), (xr * 2 + 1));
        float vb = bii.getBlockSquareSum(col, row, (yr * 2 + 1), (xr * 2 + 1));
        
        // 计算均值
        float mr = sr / size;
        float mg = sg / size;
        float mb = sb / size;
        
        // 计算方差
        float dr = (vr - (sr*sr)/size)/size;
        float dg = (vg - (sg*sg)/size)/size;
        float db = (vb - (sb*sb)/size)/size;
        
        // 计算系数K
        float kr = dr / (dr+sigma2);
        float kg = dg / (dg+sigma2);
        float kb = db / (db+sigma2);
        
        // 得到滤波后的像素值
        r = (int)((1-kr)*mr + kr*r);
        g = (int)((1-kg)*mg + kg*g);
        b = (int)((1-kb)*mb + kb*b);
        
        outPixels[row * width + col] = (0xff << 24) | (clamp(r) << 16) | (clamp(g) << 8) | clamp(b);
      }
    }
    System.out.println("FastEPFilter ->> time duration : " + (System.currentTimeMillis() - time));
    BufferedImage dest = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    setRGB(dest, 0, 0, width, height, outPixels);
    return dest;
  }
  
  /** Returns the red, green and blue planes as 3 byte arrays. */
  public void getRGB(int width, int height, int[] pixels, byte[] R, byte[] G, byte[] B) {
    int c, r, g, b;
    for (int i=0; i < width*height; i++) {
      c = pixels[i];
      r = (c&0xff0000)>>16;
      g = (c&0xff00)>>8;
      b = c&0xff;
      R[i] = (byte)r;
      G[i] = (byte)g;
      B[i] = (byte)b;
    }
  }
 
}

四:运行效果

半径设置为5,即窗口大小为5的时候,调整参数sigma的值即可得到此效果

其实很多磨皮的算法都是基于这个算法实现的,这个才是我想说的重点,

只有耐心看到此处才可以得到正确的答案。



五:参考:


http://imagej.net/Integral_Image_Filters#Variance


http://www.activovision.com/octavi/doku.php?id=integral_images

相关文章
|
1天前
|
算法 前端开发 机器人
一文了解分而治之和动态规则算法在前端中的应用
该文章详细介绍了分而治之策略和动态规划算法在前端开发中的应用,并通过具体的例子和LeetCode题目解析来说明这两种算法的特点及使用场景。
一文了解分而治之和动态规则算法在前端中的应用
|
7天前
|
算法 调度
贪心算法基本概念与应用场景
尽管贪心算法在许多问题中都非常有效,但它并不总是会产生最优解。因此,在应用贪心算法前,重要的是先分析问题是否适合采用贪心策略。一些问题可能需要通过动态规划或回溯等其他算法来解决,以找到确切的全局最优解。
28 1
WK
|
10天前
|
机器学习/深度学习 算法 数据挖掘
PSO算法的应用场景有哪些
粒子群优化算法(PSO)因其实现简单、高效灵活,在众多领域广泛应用。其主要场景包括:神经网络训练、工程设计、电力系统经济调度与配电网络重构、数据挖掘中的聚类与分类、控制工程中的参数整定、机器人路径规划、图像处理、生物信息学及物流配送和交通管理等。PSO能处理复杂优化问题,快速找到全局最优解或近似解,展现出强大的应用潜力。
WK
16 1
|
19天前
|
机器学习/深度学习 算法 Python
群智能算法:深入解读人工水母算法:原理、实现与应用
近年来,受自然界生物行为启发的优化算法备受关注。人工水母算法(AJSA)模拟水母在海洋中寻找食物的行为,是一种新颖的优化技术。本文详细解读其原理及实现步骤,并提供代码示例,帮助读者理解这一算法。在多模态、非线性优化问题中,AJSA表现出色,具有广泛应用前景。
|
1天前
|
算法 前端开发
一文了解贪心算法和回溯算法在前端中的应用
该文章深入讲解了贪心算法与回溯算法的原理及其在前端开发中的具体应用,并通过分析LeetCode题目来展示这两种算法的解题思路与实现方法。
|
26天前
|
机器学习/深度学习 算法 数据挖掘
R语言中的支持向量机(SVM)与K最近邻(KNN)算法实现与应用
【9月更文挑战第2天】无论是支持向量机还是K最近邻算法,都是机器学习中非常重要的分类算法。它们在R语言中的实现相对简单,但各有其优缺点和适用场景。在实际应用中,应根据数据的特性、任务的需求以及计算资源的限制来选择合适的算法。通过不断地实践和探索,我们可以更好地掌握这些算法并应用到实际的数据分析和机器学习任务中。
|
1月前
|
算法 C++
A : DS串应用–KMP算法
这篇文章提供了KMP算法的C++实现,包括计算模式串的next数组和在主串中查找模式串位置的函数,用于演示KMP算法的基本应用。
|
1月前
|
缓存 算法 前端开发
深入理解缓存淘汰策略:LRU和LFU算法的解析与应用
【8月更文挑战第25天】在计算机科学领域,高效管理资源对于提升系统性能至关重要。内存缓存作为一种加速数据读取的有效方法,其管理策略直接影响整体性能。本文重点介绍两种常用的缓存淘汰算法:LRU(最近最少使用)和LFU(最不经常使用)。LRU算法依据数据最近是否被访问来进行淘汰决策;而LFU算法则根据数据的访问频率做出判断。这两种算法各有特点,适用于不同的应用场景。通过深入分析这两种算法的原理、实现方式及适用场景,本文旨在帮助开发者更好地理解缓存管理机制,从而在实际应用中作出更合理的选择,有效提升系统性能和用户体验。
73 1
|
1月前
|
数据采集 搜索推荐 算法
【高手进阶】Java排序算法:从零到精通——揭秘冒泡、快速、归并排序的原理与实战应用,让你的代码效率飙升!
【8月更文挑战第21天】Java排序算法是编程基础的重要部分,在算法设计与分析及实际开发中不可或缺。本文介绍内部排序算法,包括简单的冒泡排序及其逐步优化至高效的快速排序和稳定的归并排序,并提供了每种算法的Java实现示例。此外,还探讨了排序算法在电子商务、搜索引擎和数据分析等领域的广泛应用,帮助读者更好地理解和应用这些算法。
24 0
|
1月前
|
机器学习/深度学习 数据采集 算法
随机森林算法应用
8月更文挑战第20天