天天看點

圖像處理------特殊灰階算法技巧

介紹幾種特殊的灰階算法濾鏡,将彩色圖像轉換為灰階圖像。其中涉及到的有基于門檻值的圖

像二值化,弗洛伊德.斯坦德伯格抖動算法,基于門檻值的部分灰階化

基礎知識- 怎麼把rgb轉換為單色的[0 ~256]之間的灰階,最常用的轉換公式如下:

gray = 0.299 * red + 0.587 * green + 0.114 * blue;

1.       基于像素平均值的圖像門檻值二值化算法:

處理流程:

a.      首先将彩色圖像轉換為灰階圖像

b.      計算灰階圖像的算術平均值– m

c.      以m為門檻值,完成對灰階圖二值化( 大于門檻值m,像素點指派為白色,否則指派為黑

色)

圖像效果:

圖像處理------特殊灰階算法技巧

關鍵代碼:

public bufferedimage filter(bufferedimage src, bufferedimage dest) {  

    int width = src.getwidth();  

       int height = src.getheight();  

       if ( dest == null )  

           dest = createcompatibledestimage( src, null );  

       src = super.filter(src, dest);  

       int[] inpixels = new int[width*height];  

       int[] outpixels = new int[width*height];  

       getrgb(src, 0, 0, width, height, inpixels );  

       // calculate means of pixel    

       int index = 0;    

       double redsum = 0, greensum = 0, bluesum = 0;    

       double total = height * width;    

       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;    

               redsum += tr;    

               greensum += tg;    

               bluesum +=tb;    

           }    

       }  

       int means = (int)(redsum / total);  

       system.out.println(" threshold average value = " + means);  

       // dithering   

       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;  

               if(tr >=means) {  

                tr = tg = tb = 255;  

               } else {  

                tr = tg = tb = 0;  

               }  

               outpixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;  

        }  

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

       return dest;  

}  

2.       基于錯誤擴散的floyd-steinberg抖動算法

關于什麼是floyd-steinberg抖動,參見這裡

<a target="_blank" href="http://en.wikipedia.org/wiki/floyd%e2%80%93steinberg_dithering">http://en.wikipedia.org/wiki/floyd–steinberg_dithering</a>

圖像處理------特殊灰階算法技巧

@override  

        dest = createcompatibledestimage( src, null );  

       getrgb( src, 0, 0, width, height, inpixels );  

       int index = 0;  

               int r1 = (inpixels[index] &gt;&gt; 16) &amp; 0xff;  

               int g1 = (inpixels[index] &gt;&gt; 8) &amp; 0xff;  

               int b1 = inpixels[index] &amp; 0xff;  

               int cindex = getclosecolor(r1, g1, b1);  

               outpixels[index] = (255 &lt;&lt; 24) | (color_palette[cindex][0] &lt;&lt; 16) | (color_palette[cindex][1] &lt;&lt; 8) | color_palette[cindex][2];  

               int er = r1 - color_palette[cindex][0];  

               int eg = g1 - color_palette[cindex][1];  

               int eb = b1 -  color_palette[cindex][2];  

               int k = 0;  

               if(row + 1 &lt; height &amp;&amp; col - 1 &gt; 0) {  

                k = (row + 1) * width + col - 1;  

                   r1 = (inpixels[k] &gt;&gt; 16) &amp; 0xff;  

                   g1 = (inpixels[k] &gt;&gt; 8) &amp; 0xff;  

                   b1 = inpixels[k] &amp; 0xff;  

                   r1 += (int)(er * kerneldata[0]);  

                   g1 += (int)(eg * kerneldata[0]);  

                   b1 += (int)(eb * kerneldata[0]);  

                   inpixels[k] = (255 &lt;&lt; 24) | (clamp(r1) &lt;&lt; 16) | (clamp(g1) &lt;&lt; 8) | clamp(b1);  

               if(col + 1 &lt; width) {  

                k = row * width + col + 1;  

                   r1 += (int)(er * kerneldata[3]);  

                   g1 += (int)(eg * kerneldata[3]);  

                   b1 += (int)(eb * kerneldata[3]);  

               if(row + 1 &lt; height) {  

                k = (row + 1) * width + col;  

                   r1 += (int)(er * kerneldata[1]);  

                   g1 += (int)(eg * kerneldata[1]);  

                   b1 += (int)(eb * kerneldata[1]);  

               if(row + 1 &lt; height &amp;&amp; col + 1 &lt; width) {  

                k = (row + 1) * width + col + 1;  

                   r1 += (int)(er * kerneldata[2]);  

                   g1 += (int)(eg * kerneldata[2]);  

                   b1 += (int)(eb * kerneldata[2]);  

3.       選擇性灰階算法

計算選擇的顔色與像素灰階顔色之間的幾何距離值,跟門檻值比較決定是否像素點為灰階

值,可以得到一些讓你意想不到的圖像處理效果!

圖像效果 (main color = green, 門檻值 = 200)

原圖:

圖像處理------特殊灰階算法技巧

處理以後

圖像處理------特殊灰階算法技巧

 關鍵代碼:

               int gray = (int)(0.299 * (double)tr + 0.587 * (double)tg + 0.114 * (double)tb);  

               double distance = getdistance(tr, tg, tb);  

               if(distance &lt; threshold) {  

                double k = distance / threshold;  

                int[] rgb = getadjustablergb(tr, tg, tb, gray, (float)k);  

                tr = rgb[0];  

                tg = rgb[1];  

                tb = rgb[2];  

                outpixels[index] = (ta &lt;&lt; 24) | (tr &lt;&lt; 16) | (tg &lt;&lt; 8) | tb;  

                outpixels[index] = (ta &lt;&lt; 24) | (gray &lt;&lt; 16) | (gray &lt;&lt; 8) | gray;                      

建立新的目标image  

public bufferedimage createcompatibledestimage(bufferedimage src, colormodel dstcm) {  

    if ( dstcm == null )  

        dstcm = src.getcolormodel();  

    return new bufferedimage(dstcm, dstcm.createcompatiblewritableraster(src.getwidth(), src.getheight()), dstcm.isalphapremultiplied(), null);