androidstudio opencv2.4.10下使用图像拼接,特征检测-阿里云开发者社区

开发者社区> 开发与运维> 正文

androidstudio opencv2.4.10下使用图像拼接,特征检测

简介: 说明好处:不需要额外安装apk ,java程序代码,不需要深入c++ ,要会点ndk知识  1:下载OpenCV-2.4.

说明好处:不需要额外安装apk ,java程序代码,不需要深入c++ ,要会点ndk知识 


1:下载OpenCV-2.4.10-android-sdk 和 OpenCV-2.4.10-android-nonfree-dir(这个主要用于sift surf特征编译成libnonfree.so用法  android opencv2.4.10使用SIFT编译出libnonfree.so 

2 androidstudio新建项目 myopencv-stitching

3拷贝OpenCV-2.4.10-android-sdk/sdk/native/jni/include/opencv2到项目  myopencv-stitching/app/src/main/jni  下

4在jin下添加Android.mk Application.mk stitcher.cpp三个文件

5修改Android.mk

OPENCV_PATH := /Users/xiaoying/Downloads/OpenCV-2.4.10-android-sdk/sdk/native/jni
include $(OPENCV_PATH)/OpenCV.mk

LOCAL_MODULE    := stitcher
LOCAL_SRC_FILES := stitcher.cpp

7.build.gradle添加 android{  添加  }

sourceSets.main.jni.srcDirs = []
//禁止自带的ndk功能
sourceSets.main.jniLibs.srcDirs = ['src/main/libs', 'src/main/jniLibs']
//重定向so目录为src/main/libs,原来为src/main/jniLibs

task ndkBuild(type: Exec, description: 'Compile JNI source with NDK') {
    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream())
    def ndkDir = properties.getProperty('ndk.dir')

    if (org.apache.tools.ant.taskdefs.condition.Os.isFamily(org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS)) {
        commandLine "$ndkDir/ndk-build.cmd", '-C', file('src/main/jni').absolutePath
    } else {
        commandLine "$ndkDir/ndk-build", '-C', file('src/main/jni').absolutePath
    }
}

tasks.withType(JavaCompile) {
    compileTask -> compileTask.dependsOn ndkBuild
}

task ndkClean(type: Exec, description: 'Clean NDK Binaries') {
    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream())
    def ndkDir = properties.getProperty('ndk.dir')

    if (org.apache.tools.ant.taskdefs.condition.Os.isFamily(org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS)) {
        commandLine "$ndkDir/ndk-build.cmd", 'clean', '-C', file('src/main/jni').absolutePath
    } else {
        commandLine "$ndkDir/ndk-build", 'clean', '-C', file('src/main/jni').absolutePath
    }
}

clean.dependsOn 'ndkClean'

8在 grale.properties里添加

android.useDeprecatedNdk=true


9会配置ndk的,右键jni就能编译ndk了,编译成功会在libs下生成:libstitcher.so ,libopencv_java.so,zlibnative_camera_r2.2.0.so等(在这里图像拼接so库就好了)


接下来先看看

http://www.2cto.com/kf/201511/448267.html


10 java和jin混用,在此之前,我们需要将sdk目录中的java代码拷到项目中去,java代码在sdk simple里 

这里写图片描述

但是org.opencv.engine包中是一个aidl,我们需要将它剪贴到aidl目录中去,就像这样子

这里写图片描述

最后还有一个资源文件attrs.xml,拷过来

这里写图片描述

build一下项目,不出意外应该会报错,这时候找到该类,引入自己的R文件包就可以了

这里写图片描述

再次build应该就不会有什么问题了。

就可以愉快的玩耍了了


11:新建MainActivity, 加载opencv和stitcher库(这个名字在android.mk中自定义的)


public class MainActivity extends AppCompatActivity {


    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS: {
                    Log.i("----------", "OpenCV loaded successfully");

                    System.loadLibrary("stitcher");
                }
                break;
                default: {
                    super.onManagerConnected(status);
                }
                break;
            }
        }
    };

    public void onResume() {
        super.onResume();
        if (OpenCVLoader.initDebug()) {
            Log.d("---------------", "openCV库加载完成,你可以愉快的玩耍了");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


    }
}

12:最后面具体设计图像拼接,(注意这里面不包含sift,surt这两个功能)


展示代码

public class StitchingActivity extends Activity {

    private final int CLICK_PHOTO = 1;
    private Uri fileUri;
    private ImageView ivImage;
    Mat src;
    ArrayList<Mat> clickedImages;
    private static final String FILE_LOCATION = Environment.getExternalStorageDirectory() + "/Download/PacktBook/Chapter6/";
    static int ACTION_MODE = 0, MODE_NONE = 0;

    private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                    System.loadLibrary("stitcher");
                    //DO YOUR WORK/STUFF HERE
                    break;
                default:
                    super.onManagerConnected(status);
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_stitching);
        ivImage = (ImageView)findViewById(R.id.ivImage);
        Button bClickImage, bDone;
        clickedImages = new ArrayList<Mat>();

        bClickImage = (Button)findViewById(R.id.bClickImage);
        bDone = (Button)findViewById(R.id.bDone);

        bClickImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                File imagesFolder = new File(FILE_LOCATION);
                imagesFolder.mkdirs();
                File image = new File(imagesFolder, "panorama_"+ (clickedImages.size()+1) + ".jpg");
                fileUri = Uri.fromFile(image);
                Log.d("StitchingActivity", "File URI = " + fileUri.toString());
                intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

                // start the image capture Intent
                startActivityForResult(intent, CLICK_PHOTO);
            }
        });

        bDone.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("-----------------", "111111111");
                if(clickedImages.size()==0){
                    Log.d("-----------------", "2222222");
                    Toast.makeText(getApplicationContext(), "No images clicked", Toast.LENGTH_SHORT).show();
                } else if(clickedImages.size()==1){
                    Log.d("-----------------", "3333333333");
                    Toast.makeText(getApplicationContext(), "Only one image clicked", Toast.LENGTH_SHORT).show();
                    Bitmap image = Bitmap.createBitmap(src.cols(), src.rows(), Bitmap.Config.ARGB_8888);
                    Utils.matToBitmap(src, image);
                    ivImage.setImageBitmap(image);
                } else {
                    Log.d("-----------------", "44444444");
                    createPanorama();
                }
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_pyramid, menu);
        return true;
    }

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

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
        super.onActivityResult(requestCode, resultCode, imageReturnedIntent);

        Log.d("-----------------", requestCode + " " + CLICK_PHOTO + " " + resultCode + " " + RESULT_OK);

        switch(requestCode) {
            case CLICK_PHOTO:
                if(resultCode == RESULT_OK){
                    try {
//                        final Uri imageUri = imageReturnedIntent.getData();
                        Log.d("-------------------照片返回", fileUri.toString());
                        final InputStream imageStream = getContentResolver().openInputStream(fileUri);
                        final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
                        src = new Mat(selectedImage.getHeight(), selectedImage.getWidth(), CvType.CV_8UC4);
                        Imgproc.resize(src, src, new Size(src.rows()/4, src.cols()/4));
                        Utils.bitmapToMat(selectedImage, src);
                        Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2RGB);
                        clickedImages.add(src);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
                break;
        }
    }

    private void createPanorama(){

        new AsyncTask<Void, Void, Bitmap>() {
            ProgressDialog dialog;
            @Override
            protected void onPreExecute() {
                super.onPreExecute();
                dialog = ProgressDialog.show(StitchingActivity.this, "Building Panorama", "Please Wait");
            }

            @Override
            protected Bitmap doInBackground(Void... params) {
                Mat srcRes = new Mat();


                Log.d("---------------","array:"+clickedImages.toArray()+"-------size:"+clickedImages.size()+"-----pash:"+srcRes.getNativeObjAddr());

                int success = StitchPanorama(clickedImages.toArray(), clickedImages.size(), srcRes.getNativeObjAddr());
                Log.d("--------------------", srcRes.rows()+" "+srcRes.cols()+" "+success);
                if(success==0){
                    Log.d("---------------", "为0");
                    return null;
                }

                Imgproc.cvtColor(srcRes, srcRes, Imgproc.COLOR_BGR2RGBA);
                Bitmap bitmap = Bitmap.createBitmap(srcRes.cols(), srcRes.rows(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(srcRes, bitmap);
                Log.d("-----------------", "返回图像");
                return bitmap;
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                super.onPostExecute(bitmap);
                dialog.dismiss();
                if(bitmap!=null) {
                    ivImage.setImageBitmap(bitmap);
                }
            }
        }.execute();
    }

//    @Override
//    protected void onResume() {
//        super.onResume();
//        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_10, this,
//                mOpenCVCallBack);
//    }


    public void onResume() {
        super.onResume();
        if (OpenCVLoader.initDebug()) {
            Log.d("---------------", "openCV库加载完成,你可以愉快的玩耍了");
            mOpenCVCallBack.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }



    public native int StitchPanorama(Object images[], int size, long addrSrcRes);

}

stitcher.cpp

#include <jni.h>
#include <vector>

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <opencv2/stitching/stitcher.hpp>

using namespace cv;
using namespace std;

char filepath1[100] = "/storage/emulated/0/Download/PacktBook/Chapter6/panorama_stitched.jpg";

extern "C" {

    JNIEXPORT jint JNICALL Java_com_keller_myopencvstitching_StitchingActivity_StitchPanorama(JNIEnv*, jobject, jobjectArray, jint, jlong);
    JNIEXPORT jint JNICALL Java_com_keller_myopencvstitching_StitchingActivity_StitchPanorama(JNIEnv* env, jobject, jobjectArray images, jint size, jlong resultMatAddr)
    {
        jint result = 0;
        vector<Mat> clickedImages = vector<Mat>();
        Mat& srcRes = *(Mat*)resultMatAddr, img;
        Mat output_stitched = Mat();

        jclass clazz = (env)->FindClass("org/opencv/core/Mat");
        jmethodID getNativeObjAddr = (env)->GetMethodID(clazz, "getNativeObjAddr", "()J");

        for(int i=0; i < size; i++){
            jobject obj = (env->GetObjectArrayElement(images, i));
            jlong result = (env)->CallLongMethod(obj, getNativeObjAddr, NULL);
            img = *(Mat*)result;
            resize(img, img, Size(img.rows/10, img.cols/10));
            clickedImages.push_back(img);
            env->DeleteLocalRef(obj);
        }
        env->DeleteLocalRef(images);

        Stitcher stitcher = Stitcher::createDefault();
        Stitcher::Status status = stitcher.stitch(clickedImages, output_stitched);

        output_stitched.copyTo(srcRes);

        imwrite(filepath1, srcRes);

        if (status == Stitcher::OK)
            result = 1;
        else
            result = 0;

        return result;
    }
}




版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章