OpenCV4Android is implemented in version 2.x without using OpenCVManager and compiling SIFT algorithm

Keywords: Android Attribute OpenCV SDK

This week, bloggers used the SIFT algorithm in OpenCV4Android to extract image features. The reasonably SIFT algorithm is packaged for you. Generally, it should be completed very soon by adjusting a package. But using OpenCV in Android configuration is a difficult problem. Usually when you run app, your mobile phone will prompt you to install OpenCV4Android Manager, which will definitely affect the user experience. Secondly, SIFT calculation and SURF algorithm are proprietary algorithms. You also need to compile them to invoke them on Android platform.
So this article mainly talks about configuration and compilation problems, which do not involve the program, but mainly solve the following two problems.
(1) OpenCVManager is not installed
(2) Compiling SIFT algorithm (SURF algorithm is similar to it)
Reasonable OpenCV4Android is used by too few people, and there are a lot of errors in the blog itself, which has not been specifically verified, and bloggers have taken many detours.
So I'm here to make sure that if you run in exactly the same environment as the blogger, 100% will be successful.
About my operating environment
Operating System: Windows 10
OpenCV4Android: Version 2.4.10
AndroidStudio:2.3.1
NDK
Once you're ready, you can start our first step of configuring OpenCV in an Android environment without installing OpenCV Manager
1) New your Android project (not demonstrated here)
2) File - > New - > Import mouse specific path as follows

Here's an error message, don't worry about it, because I've imported it before, you should not have this problem.
Then modify moudle's build.gradle file
Actually, just cover all your newly built app/build.gradle content and then modify some of it.

apply plugin: 'com.android.library'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 25
        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']
        }
        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.1.1'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    testCompile 'junit:junit:4.12'
}

Mainly will be
Replace apply plugin:'com.android.application'with apply plugin:'com.android.library'
Delete application Id
Finally add

    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
    }

Just re build.
Next we need to make changes in this module.
Create a new libs directory, which will
Copy all the subfiles under <your OpenCV4Android path>/sdk/native/libs to this file.
Then we add the moudle to our Project as a dependency.
File->Project Structure->Dependencies
Choose your openCVLibrary

Okay, so we've embedded OpenCV into your APP
Write some engineering documents quickly and try it out.
Here I have a direct reference. https://www.cnblogs.com/yunfang/p/6149831.html The code has been experimented, but this article is for OpenCV3. I mainly focus on OpenCV2 and there are a few steps that I think are still a bit problematic. You can also make a reference.
Write an OpenCV gray level conversion function first.
Add in the layout file

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:paddingTop="16dp"
    android:paddingBottom="16dp"
    tools:context="com.qucheng.sift4androidx.MainActivity">

    <ImageView
        android:id="@+id/img_huaishi"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>
    <Button
        android:id="@+id/btn_gray_process"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/img_huaishi"
        android:layout_centerHorizontal="true"
        android:text="Grayscale"/>"
</RelativeLayout>

Then add in MainActivity

public class MainActivity extends AppCompatActivity {
    Button btnProcess;
    Bitmap srcBitmap;
    Bitmap grayBitmap;
    ImageView imgHuaishi;
    private static boolean flag = true;
    //private static boolean isFirst = true;
    private static final String TAG = "MainActivity";

    //OpenCV library loads and initializes callback functions after success
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {

        @Override
        public void onManagerConnected(int status) {
            // TODO Auto-generated method stub
            switch (status){
                case BaseLoaderCallback.SUCCESS:
                    Log.i(TAG, "Successful loading");
                    break;
                default:
                    super.onManagerConnected(status);
                    Log.i(TAG, "Load failure");
                    break;
            }

        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initUI();
        btnProcess.setOnClickListener(new ProcessClickListener());
    }
    public void initUI(){
        btnProcess = (Button)findViewById(R.id.btn_gray_process);
        imgHuaishi = (ImageView)findViewById(R.id.img_huaishi);
        Log.i(TAG, "initUI sucess...");

    }

    public void procSrc2Gray(){
        Mat rgbMat = new Mat();
        Mat grayMat = new Mat();
        srcBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.text_img);
        grayBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), Bitmap.Config.RGB_565);
        Utils.bitmapToMat(srcBitmap, rgbMat);//convert original bitmap to Mat, R G B.
        Imgproc.cvtColor(rgbMat, grayMat, Imgproc.COLOR_RGB2GRAY);//rgbMat to gray grayMat
        Utils.matToBitmap(grayMat, grayBitmap); //convert mat to bitmap
        Log.i(TAG, "procSrc2Gray sucess...");
    }

    private class ProcessClickListener implements View.OnClickListener {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
//            if(isFirst)
//            {
                procSrc2Gray();
//                isFirst = false;
//            }
            if(flag){
                imgHuaishi.setImageBitmap(grayBitmap);
                btnProcess.setText("View Original Image");
                flag = false;
            }
            else{
                imgHuaishi.setImageBitmap(srcBitmap);
                btnProcess.setText("Grayscale");
                flag = true;
            }
        }

    }

    @Override
    public void onResume()
    {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_10, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }
}

Then run your app on the real machine and see if you don't need to install OpenCVManager anymore.

Well

Next, we use Sift algorithm to extract features in OpenCV4Android.
First, go to the OpenCV official website to download an OpenCV source package that you are currently using.
Then the
you
Paths to your OpenCV source > modules nonfree include opencv2 nonfree
The following four files are copied to feature2d.hpp gpu.hpp nonfree.hpp ocl.hpp
This step is very important in \ sdk native jni include opencv2 nonfree \ your OpenCV4Android path \ which is not mentioned in many blogs. It has made me take a lot of detours when compiling ndk.

Then find four files in OpenCV source, nonfree_init.cpp precomp.hpp sift.cpp surf.cpp. I add surf here as well.
Modify the precomp.hpp file and remove # include "cvconfig.h" and # include "opencv2/ocl/private/util.cpp".
Modify the nonfree_init.cpp file to remove the lines starting with #ifdef HAVE_OPENCV_OCL and ending with #endif
The nonfree_init.cpp is modified as follows

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                          License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "precomp.hpp"

namespace cv
{

///////////////////////////////////////////////////////////////////////////////////////////////////////////

CV_INIT_ALGORITHM(SURF, "Feature2D.SURF",
                  obj.info()->addParam(obj, "hessianThreshold", obj.hessianThreshold);
                  obj.info()->addParam(obj, "nOctaves", obj.nOctaves);
                  obj.info()->addParam(obj, "nOctaveLayers", obj.nOctaveLayers);
                  obj.info()->addParam(obj, "extended", obj.extended);
                  obj.info()->addParam(obj, "upright", obj.upright))

///////////////////////////////////////////////////////////////////////////////////////////////////////////

CV_INIT_ALGORITHM(SIFT, "Feature2D.SIFT",
                  obj.info()->addParam(obj, "nFeatures", obj.nfeatures);
                  obj.info()->addParam(obj, "nOctaveLayers", obj.nOctaveLayers);
                  obj.info()->addParam(obj, "contrastThreshold", obj.contrastThreshold);
                  obj.info()->addParam(obj, "edgeThreshold", obj.edgeThreshold);
                  obj.info()->addParam(obj, "sigma", obj.sigma))

//#ifdef HAVE_OPENCV_OCL
//
//namespace ocl {
//CV_INIT_ALGORITHM(SURF_OCL, "Feature2D.SURF_OCL",
//                  obj.info()->addParam(obj, "hessianThreshold", obj.hessianThreshold);
//                  obj.info()->addParam(obj, "nOctaves", obj.nOctaves);
//                  obj.info()->addParam(obj, "nOctaveLayers", obj.nOctaveLayers);
//                  obj.info()->addParam(obj, "extended", obj.extended);
//                  obj.info()->addParam(obj, "upright", obj.upright))
//}
//
//#endif


///////////////////////////////////////////////////////////////////////////////////////////////////////////

bool initModule_nonfree(void)
{
    Ptr<Algorithm> sift = createSIFT(), surf = createSURF();
    return sift->info() != 0 && surf->info() != 0;
}

}

precomp.hpp is as follows

/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                          License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__

//#include "cvconfig.h"

#include "opencv2/opencv_modules.hpp"

#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/internal.hpp"

#include "opencv2/nonfree/gpu.hpp"

#if defined(HAVE_CUDA) && defined(HAVE_OPENCV_GPU) && !defined(DYNAMIC_CUDA_SUPPORT)
    #include "opencv2/gpu/stream_accessor.hpp"
    #include "opencv2/gpu/device/common.hpp"
    static inline void throw_nogpu() { CV_Error(CV_StsNotImplemented, "The called functionality is disabled for current build or platform"); }
#else
    static inline void throw_nogpu() { CV_Error(CV_GpuNotSupported, "The library is compiled without GPU support"); }
#endif

#ifdef HAVE_OPENCV_OCL
#  include "opencv2/nonfree/ocl.hpp"
//#  include "opencv2/ocl/private/util.hpp"
#endif

#endif

Then add an Android.mk and Application.mk to compile and use the ndk
Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on

include F:\OpenCV-2.4.10-android-sdk\sdk\native\jni\OpenCV.mk

LOCAL_MODULE    := nonfree
LOCAL_SRC_FILES := nonfree_init.cpp \
sift.cpp \
surf.cpp
LOCAL_LDLIBS +=  -llog -ldl

include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi armeabi-v7a x86 mips
APP_PLATFORM := android-19

Note that APP_PLATFORM here is based on your smallest compiled version, otherwise it will make mistakes.

Then we go back to the project and create a new jni file under / src and add it to build.gradle

   sourceSets.main {
        jniLibs.srcDir 'src/main/libs'
        jni.srcDirs = [] //Turn off the auto-call ndk-build command
    }

Now open your CMD CD and go to this jni directory to generate. so files directly from ndk-build. Then you can find the generated. so file under your src/obj folder. We move the generated libnonfree.so to lib in the moudle. Then add it to the code just now.
System.loadLibrary("nonfree"); load it.

    //OpenCV library loads and initializes callback functions after success
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {

        @Override
        public void onManagerConnected(int status) {
            // TODO Auto-generated method stub
            switch (status){
                case BaseLoaderCallback.SUCCESS:
                    Log.i(TAG, "Successful loading");
                    System.loadLibrary("nonfree");
                    break;
                default:
                    super.onManagerConnected(status);
                    Log.i(TAG, "Load failure");
                    break;
            }

        }
    };

Then look at the documentation and use sift to do what you love to do.

Note that this article is only recommended for OpenCV4Android 2.x to experience new features
http://johnhany.net/ I also learned a lot from this blog.

Posted by dnast on Tue, 01 Jan 2019 16:45:08 -0800