圖像處理-神奇的卷積核

關於卷積的理論這裏就不囉嗦了。最近初步學習圖像處理,使用java寫了點對圖像進項卷積操作的代碼,實驗的過程中感覺頗爲驚奇,原來覺得高深的圖像的銳化、浮雕、邊緣檢測等技術,使用簡單的卷積就可以輕鬆實現。
我首先將一副彩色的圖像使用photoshop將其轉換爲灰度的raw格式,這簡化了程序。轉化後的圖像如圖所示:
這裏寫圖片描述

接下來要對該圖像做卷積操作,下面的類中只有一個靜態方法,它能對raw格式灰度圖像數據做卷積操作:

public class Convolution {
    public static byte[][] valide(byte[][] src,int[][] filter){
        if(src[0].length<filter[0].length || src.length<filter.length){
            return null;
        }
        if(filter.length%2==0 || filter[0].length%2==0){
            return null;
        }
        int[][]tem = new int[filter.length][filter[0].length];
        int valideWidth = src[0].length - filter[0].length+1;
        int valideheight = src.length - filter.length+1;
        byte[][] valide = new byte[valideheight][valideWidth];
        for(int i=0;i<valideheight;i++){
            for(int j=0;j<valideWidth;j++){
                for(int y=0;y<filter.length;y++){
                    for(int z=0;z<filter[0].length;z++){
                        tem[y][z] =(src[i+y][j+z]&0xff)*(filter[y][z]);
                    }
                }
                int kk=0;
                for(int y=0;y<filter.length;y++){
                    for(int z=0;z<filter[0].length;z++){
                        kk += tem[y][z];
                    }
                }
                if(kk<0)kk=0;
                if(kk>255)kk=255;
                valide[i][j]=(byte) kk;
            }
        }
        return valide;
    }
}

接下來,是一個測試程序。測試程序中,讀一個raw格式的灰度圖,然後將其轉換爲二維的數據格式,接下來對圖像做卷積操作,也就是調用Convolution 中的valide方法。注意這裏使用的是valide,因此不需要處理邊緣,處理後的圖像比原圖像減小卷積核大小-1。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

public class Test {

    public static void main(String[] args) {

        // TODO Auto-generated method stub
        //int[][] ttt = {{-1,-1,0},{-1,0,1},{0,1,1}}; //浮雕
        //int[][] ttt = {{1,1,1},{1,-7,1},{1,1,1}};   //強調邊緣
        //int[][] ttt = {{0,0,0},{0,1,0},{0,0,0}};     //啥也不做
        //int[][] ttt = {{-1,-1,-1},{-1,8,-1},{-1,-1,-1}};   //邊緣檢測
        int[][] ttt = {{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,24,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1}}; 
        byte [] raw = new byte[444*332];
        FileInputStream in;
        try {
            in = new FileInputStream("flower444x332.raw");
            in.read(raw);
            in.close();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        byte[][] image = new byte[332][444];
        for(int i=0;i<image.length;i++){
            for(int j=0;j<image[0].length;j++){
                image[i][j] = raw[i*image[0].length+j];
            }
        }

        byte[][] valide = Convolution.valide(image, ttt);
        for(int i=0;i<valide.length;i++){
            for(int j=0;j<valide[0].length;j++){
                if(j==valide[0].length-1)
                    System.out.println((valide[i][j]&0xff));
                else
                    System.out.print((valide[i][j]&0xff)+"  ");
            }
        }

        File file = new File("flower"+valide[0].length+"x"+valide.length+".raw");
        if(file.exists())file.delete();
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        try {
            FileOutputStream out = new FileOutputStream(file,true);
            for(int i=0;i<valide.length;i++){
                out.write(valide[i]);
            }
            out.close();

        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

下面是對幾個卷積核的嘗試,非常有趣。
首先,啥也不做,用來初步檢驗程序
int[][] ttt = {{0,0,0},{0,1,0},{0,0,0}}; //啥也不做
這裏寫圖片描述
可以看到圖像並沒有變化。
第一:浮雕
int[][] ttt = {{-1,-1,0},{-1,0,1},{0,1,1}}; //浮雕
這裏寫圖片描述
使用浮雕卷積核處理過後,圖像明顯有了浮雕的特徵。
第二、強調邊緣
int[][] ttt = {{1,1,1},{1,-7,1},{1,1,1}}; //強調邊緣
這裏寫圖片描述
邊緣被加強了。
第三、邊緣檢測(3x3卷積核)
int[][] ttt = {{-1,-1,-1},{-1,8,-1},{-1,-1,-1}}; //邊緣檢測
這裏寫圖片描述
檢測到了圖像的輪廓。
第四、邊緣檢測(5x5卷積核)
int[][] ttt = {{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,24,-1,-1},{-1,-1,-1,-1,-1},{-1,-1,-1,-1,-1}};
這裏寫圖片描述

至此,感興趣的可以自己嘗試其他的卷積核。

發佈了116 篇原創文章 · 獲贊 247 · 訪問量 54萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章