1. 程式人生 > >【Andriod】Andriod-Opencv 實現一些簡單的濾鏡功能

【Andriod】Andriod-Opencv 實現一些簡單的濾鏡功能

     最近比較忙,很久沒有更新部落格了。

    這篇文章所說的配置可以直接用android寫opencv,而不需要採用內嵌C++的辦法。(話說我本來想用Dlib來識別人臉的,卻在內嵌c++上吃了不少苦頭。)

    下面就簡單介紹下幾種濾鏡的實現以及效果圖:

   (1)灰度化:這個比較簡單,主要就一行程式碼搞定。

//灰度化方法
    Bitmap RGB2Gray(Bitmap photo) {
        Mat RGBMat = new Mat();
        Bitmap grayBitmap = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.RGB_565);
        Utils.bitmapToMat(photo, RGBMat);//convert original bitmap to Mat, R G B.
        Imgproc.cvtColor(RGBMat, RGBMat, Imgproc.COLOR_RGB2GRAY);//rgbMat to gray grayMat
        Utils.matToBitmap(RGBMat, grayBitmap);
        return grayBitmap;
    }   

   

(2)二值化:二值化主要考慮到一個閾值效果,這個我沒有設定,直接就預設中值了,以後也許會加一個控制條啥的。

//二值化濾鏡
    Bitmap theshold(Bitmap photo){
        Mat mat = new Mat();
        Bitmap thes = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        Utils.bitmapToMat(photo, mat);
        Imgproc.cvtColor(mat,mat,Imgproc.COLOR_RGB2GRAY);
        Core.bitwise_not(mat,mat);
        Imgproc.threshold(mat,mat,100,255,Imgproc.THRESH_BINARY_INV);
        Utils.matToBitmap(mat,thes);
        return thes;
    }


(3)輪廓:輪廓說到底就是一個邊緣檢測。

//輪廓
    Bitmap Lunkuo(Bitmap photo){
        Mat mat = new Mat();
        Mat Cmat = new Mat();
        Mat Bmat = new Mat();
        Bitmap cartton = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        Utils.bitmapToMat(photo, mat);
        Imgproc.Canny(mat,Cmat,50,100);
        Core.bitwise_not(Cmat,Cmat);
        Utils.matToBitmap(Cmat, cartton);
        return cartton;
    }

(4)素描:

//素描濾鏡
    Bitmap SuMiao(Bitmap photo){
        Mat SM = new Mat();
        Mat SM1 = new Mat();
        Bitmap sumiaoMap = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        Bitmap SMB = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        Bitmap SMB1 = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        Utils.bitmapToMat(photo, SM);
        //灰度化
        Imgproc.cvtColor(SM, SM, Imgproc.COLOR_RGB2GRAY);
        //顏色取反
        Core.bitwise_not(SM,SM1);
        //高斯模糊
        Imgproc.GaussianBlur(SM1,SM1,new Size(13,13),0,0);
        Utils.matToBitmap(SM, SMB);
        Utils.matToBitmap(SM1, SMB1);
        for(int i = 0;i<SMB.getWidth();i++){
            for( int j = 0;j<SMB.getHeight();j++){
                int A = SMB.getPixel(i,j);
                int B = SMB1.getPixel(i,j);
                int CR = colordodge(Color.red(A),Color.red(B));
                int CG = colordodge(Color.green(A),Color.red(B));
                int CB = colordodge(Color.blue(A),Color.blue(B));
                sumiaoMap.setPixel(i,j,Color.rgb(CR,CG,CB));
            }
        }
        return sumiaoMap;
    }


(5)接下來是懷舊色。這個要對RGB算式相乘

//懷舊色濾鏡
    Bitmap HuaiJiu(Bitmap photo){
        Bitmap huaijiu = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        for(int i = 0;i<photo.getWidth();i++){
            for( int j = 0;j<photo.getHeight();j++){
                int A = photo.getPixel(i,j);
                int AR =(int)(0.393*Color.red(A) + 0.769*Color.green(A) + 0.189*Color.blue(A));
                int AG =(int)(0.349*Color.red(A) + 0.686*Color.green(A) + 0.168*Color.blue(A));
                int AB =(int)(0.272*Color.red(A) + 0.534*Color.green(A) + 0.131*Color.blue(A));
                AR = AR > 255 ? 255 : AR;
                AG = AG > 255 ? 255 : AG;
                AB = AB > 255 ? 255 : AB;
                huaijiu.setPixel(i,j,Color.rgb(AR,AG,AB));
            }
        }
        return huaijiu;
    }

(6)連環畫:同樣是對RGB色彩操作

Bitmap LianHuanHua(Bitmap photo){
        Bitmap lianhuanhua = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        for(int i = 0;i<photo.getWidth();i++){
            for( int j = 0;j<photo.getHeight();j++){
                int A = photo.getPixel(i,j);
                int AR =Math.abs(Color.red(A) - Color.blue(A) + Color.green(A)+ Color.green(A)  ) * Color.red(A) / 256;
                int AG =Math.abs(Color.red(A) - Color.green(A) + Color.blue(A) + Color.blue(A)) * Color.red(A) / 256;
                int AB =Math.abs(Color.red(A) - Color.blue(A) + Color.blue(A) + Color.blue(A)) * Color.green(A) / 256;
                AR = AR > 255 ? 255 : AR;
                AG = AG > 255 ? 255 : AG;
                AB = AB > 255 ? 255 : AB;
                lianhuanhua.setPixel(i,j,Color.rgb(AR,AG,AB));
            }
        }
        return lianhuanhua;
    }


(7)熔鑄以及冰凍:同上:

//熔鑄濾鏡
    Bitmap RongZhu(Bitmap photo){
        Bitmap rongzhu  = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        for(int i = 0;i<photo.getWidth();i++){
            for( int j = 0;j<photo.getHeight();j++){
                int A = photo.getPixel(i,j);
                int AR =Color.red(A)*128/(Color.blue(A)+Color.green(A)+1);
                int AG =Color.green(A)*128/(Color.blue(A)+Color.red(A)+1);
                int AB =Color.blue(A)*128/(Color.red(A)+Color.green(A)+1);
                AR = AR > 255 ? 255 : AR;
                AG = AG > 255 ? 255 : AG;
                AB = AB > 255 ? 255 : AB;
                rongzhu.setPixel(i,j,Color.rgb(AR,AG,AB));
            }
        }
        return rongzhu;
    }

    //冰凍濾鏡
    Bitmap BingDong(Bitmap photo){
        Bitmap bingdong  = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        for(int i = 0;i<photo.getWidth();i++){
            for( int j = 0;j<photo.getHeight();j++){
                int A = photo.getPixel(i,j);
                int AR =(Color.red(A)-Color.blue(A)-Color.green(A))*3/2;
                int AG =(Color.green(A)-Color.blue(A)-Color.red(A))*3/2;
                int AB =(Color.blue(A)-Color.red(A)-Color.green(A))*3/2;
                AR = AR > 255 ? 255 : AR;
                AG = AG > 255 ? 255 : AG;
                AB = AB > 255 ? 255 : AB;
                bingdong.setPixel(i,j,Color.rgb(AR,AG,AB));
            }
        }
        return bingdong;
    }

(8)浮雕:

//浮雕濾鏡
    Bitmap FuDiao(Bitmap photo){
        Bitmap bingdong  = Bitmap.createBitmap(photo.getWidth(), photo.getHeight(), Bitmap.Config.ARGB_8888);
        for(int i = 1;i<photo.getWidth()-1;i++){
            for( int j = 1;j<photo.getHeight()-1;j++){
                int A = photo.getPixel(i-1,j-1);
                int B = photo.getPixel(i+1,j+1);
                int AR =Color.red(B)-Color.red(A)+128;
                int AG =Color.green(B)-Color.green(A)+128;
                int AB =Color.blue(B)-Color.blue(A)+128;
                AR = AR > 255 ? 255 : AR;
                AG = AG > 255 ? 255 : AG;
                AB = AB > 255 ? 255 : AB;
                bingdong.setPixel(i,j,Color.rgb(AR,AG,AB));
            }
        }
        return bingdong;
    }

(9)此外還做了一個影象人臉識別。


        總之效果還可以,但是還有不足的地方,比如RGB顏色的計算和素描色的計算,不像Python有Numpy大法可以直接做矩陣運算。試了很多方法,最終我妥協了,用迴圈計算每一個畫素點,這樣就導致了圖片越大,濾鏡載入的效果就越慢,尤其是素描濾鏡,簡直慢到令人發恥。這與吳恩達教授所說的向量化計算大相徑庭,根本不像一個學機器學習的人做出來的0.0。

       不管怎樣完工了,順便搞定了一門課的課程設計,可能以後會對演算法部分進行優化吧,再說。

       在這個軟體中,還有一個功能是人臉互換,要用到Dlib,但是在android上配置太麻煩了,我室友就做了一個伺服器端,將圖片上傳到電腦上用Python處理。但是這個功能不是我寫得,所以就不寫在自己的部落格裡了。

         就這樣,下次繼續刷leetcode,並將好玩的題目發到部落格上。

        完整版的原始碼已經傳到github