【Andriod】Andriod-Opencv 实现一些简单的滤镜功能

     最近比较忙,很久没有更新博客了。

     关于在android 下配置opencv的文章可以去看这一片博客:Android Studio中使用OpenCV Android SDK

    这篇文章所说的配置可以直接用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

     

    

猜你喜欢

转载自blog.csdn.net/qq_31548387/article/details/80469202