图像处理之Mean Shift滤波(边缘保留的低通滤波)

简介: 图像处理之Mean Shift滤波(边缘保留的低通滤波)

一:Mean Shift算法介绍


Mean Shift是一种聚类算法,在数据挖掘,图像提取,视频对象跟踪中都有应用。本文


重要演示Mean Shift算法来实现图像的低通边缘保留滤波效果。其处理以后的图像有点


类似油画一样。Mean Shift算法的输入参数一般有三个:


1.      矩阵半径r,声明大小


2.      像素距离,常见为欧几里德距离或者曼哈顿距离


3.      像素差值value



算法大致的流程如下:


a.      输入像素点P(x, y)


b.      计算该点的像素值pixelv


c.      根据输入的半径r与差值value求出矩阵半径内满足差值像素平均值作为输出像素点值


d.      计算shift与repetition,如果满足条件


e.      继续c ~ d,直到条件不满足退出,得到最终的输出像素值


f.       对输入图像的每个像素重复a ~ e,得到图像输出像素数据


二:色彩空间转换


本文Mean Shift滤波在YIQ颜色空间上完成,关于RGB与YIQ颜色空间转换可以参考


这里:http://en.wikipedia.org/wiki/YIQ我google找来的转换公式截屏:

1353598020_3612.png


三:程序效果

1353598184_8433.png



滤镜源代码:

package com.gloomyfish.filter.study;
 
import java.awt.image.BufferedImage;
 
public class MeanShiftFilter extends AbstractBufferedImageOp {
  
  private int radius;
  private float colorDistance;
  
  public MeanShiftFilter() {
    radius = 3; // default shift radius
    colorDistance = 25; // default color distance
  }
  public int getRadius() {
    return radius;
  }
 
  public void setRadius(int radius) {
    this.radius = radius;
  }
 
  public float getColorDistance() {
    return colorDistance;
  }
 
  public void setColorDistance(float colorDistance) {
    this.colorDistance = colorDistance;
  }
 
  @Override
  public BufferedImage filter(BufferedImage src, BufferedImage dest) {
    int width = src.getWidth();
        int height = src.getHeight();
 
        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);
        
        // convert RGB color space to YIQ color space
        float[][] pixelsf = new float[width*height][3];
        for(int i=0; i<inPixels.length; i++) {
      int argb = inPixels[i];
      int r = (argb >> 16) & 0xff;
      int g = (argb >>  8) & 0xff;
      int b = (argb) & 0xff;
      pixelsf[i][0] = 0.299f  *r + 0.587f *g + 0.114f  *b; // Y
      pixelsf[i][1] = 0.5957f *r - 0.2744f*g - 0.3212f *b; // I
      pixelsf[i][2] = 0.2114f *r - 0.5226f*g + 0.3111f *b; // Q
        }
        
        int index = 0;
        float shift = 0;
        float repetition = 0;
        float radius2 = radius * radius;
        float dis2 = colorDistance * colorDistance;
        for(int row=0; row<height; row++) {
          int ta = 255, tr = 0, tg = 0, tb = 0;
          for(int col=0; col<width; col++) {
        int xc = col;
        int yc = row;
        int xcOld, ycOld;
        float YcOld, IcOld, QcOld;
        index = row*width + col;
        float[] yiq = pixelsf[index];
        float Yc = yiq[0];
        float Ic = yiq[1];
        float Qc = yiq[2];
 
        repetition = 0;
        do {
          xcOld = xc;
          ycOld = yc;
          YcOld = Yc;
          IcOld = Ic;
          QcOld = Qc;
 
          float mx = 0;
          float my = 0;
          float mY = 0;
          float mI = 0;
          float mQ = 0;
          int num=0;
 
          for (int ry=-radius; ry <= radius; ry++) {
            int y2 = yc + ry; 
            if (y2 >= 0 && y2 < height) {
              for (int rx=-radius; rx <= radius; rx++) {
                int x2 = xc + rx; 
                if (x2 >= 0 && x2 < width) {
                  if (ry*ry + rx*rx <= radius2) {
                    yiq = pixelsf[y2*width + x2];
 
                    float Y2 = yiq[0];
                    float I2 = yiq[1];
                    float Q2 = yiq[2];
 
                    float dY = Yc - Y2;
                    float dI = Ic - I2;
                    float dQ = Qc - Q2;
 
                    if (dY*dY+dI*dI+dQ*dQ <= dis2) {
                      mx += x2;
                      my += y2;
                      mY += Y2;
                      mI += I2;
                      mQ += Q2;
                      num++;
                    }
                  }
                }
              }
            }
          }
          float num_ = 1f/num;
          Yc = mY*num_;
          Ic = mI*num_;
          Qc = mQ*num_;
          xc = (int) (mx*num_+0.5);
          yc = (int) (my*num_+0.5);
          int dx = xc-xcOld;
          int dy = yc-ycOld;
          float dY = Yc-YcOld;
          float dI = Ic-IcOld;
          float dQ = Qc-QcOld;
 
          shift = dx*dx+dy*dy+dY*dY+dI*dI+dQ*dQ; 
          repetition++;
        }
        while (shift > 3 && repetition < 100);
        tr = (int)(Yc + 0.9563f*Ic + 0.6210f*Qc);
        tg = (int)(Yc - 0.2721f*Ic - 0.6473f*Qc);
        tb = (int)(Yc - 1.1070f*Ic + 1.7046f*Qc);     
        outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;
          }
        }
        setRGB( dest, 0, 0, width, height, outPixels );
        return dest;
  }
  
  public String toString() {
    System.out.println("Mean Shift Filter...");
    return "MeanShiftFilter";
  }
 
}

转载请注明

相关文章
|
23天前
|
算法 计算机视觉
图像处理之基于像素的图像混合
图像处理之基于像素的图像混合
12 1
|
22天前
|
资源调度 算法 计算机视觉
图像处理之积分图应用二(快速边缘保留滤波算法)
图像处理之积分图应用二(快速边缘保留滤波算法)
12 0
|
1月前
|
计算机视觉 索引
【OpenCV】—ROI区域图像叠加&图像混合
【OpenCV】—ROI区域图像叠加&图像混合
|
11月前
|
传感器
ENVI: 如何进行图像的自动配准?
ENVI: 如何进行图像的自动配准?
365 0
|
11月前
ENVI Classic: 如何进行波段合成、矢量栅格叠加显示、窗口链接、图像格式转换、头文件编辑、重采样等(详细)2
ENVI Classic: 如何进行波段合成、矢量栅格叠加显示、窗口链接、图像格式转换、头文件编辑、重采样等(详细)
327 0
|
9月前
|
机器学习/深度学习 传感器 算法
【光学】基于matlab模拟参考光栅和变形光栅折叠相位
【光学】基于matlab模拟参考光栅和变形光栅折叠相位
|
9月前
|
机器学习/深度学习 传感器 算法
【 表面重建】径向剪切干涉仪 (RSI) 附matlab代码
【 表面重建】径向剪切干涉仪 (RSI) 附matlab代码
|
10月前
|
传感器 数据采集 算法
【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)
【使用 DSP 滤波器加速速度和位移】使用信号处理算法过滤加速度数据并将其转换为速度和位移研究(Matlab代码实现)
|
11月前
|
传感器 编解码
ENVI Classic: 如何进行波段合成、矢量栅格叠加显示、窗口链接、图像格式转换、头文件编辑、重采样等(详细)3
ENVI Classic: 如何进行波段合成、矢量栅格叠加显示、窗口链接、图像格式转换、头文件编辑、重采样等(详细)
232 0
|
11月前
|
传感器 编解码
ENVI Classic: 如何进行波段合成、矢量栅格叠加显示、窗口链接、图像格式转换、头文件编辑、重采样等(详细)1
ENVI Classic: 如何进行波段合成、矢量栅格叠加显示、窗口链接、图像格式转换、头文件编辑、重采样等(详细)
1025 0