android端基于openCV给图片打马赛克

最近一直在捣腾openCV,看到别人朋友圈总喜欢给图片打一点马赛克,充满神秘感。准备用openCV来实现打码,其实足够模糊就能实现马赛克效果。查看API发现ImgProc模块提供四种模糊方法:高斯模糊、均值模糊、中值模糊、双边滤波。在这里主要比较高斯模糊、均值模糊以及自定义覆盖层的实现效果。

首先,各种初始化:openCV库、模糊线程、人脸检测器。

    /**
     * 初始化openCV
     */
    private void initOpenCV(){
        boolean result = OpenCVLoader.initDebug();
        if(result){
            Log.i(TAG, "initOpenCV success...");
        }else {
            Log.e(TAG, "initOpenCV fail...");
        }
    }

    /**
     * 初始化mat
     */
    private void initMat(){
        mat = new Mat();
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.beauty);
        Utils.bitmapToMat(bitmap, mat);
    }

    /**
     * 初始化线程
     */
    private void initThread(){
        blurThread = new BlurThread(mHandler, blurMat);
        blurThread.start();
        blurThread.setRunning(true);
    }

    /**
     * 初始化人脸检测器
     * @param context context
     */
    public void initDetector(Context context){
        mFaceRect = new MatOfRect();
        mFaceDetector = new ObjectDetector(context, R.raw.lbpcascade_frontalface,
                6, 0.2F, 0.2F,
                new Scalar(0, 0, 255, 0));
    }
使用人脸检测器去检测人脸,得到待打码区域:

    /**
     * 检测人脸
     */
    private void detectFace(){
        Mat mGray = new Mat();
        Imgproc.cvtColor(mat, mGray, Imgproc.COLOR_RGBA2GRAY);
        Rect[] faceRect = mFaceDetector.detectObject(mGray, mFaceRect);
        if(faceRect != null && faceRect.length > 0){
            Rect face = faceRect[0];
            //矩形标识
            Imgproc.rectangle(mat, face.tl(), face.br(),
                    mFaceDetector.getRectColor(), 3);
            //待打码区域
            blurMat = mat.submat((int) face.tl().y, (int) face.br().y, (int) face.tl().x, (int) face.br().x);
        }
        mGray.release();
        mHandler.obtainMessage(100).sendToTarget();
    }


1、高斯模糊

高斯模糊是采用高斯核函数,创建高斯滤波器,遍历待滤波区域:每一个像素与给定像素矩阵模板相乘,求线性加权平均点。

    //高斯模糊
    private void gaussianBlur(int width, int height,double sigmaX){
        Imgproc.GaussianBlur(blurMat, blurMat, new Size(width, height), sigmaX);
    }


2、均值模糊

均值模糊是对给定像素矩阵取平均值,算法比高斯模糊简单点,耗时相对短一点。

    //均值模糊
    private void normalBlur(int width, int height){
        Imgproc.blur(blurMat, blurMat, new Size(width, height));
    }

3、深度模糊(自定义覆盖层)

自定义模糊算法相对简单:遍历待处理区域,重新赋值为指定颜色值。

    //自定义模糊
    private void customBlur(int color){
        //ARGB转成RGBA
        pixelColor[2] = color & 0xFF;//Blue
        pixelColor[1] = (color >> 8) & 0xFF;//Green
        pixelColor[0] = (color >> 16) & 0xFF;//Red
        pixelColor[3] = (color >> 24) & 0xFF;//Alpha

        for (int x=0; x<blurMat.rows(); x++){
            for (int y=0; y<blurMat.cols(); y++){
                blurMat.put(x, y, pixelColor);
            }
        }
    }

如果需要在预览时,可采用均值模糊进行实时打码(高斯模糊耗时比较长,引起预览卡顿):

    @Override
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        mRgba = inputFrame.rgba();
        mGray = inputFrame.gray();
        // 检测人脸
        Rect[] faceRect = mFaceDetector.detectObject(mGray, mFaceRect);
        if(faceRect != null && faceRect.length > 0){
            Rect face = faceRect[0];
            //采用均值模糊进行打码
            Mat blurMat = mRgba.submat((int) face.tl().y, (int) face.br().y, (int) face.tl().x, (int) face.br().x);
            Imgproc.blur(blurMat, blurMat, new Size(99, 99));
        }
        return mRgba;
    }
好了,关于采用高斯模糊、均值模糊以及自定义覆盖层给图片打码分析完毕。如果各位有什么问题或建议,欢迎交流,如果觉得本篇文章对您有所帮助,麻烦点个赞。。。


发布了63 篇原创文章 · 获赞 179 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/u011686167/article/details/79124322