首页 > 其他分享 >opencv在手机上实现照片背景虚化

opencv在手机上实现照片背景虚化

时间:2023-06-08 19:04:38浏览次数:77  
标签:mBitmap Log 照片 opencv import new 虚化 android Mat


概述


使用androidstudio开发,在手机上实现照片背景虚化

详细



一、准备工作

1、需要下载安装androidstudio和相关JDK,这两者下载安装和普通软件一样,

JDK:

http://www.oracle.com/technetwork/java/javase/downloads/index.html

androidstuido:

http://www.android-studio.org/

2、本例子在安卓手机上开发图像美化效果,用以在手机相机上实现类似高羰数码相机的背景虚化特效

3.软件下载安装配置完成后,下载本实例解压,打开androidstudio,选择FILE-》OPEN菜单,在弹出的对话中选择实例解压的位置,打开就行了

二、程序实现

1、主程序包含一个源码主文件MainActivity一个布局文件layout及相当菜单资源

opencv在手机上实现照片背景虚化_opencv

2、实现思路怎样

要使用软件技术精确的背景虚化,需要经过三个步骤:

一是选定区域,根据远区使用抠图技术实现前背景分离

二对背景根据需要使用高斯或者平均值等模糊方法处理

三把处理后的背景和前景合并

3、具体设计到哪些代码

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;


public class MainActivity extends Activity {

    static final int REQUEST_OPEN_IMAGE = 1;

    String mCurrentPhotoPath;
    Bitmap mBitmap;
    ImageView mImageView;
    int touchCount = 0;
    Point tl;
    Point br;
    boolean targetChose = false;
    ProgressDialog dlg;
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    //Log.i(TAG, "OpenCV loaded successfully");

                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };

    @Override
    public void onResume()
    {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d("OpenCV", "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d("OpenCV", "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mImageView = (ImageView) findViewById(R.id.imgDisplay);
        dlg = new ProgressDialog(this);
        tl = new Point();
        br = new Point();
        // if (!OpenCVLoader.initDebug()) {
        // Handle initialization error
        //}
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
    int scaleFactor = 1;
    private void setPic() {
        int targetW = 720;//mImageView.getWidth();
        int targetH = 1128;//mImageView.getHeight();
        Log.i(">>>>>", "targetW="+targetW);
        Log.i(">>>>>", "targetH=" + targetH);
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
        int photoW = bmOptions.outWidth;
        int photoH = bmOptions.outHeight;
        Log.i(">>>>>", "photoW="+photoW);
        Log.i(">>>>>", "photoH=" + photoH);

        scaleFactor = Math.max(photoW / targetW, photoH / targetH)+1;
        Log.i(">>>>>", "photoW / targetW="+(photoW / targetW));
        Log.i(">>>>>", "photoH / targetH="+(photoH / targetH));

        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
        bmOptions.inPurgeable = true;

        mBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
        mImageView.setImageBitmap(mBitmap);
        Log.i(">>>>>", "mBitmap.getWidth()="+mBitmap.getWidth());
        Log.i(">>>>>", "mBitmap.getHeight()=" + mBitmap.getHeight());
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_OPEN_IMAGE:
                if (resultCode == RESULT_OK) {
                    Uri imgUri = data.getData();
                    String[] filePathColumn = { MediaStore.Images.Media.DATA };

                    Cursor cursor = getContentResolver().query(imgUri, filePathColumn,
                            null, null, null);
                    cursor.moveToFirst();

                    int colIndex = cursor.getColumnIndex(filePathColumn[0]);
                    mCurrentPhotoPath = cursor.getString(colIndex);
                    cursor.close();
                    setPic();
                }
                break;
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        switch (id) {
            case R.id.action_open_img:
                Intent getPictureIntent = new Intent(Intent.ACTION_GET_CONTENT);
                getPictureIntent.setType("image/*");
                Intent pickPictureIntent = new Intent(Intent.ACTION_PICK,
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                Intent chooserIntent = Intent.createChooser(getPictureIntent, "Select Image");
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {
                        pickPictureIntent
                });
                startActivityForResult(chooserIntent, REQUEST_OPEN_IMAGE);
                return true;
            case R.id.action_choose_target:

                if (mCurrentPhotoPath != null)
                    targetChose = false;
                mImageView.setOnTouchListener(new View.OnTouchListener() {

                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        int cx = (mImageView.getWidth()-mBitmap.getWidth())/2;
                        int cy = (mImageView.getHeight()-mBitmap.getHeight())/2;
                        if (event.getAction() == MotionEvent.ACTION_DOWN) {
                            if (touchCount == 0) {
                                tl.x = event.getX();//300;//
                                tl.y = event.getY();//300;//
                                touchCount++;
                            }
                            else if (touchCount == 1) {
                                br.x = event.getX();//1100;//
                                br.y = event.getY();//1200;//

                                Paint rectPaint = new Paint();
                                rectPaint.setARGB(255, 255, 0, 0);
                                rectPaint.setStyle(Paint.Style.STROKE);
                                rectPaint.setStrokeWidth(3);
                                Bitmap tmpBm = Bitmap.createBitmap(mBitmap.getWidth(),
                                        mBitmap.getHeight(), Bitmap.Config.RGB_565);
                                Canvas tmpCanvas = new Canvas(tmpBm);

                                tmpCanvas.drawBitmap(mBitmap, 0, 0, null);
                                tmpCanvas.drawRect(new RectF((float) tl.x, (float) tl.y, (float) br.x, (float) br.y),
                                        rectPaint);
                                mImageView.setImageDrawable(new BitmapDrawable(getResources(), tmpBm));

                                targetChose = true;
                                touchCount = 0;
                                mImageView.setOnTouchListener(null);
                            }
                        }

                        return true;
                    }
                });

                return true;
            case R.id.action_cut_image:
                if (mCurrentPhotoPath != null && targetChose) {
                    new ProcessImageTask().execute();
                    targetChose = false;
                }
                return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private class ProcessImageTask extends AsyncTask<Integer, Integer, Integer> {
        Mat img;
        Mat foreground;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dlg.setMessage("Processing Image...");
            dlg.setCancelable(false);
            dlg.setIndeterminate(true);
            dlg.show();
        }

        @Override
        protected Integer doInBackground(Integer... params) {
            //Mat img = new Mat(mBitmap.getHeight(), mBitmap.getHeight(), CvType.CV_8UC3);
            //Utils.bitmapToMat(mBitmap, img);
            long ll = System.currentTimeMillis();
            Log.i(">>>>>", "start="+ll);
            img = Imgcodecs.imread(mCurrentPhotoPath);
            Imgproc.resize(img, img, new Size(img.cols()/scaleFactor, img.rows()/scaleFactor));
            Log.i(">>>>>", "11111=" + System.currentTimeMillis()+"@@@@@"+(System.currentTimeMillis()-ll));
            Mat background = new Mat(img.size(), CvType.CV_8UC3,
                    new Scalar(255, 255, 255));

            Mat firstMask = new Mat();
            Mat bgModel = new Mat();
            Mat fgModel = new Mat();
            Mat mask;
            Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(Imgproc.GC_PR_FGD));
            Mat dst = new Mat();
            Rect rect = new Rect(tl, br);
            Log.i(">>>>>", "22222="+System.currentTimeMillis()+"@@@@@"+(System.currentTimeMillis()-ll));
            Imgproc.grabCut(img, firstMask, rect, bgModel, fgModel,
                    1, Imgproc.GC_INIT_WITH_RECT);
            Log.i(">>>>>", "33333=" + System.currentTimeMillis() + "@@@@@" + (System.currentTimeMillis() - ll));
            Core.compare(firstMask, source, firstMask, Core.CMP_EQ);
            Log.i(">>>>>", "44444=" + System.currentTimeMillis() + "@@@@@" + (System.currentTimeMillis() - ll));
            foreground = new Mat(img.size(), CvType.CV_8UC3,
                    new Scalar(255, 255, 255));
            /
            img.copyTo(foreground);
            Imgproc.blur(foreground, foreground, new Size(20, 20));
            Log.i(">>>>>", "55555=" + System.currentTimeMillis()+"@@@@@"+(System.currentTimeMillis()-ll));
            /
            img.copyTo(foreground, firstMask);
            Log.i(">>>>>", "66666=" + System.currentTimeMillis()+"@@@@@"+(System.currentTimeMillis()-ll));

            firstMask.release();
            source.release();
            bgModel.release();
            fgModel.release();

            Imgcodecs.imwrite(mCurrentPhotoPath + ".png", foreground);

            return 0;
        }

        @Override
        protected void onPostExecute(Integer result) {
            super.onPostExecute(result);

            Bitmap jpg = BitmapFactory
                    .decodeFile(mCurrentPhotoPath + ".png");

            mImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
            mImageView.setAdjustViewBounds(true);
            mImageView.setPadding(2, 2, 2, 2);
            mImageView.setImageBitmap(jpg);
            mImageView.invalidate();


            dlg.dismiss();
        }
    }
}

4、配置文件说明

三、运行效果

运行,右键项目:Run as -》Android Application


1、运行时的截图

opencv在手机上实现照片背景虚化_ide_02

opencv在手机上实现照片背景虚化_照片背景虚化_05

opencv在手机上实现照片背景虚化_android_06

四、其他补充

1、Imgproc.grab分割前景效果比较好,但速度比较慢,如果是确认是固定的比如人脸,水果,植物,可以使用其他OPENCV提代的其他分割方法以加快速度

2.有关模糊,可以根据需要选择合适的模糊算法,比如高斯,比如运动模糊等


标签:mBitmap,Log,照片,opencv,import,new,虚化,android,Mat
From: https://blog.51cto.com/u_7583030/6442263

相关文章

  • html照片从模糊到清晰的渐变加载显示方法
    1.背景介绍在网络相册应用中用户查看照片是最朴素的需求,当网络比较慢的时候查看照片等待的时间是比较长的,用户体验会很差。 2.现状现在加载照片的方法主要有一下两种:(1)最原始的方式在html页面直接用img标签加载显示照片。该方法在网络速度比较慢或者要显示的照片比较大的时候会......
  • python opencv图片旋转任意角度
    pythonopencv图片旋转任意角度 importcv2#Loadtheimageimg=cv2.imread("20230222100736979.jpg")#Gettheimagedimensionsheight,width=img.shape[:2]#Settherotationangleangle=25#Calculatetherotationmatrixrotation_matrix=cv2......
  • MidJourney如何画出专业摄影师拍出的照片效果,附提示词
    文/高扬 最近沉迷于MidJourney作画,与ChatGPT相比,研究AI绘画,可以扩大自己的想像空间。 孩子的想像力更为丰富,如果家有宝宝,可以把孩子们的想法用AI绘画呈现出来,相信会更加好玩。 为了掌握AI绘画要领,我已学到了一些相机、镜头等知识。MidJourney已很好地针对不同相机不同......
  • python opencv GaussianBlur
    pythonopencvGaussianBlur importcv2#Loadtheimageimg=cv2.imread('20230222100736979.jpg')#ApplyaGaussianblurwithakernelsizeof5x5blur=cv2.GaussianBlur(img,(5,5),0)#Displaytheoriginalandblurredimagessidebysi......
  • OpenCV——识别印刷体数字
    数字识别和其他的所有计算机视觉相关的应用都会分为两个步骤:ROI抽取和识别。1.ROI抽取即将感兴趣的区域从原始图像中分离初来,这个步骤包括二值化,噪点的消除等2.识别即通过一些分类器将第一步中的结果进行分类,事实上属于机器学习的一个典型应用 数字识别步骤:1.先处理图像:  转换......
  • OpenCV学习之旅 ch4下
    OpenCV学习之旅​ 由于这部分实在是太长了,所以只好先发布上半部分,再开始写下半部分~O.oChapter4OPENCV中的图像处理4_4图像平滑​ iu女王最近长了痘痘,所以她想通过各种低通滤镜模糊图像OvO2D卷积(图像过滤)​ 与一维信号一样,还可以使用各种低通滤波器(LPF),高通滤波器(HPF)......
  • 用 Python3 & OpenCV 将视频转成字符动画
    在介绍如何用Python3&OpenCV将视频转成字符动画之前,先简单的介绍一下OpenCV吧,毕竟可能很多小伙伴不太了解:百度百科:OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上。它轻量级而且高效——由一系列C函数和少量C++类构成,......
  • 【计算机视觉】---OpenCV实现物体追踪
    简介OpenCV中的物体追踪算法基于视觉目标跟踪的原理。物体追踪的目标是在连续的图像序列中定位和跟踪特定物体的位置。目标表示在物体追踪中,我们需要对目标对象进行表示。通常使用边界框(boundingbox)来表示目标的位置和大小。边界框是一个矩形区域,由左上角的坐标(x,y)和宽度(w)以及高度(h......
  • OpenCV 学习之旅
    OpenCV学习之旅​ 话说已经有一周没见面了,勇士们每天都聚集在我的门前敲门,请求我出山,可是我仍然忙于我的AI大作业,操作系统实验和信号与系统实验,简称三座大山。看在你们的情真意切,周末抽出一点时间帮助你们解决公主布置的问题。​ 上回说到IU公主想要比OpenCV招胥,到底谁能成为......
  • opencv之图像匹配
    输入一张原图和一张你从原图上扣下来的矩形图,用opencv寻找到这个区域。代码如下:#include<opencv2/opencv.hpp>#include<iostream>intmain(){//读取源图像和模板cv::MatsrcImg=cv::imread("targe_graph.jpg");cv::MattmplImg=cv::imread("template.......