Android Studio3.3.2 +OpenCV3.4.3图像处理

  • 1 前言
  • 2 开发环境
  • 3 OpenCV for Android的配置
    • 3.1导入OpenCV Module
  • 4 demo(附源码)
    • 4.1 demo简介
    • 4.2 核心代码
      • 4.2.1 activity_main.xml
      • 4.2.2 MainActivity.java
      • 4.2.3 ScreenUtils.java
    • 4.3 运行结果
  • 5 参考链接

1 前言

大学一门课需要在Android Studio中配置OpenCV,感谢博主们的无私分享,将学习记录于此,文末有列出学习链接和demo源码。如果你也想在Android Studio中配置OpenCV,本文或许会给你帮助,来自小白的感谢。

2 开发环境

  • Android Studio 3.3.2
  • OpenCV for Android 3.4.3
  • Windows 10 Enterprise 64bit

注:查看Android Studio版本方法:打开Android Studio顶部工具栏Help→About即可。
相关下载:Android相关工具下载,OpenCV相关下载,gradle个版本下载,

3 OpenCV for Android的配置

3.1导入OpenCV Module

在官网下载好OpenCV的Android SDK,我下载的是OpenCV for Android 3.4.3,解压到本地,创建好一个Android project,开始配置。

第一步,file→new→import module导入刚刚解压好的OpenCV for Android 3.4.3,选择D:\OpenCV for Android 3.4.3\OpenCV-android-sdk\sdk\java,如下图所示,出现openCVLibrary343,就说明被导进来了,然后next→finish即可。导入后可看到我们的project目录下有一个openCVLibrary343的目录。
若出现sync failed ,根据提示修改即可,我的情况如下。

第二步,在project中添加依赖,如下鼠标操作,适合不熟悉Android的小白们。


然后选择openCVLibrary343一路OK下去。

第三步,把D:\OpenCV for Android 3.4.3\OpenCV-android-sdk\sdk\native\libs目录下的库复制到我们的project的app\libs目录下,具体如图所示:

这个目录下存放的是CPU架构相关的库,选择符合自己CPU架构的复制进去。我这里复制了armeabi和armeabi-v7a两个。(注:如果你是X86的架构就把x86的放进去,对应自己CPU架构。)

还要更改下OpenCV的build.gradle里的内容,主要是sdk版本问题,改成和我们app里(build.gradle)的一致就好了,如下图所示:

第四步,在app的gradle.build里配置刚刚复制进来的库,即把下面的代码添加到gradle.build文件里的android结点下:

sourceSets {        main {            jni.srcDirs = []            jniLibs.srcDirs = ['libs']        }    }


然后点击 sync now同步下,gradle没有报错信息,就配置成功了。下面就可以调用OpenCV库进行开发了。

4 demo(附源码)

在开发的时候,要先在用到的java文件里先加载OpenCV初始化库,即添加下面代码:

static {        if(!OpenCVLoader.initDebug())        {            Log.d("opencv","初始化失败");        }    }

4.1 demo简介

demo简介:找到最大轮廓→加粗画出最大轮廓→获得最大轮廓面积。

1.调用bitmapToMat()和matToBitmap()进行图片格式转换,Android显示Bitmap型,OpenCv处理Mat型。

2.调用cvtColor()进行颜色空间转换,可以实现RGB颜色向HSV,HSI等颜色空间转换。也可以转换为灰度图。在demo中,将原图置灰。

3.调用Canny()进行边缘检测。

4.调用dilate()和erode()对图片进行膨胀和腐蚀。两个函数都是针对高亮部分(白色)进行操作。

5.调用findContours()找出所有轮廓。

6.调用contourArea()找出最大面积,即标尺面积。

7.调用DecimalFormat()对输出数据格式化,规定小数点后最多四位。

demo project目录如下图:

4.2 核心代码

4.2.1 activity_main.xml

Android ConstraintLayout图文并茂详解(一)
觉得上面那篇Blog用来学习Android Constraint挺好的,当然下面的布局没那么复杂。

<?xml version="1.0" encoding="utf-8"?>        

4.2.2 MainActivity.java

package com.example.lch.android_opencv_lch;import android.annotation.TargetApi;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.hardware.display.DisplayManager;import android.hardware.display.VirtualDisplay;import android.icu.text.DecimalFormat;import android.media.Image;import android.media.ImageReader;import android.media.projection.MediaProjection;import android.media.projection.MediaProjectionManager;import android.net.Uri;import android.os.Build;import android.os.Handler;import android.provider.MediaStore;import android.support.annotation.RequiresApi;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;import org.opencv.android.OpenCVLoader;import org.opencv.android.Utils;import org.opencv.core.CvType;import org.opencv.core.Mat;import org.opencv.core.MatOfPoint;import org.opencv.core.Point;import org.opencv.core.Scalar;import org.opencv.core.Size;import org.opencv.imgproc.Imgproc;import java.io.FileNotFoundException;import java.nio.ByteBuffer;import java.util.ArrayList;import java.util.List;import static org.opencv.imgproc.Imgproc.MORPH_RECT;import static org.opencv.imgproc.Imgproc.getStructuringElement;public class MainActivity extends AppCompatActivity implements View.OnClickListener {    static {        if(!OpenCVLoader.initDebug())        {            Log.d("opencv","初始化失败");        }    }    private ImageView imageView;    private Bitmap bitmap;    private TextView edt_max;//显示最大面积    private Button btn_max;//最大面积    private Button btn_prtscr;//截图    private Button btn_choose;//从手机选择截图    private static final int REQUEST_MEDIA_PROJECTION = 1;    private VirtualDisplay mVirtualDisplay;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        imageView = (ImageView) findViewById(R.id.image);        edt_max = (TextView) findViewById(R.id.edt_max);        btn_choose = (Button) findViewById(R.id.btn_choose);        btn_choose.setOnClickListener(this);        btn_max = (Button) findViewById(R.id.btn_max);        btn_max.setOnClickListener(this);        btn_prtscr = (Button) findViewById(R.id.btn_prtscr);        btn_prtscr.setOnClickListener(this);    }    @Override    public void onClick(View view) {        switch(view.getId()){            case R.id.btn_choose:ChooseImage();break;            case R.id.btn_max:Maxarea(); break;            case R.id.btn_prtscr:PrtScr();break;        }    }    @TargetApi(Build.VERSION_CODES.N)    private void Maxarea() {        Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap();//获取image里的资源        Mat grayMat = new Mat();        Mat cannyEdges = new Mat();        Mat src = new Mat(bitmap.getHeight(), bitmap.getWidth(), CvType.CV_8UC4);        Utils.bitmapToMat(bitmap, src);        Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGR2GRAY);//置灰        Imgproc.Canny(grayMat, cannyEdges, 10, 100);//Canny边缘检测        Mat element = getStructuringElement(MORPH_RECT, new Size(3, 3));        Imgproc.dilate(cannyEdges, cannyEdges, element);//膨胀        Imgproc.erode(cannyEdges, cannyEdges, element);//腐蚀        List contours=new ArrayList<>();        Mat hierarchy = new Mat();        Imgproc.findContours(cannyEdges,contours,hierarchy ,Imgproc.RETR_EXTERNAL,Imgproc.CHAIN_APPROX_SIMPLE, new Point(0,0));        double Max = 0,contourarea;        int j = 0;//最大轮廓的索引号        for (int i=0;i= android.os.Build.VERSION_CODES.KITKAT) {                        image = mImageReader.acquireLatestImage();                    }                    if (image == null) {                        return;                    }                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {                        int width = image.getWidth();                        int height= image.getHeight();                        final Image.Plane[] planes = image.getPlanes();                        final ByteBuffer buffer = planes[0].getBuffer();                        int pixelStride = planes[0].getPixelStride();                        int rowStride = planes[0].getRowStride();                        int rowPadding = rowStride - pixelStride * width;                        Bitmap mBitmap;                        mBitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);                        mBitmap.copyPixelsFromBuffer(buffer);                        mBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height);//不想截全屏就改这                        image.close();                        if (mBitmap != null) {                            //拿到mitmap                            final Bitmap finalMBitmap = mBitmap;                            imageView.setImageBitmap(finalMBitmap);;                        }                    }                }            }, 300);        }    }    @Override    public void onPointerCaptureChanged(boolean hasCapture) {    }}

4.2.3 ScreenUtils.java

package com.example.lch.android_opencv_lch;import android.content.Context;import android.util.DisplayMetrics;import android.view.WindowManager;public class ScreenUtils {    /**     * 获得屏幕相关的辅助类     */    private ScreenUtils()    {        /* cannot be instantiated */        throw new UnsupportedOperationException("cannot be instantiated");    }        /**     * 获得屏幕高度     * @param context     * @return     */    public static int getScreenWidth(Context context)    {        WindowManager wm = (WindowManager) context                .getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics outMetrics = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics(outMetrics);        return outMetrics.widthPixels;    }        /**     * 获得屏幕宽度     * @param context     * @return     */    public static int getScreenHeight(Context context)    {        WindowManager wm = (WindowManager) context                .getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics outMetrics = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics(outMetrics);        return outMetrics.heightPixels;    }}

4.3 运行结果

run app→Logcat→方便的保存运行情况到PC端。(Android Studio视频录制和截图功能)

运行结果图太大,未传。

5 参考链接

  1. Android Studio中配置OpenCV
  2. androidstudio添加多个按钮方法
  3. android studio 添加按钮点击事件的三种方法
    源码

更多相关文章

  1. popwindow动画显示消失,activity切换动画
  2. android Activity生命周期详解(图文)
  3. popwindow动画显示消失,activity切换动画
  4. Android(安卓)Intent (1)
  5. android Activity生命周期详解(图文)
  6. [置顶] [Android] AsyncTask使用实例---加载网络图片
  7. Android(安卓)剪切板监听
  8. android 竖屏activity跳转横屏activity返回时数据消失
  9. Android(安卓)获取网络状态及调用网络配置界面(转帖)

随机推荐

  1. Android Settings ——language / locale
  2. jni cocos2d-x游戏引擎移植到android:hell
  3. android api和版本对照表
  4. android launcher开发之图标背景以及默认
  5. android 解析xml
  6. Android可滑动的Tab页
  7. Android判断网线连接
  8. Android Studio遇到Installation failed
  9. android 中使用sqLite例子
  10. android中 sqlite sql操作