天天看點

圖像處理------Mean Shift濾波(邊緣保留的低通濾波)

<a target="_blank" href="http://blog.csdn.net/jia20003/article/details/8214567"></a>

一: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顔色空間轉換可以參考

圖像處理------Mean Shift濾波(邊緣保留的低通濾波)

三:程式效果

圖像處理------Mean Shift濾波(邊緣保留的低通濾波)

濾鏡源代碼:

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&lt;inpixels.length; i++) {  

            int argb = inpixels[i];  

            int r = (argb &gt;&gt; 16) &amp; 0xff;  

            int g = (argb &gt;&gt;  8) &amp; 0xff;  

            int b = (argb) &amp; 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&lt;height; row++) {  

            int ta = 255, tr = 0, tg = 0, tb = 0;  

            for(int col=0; col&lt;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;  

                    icold = ic;  

                    qcold = qc;  

                    float mx = 0;  

                    float my = 0;  

                    float mi = 0;  

                    float mq = 0;  

                    int num=0;  

                    for (int ry=-radius; ry &lt;= radius; ry++) {  

                        int y2 = yc + ry;   

                        if (y2 &gt;= 0 &amp;&amp; y2 &lt; height) {  

                            for (int rx=-radius; rx &lt;= radius; rx++) {  

                                int x2 = xc + rx;   

                                if (x2 &gt;= 0 &amp;&amp; x2 &lt; width) {  

                                    if (ry*ry + rx*rx &lt;= 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 &lt;= dis2) {  

                                            mx += x2;  

                                            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 &gt; 3 &amp;&amp; repetition &lt; 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 &lt;&lt; 24) | (tr &lt;&lt; 16) | (tg &lt;&lt; 8) | tb;  

            }  

        setrgb( dest, 0, 0, width, height, outpixels );  

        return dest;  

    public string tostring() {  

        system.out.println("mean shift filter...");  

        return "meanshiftfilter";  

}  

繼續閱讀