1. 程式人生 > >一種基於Android Bitmap和陣列操作的簡單卷積影象處理函式

一種基於Android Bitmap和陣列操作的簡單卷積影象處理函式

原理來自於知乎文章:

https://zhuanlan.zhihu.com/p/43738099+

我的實現函式:

    /**使用卷積核對影象進行處理**/
    private static  float sharpeningEffect[] = new float[]{-1,-1,-1,-1,9,-1,-1,-1,-1};//銳化效果
    private static  float noEffect[] = new float[]{0,0,0,0,1,0,0,0,0}; //原圖(測試用)
    private static  float effect2[] = new float[]{1,1,1,1,-7,1,1,1,1}; //強調邊緣
    private static float[] effect3 = {0.1f,0.1f,0.1f,0.1f,0.1f,0.1f,0.1f,0.1f,0.1f};//平滑效果
    private static float[] effect4 = {1/9f,1/9f,1/9f,1/9f,1/9f,1/9f,1/9f,1/9f,1/9f};//平滑效果
    private static float[] effect5 = {1/16f,2/16f,1/16f,2/16f,4/16f,2/16f,1/16f,2/16f,1/16f};//高斯平滑
    private static float[] effect6 = {1,1,1,0,0,0,-1,-1,-1};//豎向邊緣
    public static Bitmap bitmapConvolution(Bitmap bitmap){
        float effect[] = effect2;
        int[] newPixels = new int[bitmap.getWidth() * bitmap.getHeight()];
        for(int y = 0; y < bitmap.getHeight(); y++) {
            for (int x = 0; x < bitmap.getWidth(); x++) {
                int newargb[][] = new int[9][4];
                int count = 0;
                for (int offsetY = -1; offsetY <= 1; offsetY++) {
                    for (int offsetX = -1; offsetX <= 1; offsetX++) {
                        int newX = x + offsetX;
                        int newY = y + offsetY;
                        if(!(newX < 0 || newY < 0 || newX >= bitmap.getWidth() || newY >= bitmap.getHeight())){
                            int pixel = bitmap.getPixel(newX, newY);
                            newargb[count][0] = pixel >> 24 & 0xFF;
                            newargb[count][1] = pixel >> 16 & 0xFF;
                            newargb[count][2] = pixel >> 8 & 0xFF;
                            newargb[count][3] = pixel & 0xFF;
                        } else {
//                            newargb[count][0] = newargb[count][1] = newargb[count][2] = newargb[count][3] = 0xFF;
                        }
                        count++;
                    }
                }
                int resultArgb[] = new int[4];
                for(int i = 0; i < effect.length; i++){
                    for(int j = 0; j < 4; j++){
                        resultArgb[j] += (int) (effect[effect.length - i - 1] *  (float)newargb[i][j]); //第i畫素的第j顏色通道乘以第i個卷積核
                    }
                }
                for(int i = 0; i < resultArgb.length; i++){
                    resultArgb[i] = resultArgb[i] < 0 ? 0 : resultArgb[i] > 255 ? 255 : resultArgb[i];
                }
                newPixels[y * bitmap.getWidth() + x] |= resultArgb[0] << 24;
                newPixels[y * bitmap.getWidth() + x] |= resultArgb[1] << 16;
                newPixels[y * bitmap.getWidth() + x] |= resultArgb[2] << 8;
                newPixels[y * bitmap.getWidth() + x] |= resultArgb[3];
            }
        }
        return  Bitmap.createBitmap(newPixels, bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
    }

大家可以替換effect裡面使用的矩陣來更替影象處理的效果,我預設使用的是“強調邊緣”效果

效果如下:

原圖:

處理後:

原圖:

處理後:

 

改為使用“高斯模糊”(effect5 )效果:

原圖:

處理後: