• opencv移植Android

    2018-04-13 11:24:34
    opencv移植Android端一. 说明 前次的博客说了怎样使用opencv训练识别一些指定的物体,既然有了自己的模型,那么我们是否可以将这个模型用于手机端,结合app进行一些更方便的检测任务呢,回答是肯定的,本篇博客...
    opencv移植到Android端


    一. 说明

        前次的博客说了怎样使用opencv训练识别一些指定的物体,既然有了自己的模型,那么我们是否可以将这个模型用于手机端,结合app进行一些更方便的检测任务呢,回答是肯定的,本篇博客主要记录一下用于物体检测的opencv怎样移植到安卓移动端进行使用的。

    二. 准备工作

    1. 需要的环境

    Android studio(这里使用了2.3.3版本)

    opencv-3.4.0-android-sdk

    地址:https://jaist.dl.sourceforge.net/project/opencvlibrary/opencv-android/3.4.0/opencv-3.4.0-android-sdk.zip

    三. 开始集成

    1. 下载opencv-3.4.0-android-sdk并解压缩

    2. 新建安卓项目,在项目的根目录新建libraries文件夹,复制 Android SDK 中目录 sdk 下的 java 文件夹到刚刚创建的 libraries 目录中,并将拷贝进去的java文件夹名称修改为 opencv

    3. 在重命名的 opencv 文件夹下创建一个 build.gradle 文件,

    内容如下图所示:

    apply plugin: 'android-library'
    
    buildscript {
        repositories {
            mavenCentral()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.3.3'
        }
    }
    
    android {
        compileSdkVersion 25
        buildToolsVersion "27.0.3"
    
        defaultConfig {
            minSdkVersion 15
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
        }
    
        sourceSets {
            main {
                manifest.srcFile 'AndroidManifest.xml'
                java.srcDirs = ['src']
                resources.srcDirs = ['src']
                res.srcDirs = ['res']
                aidl.srcDirs = ['src']
            }
        }
    }

     注: minSdkVersion , targetSdkVersion , versionCode , versionName 等可依实际情况而定


    4. 编辑安卓项目中的settings.gradle 文件,添加一行代码:include ':libraries:opencv',然后点击右上方的Sync Now进行同步

    5. 右键工程, Open Module Settings , 左边选中应用的module名称,右边点击 Dependencies 选项,再点击 + 按钮,添加依赖。选择 Module dependency, 会出现一个含有多个module的列表,选择 :libraries:opencv。





    6.   /app/src/main/ 下创建一个 jniLibs 文件夹在,将OpenCV Android SDK 中 sdk/native/libs 下的所有文件夹复制到创建的 jniLibs 目录下,点击右上方的Sync Now进行同步。

    至此完成了opencv的基本环境配置。


    四. 测试使用

    1. 在安卓项目的res文件夹下新建raw文件夹,将我们之前训练好的舌头模型tongue.xml(制作教程链接:https://blog.csdn.net/qq_27063119/article/details/79247266), (如果没有训练,可以使用gopencv自带的人脸模型OpenCV-android-sdk\sdk\etc\haarcascades\haarcascade_frontalface_alt2.xml)

    2. 在Activity里面添加初始化opencv的函数

    private void initializeOpenCVDependencies() {
            try {
                InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
                File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
    //            File mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
    //            File mCascadeFile = new File(cascadeDir, "haarcascade_frontalface_alt2.xml");
                File mCascadeFile = new File(cascadeDir, "tongue.xml");
                FileOutputStream os = new FileOutputStream(mCascadeFile);
    
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = is.read(buffer)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
                is.close();
                os.close();
    
                // Load the cascade classifier
                cascadeClassifier = new CascadeClassifier(mCascadeFile.getAbsolutePath());
    
                if (cascadeClassifier.empty()) {
                    Log.e("initializeOpenCVDependencies : ", "Failed to load cascade classifier");
                    cascadeDir = null;
                } else{
                    Log.i("initializeOpenCVDependencies : ", "Loaded cascade classifier from " + mCascadeFile.getAbsolutePath());
                }
    
            } catch (Exception e) {
                Log.e("OpenCVActivity", "Error loading cascade", e);
            }
    //        openCvCameraView.enableView();
        }

    使用静态方法进行加载:

    /**
         * 此方式配置的opencv必须要静态方式加载
         */
        private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                    case LoaderCallbackInterface.SUCCESS:
                        initializeOpenCVDependencies();
                        break;
                    default:
                        super.onManagerConnected(status);
                        break;
                }
            }
        };


    接下来就可以对拍照后的图片:Bitmap类型进行 物体检测了:

    检测所用的工具类:FaceRtspUtil,添加检测的方法:detectFrame2()

    /**
     * 人脸检测工具
     */
    public class FaceRtspUtil {
    
        private static final String TAG = "FaceUtil";
        private Mat grayscaleImage;
        private CascadeClassifier cascadeClassifier = null;
    
        public FaceRtspUtil(CascadeClassifier cascadeClassifier, int width, int height) {
            this.cascadeClassifier = cascadeClassifier;
            //人脸的宽高最小也要是原图的height的 10%
            grayscaleImage = new Mat(height, width, CvType.CV_8UC4);
        }
    
    
        /**
         * 测试有没有人脸
         * @param oldBitmap
         * @return
         */
        public boolean detectFrame2(Bitmap oldBitmap) {
            Mat aInputFrame = new Mat();
            if (oldBitmap == null) {
                return false;
            }
            Utils.bitmapToMat(oldBitmap, aInputFrame);
            if (grayscaleImage == null) {
                Log.i(TAG, "detectFrame: aInputFrame == null || grayscaleImage == null");
                return false;
            }
            Imgproc.cvtColor(aInputFrame, grayscaleImage, Imgproc.COLOR_RGBA2RGB);
    
            MatOfRect faces = new MatOfRect();
    
            // 使用级联分类器 检测物体
            if (cascadeClassifier != null) {
                //不获取60*60以下的物体
                cascadeClassifier.detectMultiScale(grayscaleImage, faces, 1.1, 2, 2 , new Size(60, 60), new Size());
            }
            //facesArray里保存所有检测到的人脸的位置及大小
            Rect[] facesArray = faces.toArray();
            if (facesArray == null || facesArray.length == 0) {
                //如果没有人脸,直接退出
                Log.i(TAG, "detectFrame: 该图片中没有人脸");
                return false;
            }else{
                Log.i(TAG, "detectFrame: OK ! 检测到人脸");
                return true;
            }
        }
    
    }
    

    最后就是提供一下调用了,拍照后调用方式:

    //调用opencv检测物体
            FaceRtspUtil mFaceUtil = new FaceRtspUtil(cascadeClassifier, PIC_WIDTH, PIC_HEIGHT);
            //对保存在本地的图片进行人脸检测,并获取截到的所有人脸
            boolean hasSubstance =  mFaceUtil.detectFrame2(rightBitmap);

    如果想自动进行检测到人脸(物体) 自动拍照,可以使用线程进行间断性抓拍,然后将图片递交给opencv检测,如果是检测正确的话就进行存储。


    这里放一下android的效果图:

        


    android 源码下载地址,8个积分(由于集成opencv后项目太大1.2G, 因此不包含opencv集成的文件,自行去文中给的官方链接下载即可) : 

    https://download.csdn.net/download/qq_27063119/10346007




    展开全文
  • 如今,大部分的AR都是基于移动设备的,所以这里我们尝试在Android中调用OpenCV的功能来做一些相关的测试。由于OpenCV是基于C语言和部分C++语言开发的,而Android开发使用的则是Java,那么如何才能在Java中调用OpenCV...

            如今,大部分的AR都是基于移动设备的,所以这里我们尝试在Android中调用OpenCV的功能来做一些相关的测试。由于OpenCV是基于C语言和部分C++语言开发的,而Android开发使用的则是Java,那么如何才能在Java中调用OpenCV库中的类或者代码呢?这就需要借助于JNI了,不过在使用JNI之前,我们首先要先配置好开发环境。


    一、工具:

    1.Eclipse:包含JDK、SDK、IDE、CDTNDK和ADT插件,也就是在android软件开发环境配置完成之后再加上NDK和CDT插件,在这里我只简单说一下NDK的配置过程:

        下载NDK安装包,这里我是在云盘下载的,因为官方链接非常不稳定,我使用的是ndk-r9的版本

           

            解压压缩包到指定目录下面,然后打开eclipse编辑器,工具栏中Window—>Preferences:

            

            注意NDK的路径不能包含空格!!!假如配置NDK后遇到更多的问题可以参考:http://www.bkjia.com/Androidjc/934212.html

    2.OpenCV for Android插件包:到OpenCV的官方网站(http://opencv.org/)下载android专用版的OpenCV资源包

           下载之后得到压缩包:,加压压缩包并得到SDK文件:

          

            这些目录分别存放的文件:

    apk:使用了opencv库的android程序管理包,这个需要按照你手机的实际芯片情况来选择相应版本手工安装,除非你可以连接上google play自动安装;

    samples:一些简单的案例apk及其工程源码

    sdk:最为关键的目录,包含OpenCV android开发用到的API和库文件


    二、安装配置:

    1.将OpenCV库导入Eclipse中:Eclipse中选择工具栏中的:File —>Import...,然后选择General—>Existing Projects into Workspace:

           

        选择刚刚解压出来的OpenCV SDK的根目录,然后导入其中的一个工程:

          

        

        导入的过程中Eclipse就会对导入的项目进行编译,导入成功之后发现一片飘红,那么接下来我们就开始慢慢解决这些错误指导能够成功编译为止。


    2. OpenCV Library -3.1.0是其他所有demo的依赖库文件,所以我们优先解决它的问题然后再导入demo进行测试。从错误列表中我们可以看出大部分的错误都是“XXX cannot be revoled to a type”,这个错误其实就是引用了一些未定义的类,考虑到我们还未引入其他第三方的类库,所以导致这个问题的原因只可能是引用android内部类库所引起的,那么显而易见的可以定位到应该是android API版本不匹配的问题。

        选中工程,右键选择Properties(属性),打开属性页面:

        

        选择Android页签,在此处切换工程依赖的Android API版本,进过查询可以定位缺少的API是Android 5.0中新增的,所以我们只要选择5.0或者5.0以上的API版本,即可解决问题:

         


    3.解决完上述问题之后,我们可以用相同的办法导入一个demo工程,这里我们也可以将全部demo工程一并导入到Eclipse中:

          

        又红了是不是?不要慌,查看错误列表发现错误都是引用未定义类导致的,这其实是因为每个demo都会引用OpenCV Library -3.1.0库文件,但是此时库文件的路径发生了变化,所以才出现了无法正常引入库文件导致的错误,解决方法很简单,只需要为每个工程重新定位库文件路径到当前库文件路径即可:

        

        删除无效的引用,点击Add重新添加库工程引用:

          


     4.对所有的demo工程进行上述设置之后,发现错误栏的错误剩下两个:

            

            这个错误导致的原因是编译的时候无法找到ndk工具,此时我们需要在属性面板中修改C/C++ Build的一些配置信息,取消使用默认的command:

           

           展开目录选中Environment选项,在其中Add多一个路径参数NDKROOT,参数值为NDK的根路径:

           

    5.完成上述操作之后,选择工程右键“clean project”重新编译一次工程,发现错误变成了:

           

           这是因为编译的时候找不到OpenCV SDK中的工具OpenCV.mk所导致的,也就是OpenCV SDK的匹配路径不正确或者是没有匹配,打开当前工程的jni文件夹下的Android.mk文件,这是C/C++编译时使用的配置文件,我们可以看到OpenCV.mk的路径必须为OPENCV_ANDROID_SDK目录下面,或者是与当前工程文件在同一目录下:

            

           所以解决这个问题的方法是:在C/C++ Build的Environment页签再添加一个OPENCV_ANDROID_SDK路径配置常量:

            


    三、案例运行:

            完成以上所有配置之后,工程错误全部解决,那么接下来我们需要看看demo是否能正常运行起来,设备连接PC,然后选择工程右键“Run As”然后选中“Android Application”:

            

            出现此提示的原因是OpenCV 2.4.3之后,apk正常运行必须依赖于OpenCV Manager.apk,找到OpenCV android sdk目录下面的apk目录:

            

            这里适用于很多Android硬件设备,这里我选择安装的是armeabi-v7a这个版本的,顺利安装完OpenCV Manager之后,再次重启刚刚的demo,可以正常运行并看到结果如下:

            

    展开全文
  • 在《Android Studio增加NDK代码编译支持--Mac环境》和《Mac平台下Opencv开发环境搭建》两篇文章中,介绍了如何使用NDK环境和Opencv环境搭建与测试使用,现在,在PC端对图像处理算法测试没问题后,该在移动端进行功能...
    在《Android Studio增加NDK代码编译支持--Mac环境》和《Mac平台下Opencv开发环境搭建》两篇文章中,介绍了如何使用NDK环境和Opencv环境搭建与测试使用,现在,在PC端对图像处理算法测试没问题后,该在移动端进行功能移植了,ios平台的很简单,直接把类库拷进工程就行了,android的稍微麻烦点,这里就以android平台为例说明移植步骤。
    

      为了更好的模块移植,这里使用Android源码的make文件写法:*.mk,Android源码是一个很大的工程,它的编译采用一个大的mk文件,通过脚本文件的配置来自定义编译的,在build/core/下面的Android.mk文件就是总的编译文件入口:

      

       这里写的opencv安卓模块也使用mk文件写法来编译so库。这里新建了一个测试工程,可以在GitHub上download或fork来查看源码: https://github.com/linjk/TestOpenCV

        下面开始移植步骤:

       1. 新建测试工程OpenCVTest:

        

        2. 拷贝下载的opencv的android平台的开发包,这里下载3.1.0版本的:

         

          这里把sdk目录下的native目录拷贝到工程根目录,这个目录下是c/c++语法的,java目录是已封装好的一些java接口,按需选择吧,为了更好的算法移植而不用每次改写,这里选择native库,复制后工程结构如下:

          

        3. 新建jni目录,用于编写本地c++代码:

          在src目录单击右键,按下图操作:

          

          结果如下:

          

        4. 编写java类的本地接口声明,用于给java层调用:

          这里声明一个很简单的opencv本地方法,用于把一副图像编程灰度图像,当然,这个效果用安卓的图像矩阵来处理就行了,但是,复杂一点的功能,如边缘检测、身份证识别就要借助opencv来弄了,这里仅做功能测试:

          

        5. 生成本地方法桥接头文件:

          命令行进入src/main/java路径,然后执行命令: javah -jni cn.linjk.jniBridge.OpenCVUtils, -jni参数后面参数格式是:包名+类名,结果如下:

            

            我们把这个文件移动到jni目录下,并新建一个同名的cpp类cn_linjk_jniBridge_OpenCVUtils.cpp:

        6. 由于之前使用了android studio生成的jni目录,因此,编译上可能会和使用mk文件编译生成so库不一样,这里取消它的路径属性:

        在app/build.gradle文件的android块下增加这个配置:

    sourceSets{
            main{
                jni.srcDirs = []
            }
        }
    

         可以发现,jni目录由蓝色变成了黄色:

        

        7. 编写编译规则文件,指定ndk路径:

          7.1 指定ndk路径:

          

          7.2 在jni目录下新建两个mk编译文件,内容分别如下:

          

          Android.mk文件内容如下:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    OpenCV_INSTALL_MODULES := on
    OpenCV_CAMERA_MODULES := off
    
    OPENCV_LIB_TYPE := SHARED
    
    ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
    include ../../../../native/jni/OpenCV.mk
    else
    include $(OPENCV_MK_PATH)
    endif
    
    LOCAL_MODULE := testopencv
    
    LOCAL_SRC_FILES := cn_linjk_jniBridge_OpenCVUtils.cpp
    
    LOCAL_LDLIBS +=  -lm -llog -landroid
    
    include $(BUILD_SHARED_LIBRARY)
    

         LOCAL_MODULE声明的是模块名称,必须与在OpenCVUtils声明的加载库名一样。

        Application.mk文件内容如下:

    APP_STL := gnustl_static
    APP_CPPFLAGS := -frtti -fexceptions
    APP_ABI := arm64-v8a armeabi armeabi-v7a mips mips64
    

         APP_ABI声明了声明针对那些CPU架构的so库。

        7.3 在app/build.gradle声明一个task,用于编译生成so库。

          7.3.1 编辑jni的cpp文件,内容如下,为测试能否调用库,这里先在函数打印cv版本:

    //
    // Created by LinJK on 21/11/2016.
    //
    
    #include "cn_linjk_jniBridge_OpenCVUtils.h"
    
    #include <opencv2/opencv.hpp>
    
    #include <Android/log.h>
    #include <Android/asset_manager.h>
    #include <Android/asset_manager_jni.h>
    
    #define TAG "cn.linjk.opencvtest.jni"
    #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
    #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__)
    #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__)
    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)
    #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)
    
    extern "C" {
    
    JNIEXPORT void JNICALL Java_cn_linjk_jniBridge_OpenCVUtils_img2gray
        (JNIEnv *env , jclass objClass, jstring imgFilePath) {
    
            LOGI("OpenCV version: %s", CV_VERSION);
    
        }
    
    }
    

         7.3.2 增加生成so库的task:

          

        7.3.3 执行任务,生成so库:

          执行命令"gradle cv_ndkBuild",结果如下:

          

          把对应得so库复制到app/libs目录下对应cpu架构目录下:

          

        8. 在MainActivity调用看能否输出opencv库版本:

          MainActivity.java内容:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            OpenCVUtils.img2gray("");
        }
    }
    

         运行后,发现出现如下错误:

        

        这是我们指定生成动态链接库,因此,还需要libopencv_java3.so这个库,复制到我们的libs下,再次运行,结果如下:

        

        输出正确,可以继续下一步了。

        附:

        也可以使用命令“arm-none-eabi-readelf -d libtestopencv.so”查看其需要的链接库,命令执行结果如下:

        

        .so文件是ELF(Excutable and Linking Formar)格式的缩写,最初由UNIX系统实验室发布,它是应用程序二进制接口的一部分,ELF文件以节(section)的方式组织在一起,“节”描述了文件的各项信息,例如代码、数据、符号表、重定位表、全局偏移表等。

      9. 编写图像处理类:

      9.1 这里使用照相机获取输入图像,代码看github的源码就行,这里主要看看c++最终代码:

        cn_linjk_jniBridge_OpenCVUtils.cpp

    //
    // Created by LinJK on 21/11/2016.
    //
    
    #include "cn_linjk_jniBridge_OpenCVUtils.h"
    
    #include <opencv2/opencv.hpp>
    #include <string>
    #include <iostream>
    
    #include <Android/log.h>
    #include <Android/asset_manager.h>
    #include <Android/asset_manager_jni.h>
    
    #define TAG "cn.linjk.opencvtest.jni"
    #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__)
    #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__)
    #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__)
    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__)
    #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__)
    
    using namespace std;
    using namespace cv;
    
    class ImageUtils{
    public:
        void imageToGray(Mat inputImg, string outFilePath);
    };
    
    void ImageUtils::imageToGray(Mat inputImg, string outFilePath) {
        Mat gray;
    
        Mat input = inputImg.clone();
    
        cvtColor(input, gray, COLOR_BGR2GRAY);
    
        imwrite(outFilePath,  gray);
    }
    
    extern "C" {
    
    JNIEXPORT void JNICALL Java_cn_linjk_jniBridge_OpenCVUtils_img2gray
        (JNIEnv *env , jclass objClass, jstring imgFilePath) {
    
            LOGI("OpenCV version: %s", CV_VERSION);
    
            char buf[128];
            const char *str = env->GetStringUTFChars(imgFilePath, 0);
            LOGD("图像路径: %s", str);
    
            Mat img = imread(str);
            if (!img.data) {
                LOGE("-----CV: 读取相片数据出错");
            }
            else {
                LOGD("-----CV: 读取相片数据成功");
                ImageUtils().imageToGray(img, str);
            }
        }
    
    }
    

           MainActivity.java方法内容如下:

    package cn.linjk.opencvtest;
    
    import android.content.Intent;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.os.Environment;
    import android.provider.MediaStore;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.Display;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    import cn.linjk.jniBridge.OpenCVUtils;
    
    public class MainActivity extends AppCompatActivity {
    
        private Button btnOpenCamera;
        private ImageView ivImgOutput;
        private Button btnImgGray;
    
        private String imageFilePath;
    
        private static final int CAMERA_RESULT = 1112;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btnOpenCamera = (Button)findViewById(R.id.btn_open_camera);
            btnOpenCamera.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View pView) {
                    openCamera();
                }
            });
    
            ivImgOutput = (ImageView)findViewById(R.id.img_output);
    
            btnImgGray   = (Button)findViewById(R.id.img_gray);
            btnImgGray.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View pView) {
                    OpenCVUtils.img2gray(imageFilePath);
                    //
                    BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
                    bmpFactoryOptions.inJustDecodeBounds = true;
                    Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
    
                    bmpFactoryOptions.inSampleSize = calculateInSampleSize(bmpFactoryOptions, 1280, 800);
    
                    bmpFactoryOptions.inJustDecodeBounds = false;
    
                    bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
    
                    ivImgOutput.setImageBitmap(bmp);
                }
            });
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
    
            if (resultCode == RESULT_OK) {
                BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
                bmpFactoryOptions.inJustDecodeBounds = true;
                Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
    
                bmpFactoryOptions.inSampleSize = calculateInSampleSize(bmpFactoryOptions, 1280, 800);
    
                bmpFactoryOptions.inJustDecodeBounds = false;
    
                bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);
    
                ivImgOutput.setImageBitmap(bmp);
    
                saveBitmap(bmp);
            }
        }
    
        private void openCamera() {
            imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/testImage.jpg";
            File imageFile = new File(imageFilePath);
            Uri imageFileUri = Uri.fromFile(imageFile);
    
            Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            i.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
            startActivityForResult(i, CAMERA_RESULT);
        }
    
        private int calculateInSampleSize(BitmapFactory.Options options,
                                          int reqWidth, int reqHeight) {
    
            final int height = options.outHeight;
            final int width = options.outWidth;
            int inSampleSize = 1;
    
            if (height > reqHeight || width > reqWidth) {
    
                final int heightRatio = Math.round((float) height
                        / (float) reqHeight);
                final int widthRatio = Math.round((float) width / (float) reqWidth);
    
                inSampleSize = heightRatio < widthRatio ? widthRatio : heightRatio;
            }
    
            return inSampleSize;
        }
    
        private void saveBitmap(Bitmap bm) {
            File f = new File(imageFilePath);
            if (f.exists()) {
                f.delete();
            }
            try {
                FileOutputStream out = new FileOutputStream(f);
                bm.compress(Bitmap.CompressFormat.PNG, 90, out);
                out.flush();
                out.close();
            }
            catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

           运行结果如下:

          

         这里,opencv在android平台的移植和简单功能测试已经完成了,后面更多精彩opencv算法就可以继续实现啦~~

          详细代码移步我的GitHub查阅即可:

          https://github.com/linjk/TestOpenCV 

    展开全文
  • OpenCV4Android开发实录(1):移植OpenCV3.3.0库到Android Studio 转载请声明出处:http://blog.csdn.net/andrexpert/article/details/78993533   OpenCV4Android系列: 1. OpenCV4Android开发实录(1):移植...

    OpenCV4Android开发实录(1):移植OpenCV3.3.0库到Android Studio

    转载请声明出处:http://blog.csdn.net/andrexpert/article/details/78993533

     

    OpenCV4Android系列

    1. OpenCV4Android开发实录(1):移植OpenCV3.3.0库到Android Studio

    2.OpenCV4Android开发实录(2): 使用OpenCV3.3.0库实现人脸检测

     

    1.OpenCV开源框架简介
        OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。截止本文日期,OpenCV官方提供的最新版本为OpenCV3.4.0,但是这里将以OpenCV3.3.0为主,根据不同的平台下载方式如下:

       

    (1)  OpenCV核心框架

    (2) OpenCV SDK介绍

    2. 移植OpenCV库到Android Studio

    以静态加载方式
    (1) 创建新的Android Studio工程,将OpenCV库以Module的形式引入到工程中,即File->Import Module,Source directory选中...\opencv-3.3.0-android-sdk\OpenCV-android-
    sdk\sdk\java目录,然后直接下一步即可。

    (2) 添加openCVLibrary330库作为app module的依赖
    步骤:File->Project Structure->选中app的Dependencies选项,点击”+”选中Module dependencies
     
    (3) 配置NDK环境。由于在后面演示使用官方Sample需要使用NDK编译,这里需要在Android Studio工程中配置好NDK环境。
    步骤:File->Project Structure->选中SDK Location选项,设置Android NDK location路径
     
    (4)修改app模块中的build.gradle,添加sourceSets字段。

    android {
        compileSdkVersion 25
        defaultConfig {
            applicationId "com.jiangdg.opencv4android"
            minSdkVersion 15
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
        }
        ….// 代码省略
        sourceSets {
            main {
                jniLibs.srcDirs = ['libs']
            }
        }
    }

    将工程切换到Android选项,就会看到在app目录下自动生成一个jniLibs目录,然后,我们再将OpenCV本地库(…\opencv-3.3.0-android-sdk\OpenCV-android-sdk\sdk\native\libs)拷贝到工程的jniLibs目录。这里我根据项目所需只拷贝了arm64-v8a、armeabi、armeabi-v7a架构文件,内容如下:
     
    至此,OpenCV库的移植就完成了,整个工程视图如下:

    3.编写第一个OpenCV实例:Hello OpenCV
        HelloOpenCV实例功能比较简单,即通过OpenCV库实现Camera渲染到手机屏幕,以便验证OpenCV库移植到Android Studio是否成功。核心代码如下:
    (1) HelloOpenCVActivity.class

    /**
     * 第一个OpenCV例子
     * Created by jiangdongguo on 2017/12/29.
     */
    public class HelloOpenCVActivity extends AppCompatActivity {
        private static final String TAG = "HelloOpenCVActivity";
        @BindView(R.id.HelloOpenCvView)
        CameraBridgeViewBase mOpenCvCameraView;
        private LoaderCallbackInterface mLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                    // OpenCV引擎初始化加载成功
                    case LoaderCallbackInterface.SUCCESS:
                        Log.i(TAG, "OpenCV loaded successfully.");
                        // 连接到Camera
                        mOpenCvCameraView.enableView();
                        break;
                    default:
                        super.onManagerConnected(status);
                        break;
                }
            }
        };
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 全屏显示
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    
    
            setContentView(R.layout.activity_hello);
            // 绑定View
            ButterKnife.bind(this);
            mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
            // 注册Camera连接状态事件监听器
            mOpenCvCameraView.setCvCameraViewListener(new CameraBridgeViewBase.CvCameraViewListener2() {
    
    
                @Override
                public void onCameraViewStarted(int width, int height) {
                }
    
                @Override
                public void onCameraViewStopped() {
                }
    
                @Override
                public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
                    return inputFrame.rgba();
                }
            });
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            // OpenCVLoader.initDebug()静态加载OpenCV库
    	    // OpenCVLoader.initAsync()为动态加载OpenCV库,即需要安装OpenCV Manager
            if (!OpenCVLoader.initDebug()) {
                Log.w(TAG, "static loading library fail,Using Manager for initialization");
                OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_3_0, this, mLoaderCallback);
            } else {
                Log.w(TAG, "OpenCV library found inside package. Using it!");
                mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
            }
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            // 断开与Camera的连接
            if (mOpenCvCameraView != null) {
                mOpenCvCameraView.disableView();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 断开与Camera的连接
            if (mOpenCvCameraView != null) {
                mOpenCvCameraView.disableView();
            }
        }
    }

    (2) activity_hello.xml

     

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:opencv="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <org.opencv.android.JavaCameraView
            android:id="@+id/HelloOpenCvView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:visibility="gone"
            opencv:camera_id="any"
            opencv:show_fps="true" />
    </LinearLayout>

    注:通过JavaCameraView源码可知,JavaCameraView实际上是SurfaceView的一个子类,自定义属性opencv:camera_id为指定摄像头ID,其默认为开启后置摄像头;opencv:show_fps为是否显示帧率。
    (3) AndroidMainfest.xml:添加使用权限

     

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>


    参考资料:
    (1)  OpenCV4Android官网
    (2) OpenCV Tutorials
    (3) Android Development with OpenCV

     

    (4) OpenCV4Android SDK

     

     

    源码下载:https://github.com/jiangdongguo/OpenCV4Android(欢迎star & fork)

     

     

    展开全文
  • openCV移植Android Studio1、引入OpenCV库2、添加依赖3、添加jniLibs4、主要文件HelloOpenCVActivityactivity_hello.xmlAndroidMainfest.xmlbuild.gradle 1、引入OpenCV库 将openCV库以module的形式引入进来:File...

    1、引入OpenCV库

    将openCV库以module的形式引入进来:File --> Import Module
    在这里插入图片描述

    2、添加依赖

    点击 Project Structure --> 选中 openCVLibrary330 --> 把Compile Sdk Version改为 API 28
    在这里插入图片描述

    点击 Project Structure --> 选中 test01 --> 点击 Dependecies --> 点击 ‘+’ ,选中 Module Dependecy
    在这里插入图片描述

    3、添加jniLibs

    在build.gradle中添加sourceSets
    在这里插入图片描述
    然后切换到Android视图,会自动生成一个jniLibs目录,把opencv的native目录中libs目录中的arm64-v8a,armeabi和armeabi-v7a三个文件夹复制到jniLibs中
    在这里插入图片描述

    4、主要文件

    HelloOpenCVActivity

    package com.example.test01;
    
    import android.support.annotation.Nullable;
    import android.support.v7.app.AppCompatActivity;-v7
    import android.os.Bundle;
    import android.util.Log;
    import android.view.SurfaceView;
    import android.view.WindowManager;
    
    import org.opencv.android.BaseLoaderCallback;
    import org.opencv.android.CameraBridgeViewBase;
    import org.opencv.android.LoaderCallbackInterface;
    import org.opencv.android.OpenCVLoader;
    import org.opencv.core.Mat;
    
    import butterknife.BindView;
    import butterknife.ButterKnife;
    
    /**
     * 第一个OpenCV例子
     * Created by jiangdongguo on 2017/12/29.
     */
    public class HelloOpenCVActivity extends AppCompatActivity {
        private static final String TAG = "HelloOpenCVActivity";
        @BindView(R.id.HelloOpenCvView)
        CameraBridgeViewBase mOpenCvCameraView;
        private LoaderCallbackInterface mLoaderCallback = new BaseLoaderCallback(this) {
            @Override
            public void onManagerConnected(int status) {
                switch (status) {
                    // OpenCV引擎初始化加载成功
                    case LoaderCallbackInterface.SUCCESS:
                        Log.i(TAG, "OpenCV loaded successfully.");
                        // 连接到Camera
                        mOpenCvCameraView.enableView();
                        break;
                    default:
                        super.onManagerConnected(status);
                        break;
                }
            }
        };
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 全屏显示
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    
    
            setContentView(R.layout.activity_hello);
            // 绑定View
            ButterKnife.bind(this);
            mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
            // 注册Camera连接状态事件监听器
            mOpenCvCameraView.setCvCameraViewListener(new CameraBridgeViewBase.CvCameraViewListener2() {
    
    
                @Override
                public void onCameraViewStarted(int width, int height) {
                }
    
                @Override
                public void onCameraViewStopped() {
                }
    
                @Override
                public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
                    return inputFrame.rgba();
                }
            });
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            // OpenCVLoader.initDebug()静态加载OpenCV库
            // OpenCVLoader.initAsync()为动态加载OpenCV库,即需要安装OpenCV Manager
            if (!OpenCVLoader.initDebug()) {
                Log.w(TAG, "static loading library fail,Using Manager for initialization");
                OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_3_0, this, mLoaderCallback);
            } else {
                Log.w(TAG, "OpenCV library found inside package. Using it!");
                mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
            }
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            // 断开与Camera的连接
            if (mOpenCvCameraView != null) {
                mOpenCvCameraView.disableView();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            // 断开与Camera的连接
            if (mOpenCvCameraView != null) {
                mOpenCvCameraView.disableView();
            }
        }
    }
    
    

    activity_hello.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:opencv="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <org.opencv.android.JavaCameraView
            android:id="@+id/HelloOpenCvView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:visibility="gone"
            opencv:camera_id="any"
            opencv:show_fps="true" />
    </LinearLayout>
    

    AndroidMainfest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.test01">
        <uses-permission android:name="android.permission.CAMERA"/>
        <uses-feature android:name="android.hardware.camera" android:required="false"/>
        <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
        <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
        <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".HelloOpenCVActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
        </application>
    
    </manifest>
    

    build.gradle

    apply plugin: 'com.android.application'
    
    android {
        compileSdkVersion 28
    
    
    
        defaultConfig {
            applicationId "com.example.test01"
            minSdkVersion 15
            targetSdkVersion 28
            versionCode 1
            versionName "1.0"
    
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    
        }
    
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    
        sourceSets {
            main {
                jniLibs.srcDirs = ['libs']
            }
        }
    
    }
    
    dependencies {
        implementation fileTree(include: ['*.jar'], dir: 'libs')
        implementation 'com.android.support:appcompat-v7:28.0.0'
        implementation 'com.android.support.constraint:constraint-layout:1.1.3'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
        implementation project(':openCVLibrary330')
        implementation 'com.jakewharton:butterknife:8.8.1'
        annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    }
    
    
    展开全文
  • openCV人脸识别移植Android1、引入openCV人脸检测模块2、修改jni目录下的文件修改Android.mk修改Application.mk修改DetectionBasedTracker_jni.h和DetectionBasedTracker_jni.cpp3、进行ndk-build生成动态库4、...
  • 本文记录了如何使用官方提供的OpenCV4Android库在android下使用OpenCV
  • 前言:最近在做项目移植,项目较大,在Eclipse中配置的Jni及OpenCV环境没任何问题,但是迁移到Studio中就问题一大堆,网上也找了一些资料参考及学习,很感谢前人留下的总结及经验。关于在AS中使用jni及配置OpenCV也...
  • PC机上的行人检测的C++项目移植Android平台遇到很多的问题,因此,记录一些重点。
  • 之前的利用java命令编辑生jni文件的方式已经out了,本文主要介绍利用cmake插件来实现opencv for android 的配置和使用,掌握了cmake文件想配置其他的算法移植等工作也是一样的原理。配置 android studio 2.3以后的...
  • OpenCV android sdk配置OpenCV android NDK开发实例  【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/78374708  在Android应用中调用OpenCV进行图像处理的方法有很多种,考虑到...
  • OpenCV-android-sdk.zip

    2020-07-11 12:17:32
    OpenCV android的SDK用于androidopencv移植OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 ...
  • 简介本教程是经过本人多次踩坑,并参考网上众多OpenCV On Android的配置教程总结而来,尽希望帮助学习移动图像处理的朋友少走点弯路。这是本人第一次在简书上发布文章,如有不足,希望各位dalao能够指正,我也将及时...
  • 上一篇文章OpenCV4Android开发实录(1):移植OpenCV3.3.0库到Android Studio大概介绍了下OpenCV库的基本情况,阐述了将OpenCV移植Android Studio项目中的具体步骤。本文将在此文的基础上,通过对OpenCV框架中的...
  • Opencv移植到安卓平台

    2017-11-09 13:54:52
    OpenCV于1999年由Intel 建立,全称:OpenSource Computer Vision Library。 OpenCV是一个跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++类构成...
  • 编译OpenCV for Android

    2017-05-10 10:00:20
    前言:现在机器视觉越来越多的在移动设备上应用,所以,经常有人需要编译可以运行在android平台上的可以运行的OpenCV。 其实,编译OpenCV并不难,毕竟编译的脚本都写好了,运行一下就Ok了。不过,还是经常会遇见...
  • 此文实在android集成开发环境下进行的安装。 步骤1:  安装adt-bundle-windows-x86-20130917,这是个集成的Android开发编程环境,下载到电脑上后直接打开上面的Eclipse就可以了。  添加androidsdk:  首先按...
  • 本文介绍OpenCV的发展历程,以OpenCV2.4.4为载体演示如何将Android开发和OpenCV通过Java接口进行调用。让数字图像处理和Android APP开发完美融合。
  • http://opencv.willowgarage.com/wiki/Android
1 2 3 4 5 ... 20
收藏数 2,539
精华内容 1,015
关键字:

opencv 移植android