여기서 이어지는 글입니다. 원래 출처인 http://webnautes.tistory.com/923 이 글을 보고 맥에서 따라 해보는데 굳이 필요 없는 부분이라던지 맥이라 조금씩 다른 부분 고쳐가면서 정리한 글입니다.
참고 사이트
http://docs.opencv.org/2.4/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.html
http://webnautes.tistory.com/923
그럼 시작…
File->New-> Import Module을 선택합니다.
그리고 OpenCV SDK에서 위 이미지 처럼 sdk/java 폴더를 선택합니다.
(자동검색해서 하위 선택하지 않을까 해서 그냥 SDK상위 폴더 선택하니
이클립스 플젝이나 안드로이드 스튜디오 기본형식 폴더가 아님 안된다고 에러뜸)
좋은 내용이니 잘 새겨들읍시다.. ㅋㅋㅋ
추가 다하고 보면 에러 납니다.
이거 기본 build.gradle이 안드로이드 SDK 14로 설정되어 있어서 생기는 문제입니다.
apply plugin: 'com.android.library' android { compileSdkVersion 14 buildToolsVersion "19.1.0" defaultConfig { minSdkVersion 8 targetSdkVersion 21 }
이렇게 되어 있는데 이걸 아래와 같이 바꿨습니다.
apply plugin: 'com.android.library' android { compileSdkVersion 22 buildToolsVersion "24.0.1" defaultConfig { minSdkVersion 22 targetSdkVersion 22 }
본인 컴에 깔려있는 빌드툴 버전이랑 SDK 버전에 맞게 고치면 됩니다.
⌘ + ; 를 눌러서 Project Structure… 로 들어가서 위 이미지 처럼 Module dependency를 추가합니다.
아까 추가한 OpenCVLibrary310를 선택해줍니다.
jni 폴더에 아래 내용으로 android.mk 파일을 추가해줍니다.
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) #opencv OPENCVROOT:= /Users/linsoo/Desktop/Develop/SDK/OpenCV-android-sdk OPENCV_CAMERA_MODULES:=on OPENCV_INSTALL_MODULES:=on OPENCV_LIB_TYPE:=SHARED include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk LOCAL_SRC_FILES := kr_co_linsoo_opencvtest_MainActivity.cpp LOCAL_LDLIBS += -llog LOCAL_MODULE := nativegray include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS)
jni 폴더에 아래 내용으로 Application.mk 파일을 추가해줍니다.
APP_ABI := armeabi APP_PLATFORM := android-22 APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions
하이라이트 부분 본인의 컴에 맞게 잘 확인해서 수정합니다.
이제 app의 build.gradle 을 수정합니다.
apply plugin: 'com.android.application' android { compileSdkVersion 22 buildToolsVersion "24.0.1" defaultConfig { applicationId "kr.co.linsoo.opencvtest" minSdkVersion 22 targetSdkVersion 22 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } //------------------------------------------------------------------------------------------ //여기 추가된부분 android { sourceSets { main { jni.srcDirs = [] } } } task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') { def ndkDir = project.plugins.findPlugin('com.android.application').sdkHandler.getNdkFolder() commandLine "$ndkDir/ndk-build", 'NDK_PROJECT_PATH=build/intermediates/ndk', 'NDK_LIBS_OUT=src/main/jniLibs', 'APP_BUILD_SCRIPT=src/main/jni/Android.mk', 'NDK_APPLICATION_MK=src/main/jni/Application.mk' } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild } //------------------------------------------------------------------------------------------ dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:22.2.1' compile project(':openCVLibrary310') }
중간에
//———————-
여기 추가된 부분
…..
//———————-
의 내용을 추가해줍니다.
이제 AndroidManifest.xml에 카메라 권한을 넣어줍니다.
출처에는 이것저것 넣긴 했는데 그냥
<uses-permission android:name="android.permission.CAMERA"/>
이거 하나만 넣어도 되긴 합니다.
다른건 설치할때 권한 표기 안하게 하는거랑 화면 사이즈 관련해서 옵션이라
activity_main.xml에는 다른것들도 넣어도 상관없지만 일단 샘플이니
<org.opencv.android.JavaCameraView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/activity_surface_view" />
이거 하나만 넣어줍니다. (실제 카메라 뷰가 나올거)
MainActivity.java 파일
package kr.co.linsoo.opencvtest; import android.app.Activity; import android.os.Bundle; import android.util.Log; 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.CvType; import org.opencv.core.Mat; public class MainActivity extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 { public native int convertNativeGray(long matAddrRgba, long matAddrGray); private Mat mRgba, mGray; private CameraBridgeViewBase mOpenCvCameraView; static { System.loadLibrary("opencv_java3"); } private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS:{ Log.i("linsoo", "OpenCV loaded successfully"); System.loadLibrary("nativegray");// Load Native module mOpenCvCameraView.enableView(); } break; default: super.onManagerConnected(status); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags( WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); setContentView(R.layout.activity_main); mOpenCvCameraView = (CameraBridgeViewBase)findViewById(R.id.activity_surface_view); mOpenCvCameraView.setCvCameraViewListener(this); } @Override public void onPause() { super.onPause(); if (mOpenCvCameraView != null) mOpenCvCameraView.disableView(); } @Override public void onResume() { super.onResume(); if (OpenCVLoader.initDebug() == false) { Log.d("linsoo", "Internal OpenCV library not found."); OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this,mLoaderCallback); } else { Log.d("linsoo", "OpenCV library found inside package. Using it!"); mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS); } } public void onDestroy() { super.onDestroy(); if (mOpenCvCameraView != null) mOpenCvCameraView.disableView(); } @Override public void onCameraViewStarted(int width, int height) { } @Override public void onCameraViewStopped() { } @Override public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { if (inputFrame.rgba() != null) { mRgba = inputFrame.rgba(); if ( mGray!=null ) mGray.release(); mGray = new Mat( inputFrame.rgba().rows(),inputFrame.rgba().cols(), CvType.CV_8UC1); convertNativeGray(mRgba.getNativeObjAddr(),mGray.getNativeObjAddr()); } return mGray; } }
대충 어떻게 돌아가는건지는 알겠는데
일일히 설명할 필요는 없을거 같고 opencv 매뉴얼 찾아보면 의미를 알수 있겠죠
kr_co_linsoo_opencvtest_MainActivity.cpp
// // Created by linsoo on 2016. 8. 26.. // #include "kr_co_linsoo_opencvtest_MainActivity.h" #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <stdio.h> using namespace std; using namespace cv; int toGray(Mat img, Mat& gray); JNIEXPORT jint JNICALL Java_kr_co_linsoo_opencvtest_MainActivity_convertNativeGray(JNIEnv*, jobject, jlong addrRgba, jlong addrGray); //------------------------------------------------------- JNIEXPORT jint JNICALL Java_kr_co_linsoo_opencvtest_MainActivity_convertNativeGray(JNIEnv*, jobject, jlong addrRgba, jlong addrGray) { Mat& mRgb = *(Mat*)addrRgba; Mat& mGray = *(Mat*)addrGray; int conv; jint retVal; conv = toGray(mRgb, mGray); retVal = (jint)conv; return retVal; } int toGray(Mat img, Mat& gray){ cvtColor(img, gray, CV_RGBA2GRAY); if (gray.rows == img.rows && gray.cols == img.cols) return (1); return(0); }
kr_co_linsoo_opencvtest_MainActivity.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class kr_co_linsoo_opencvtest_MainActivity */ #ifndef _Included_kr_co_linsoo_opencvtest_MainActivity #define _Included_kr_co_linsoo_opencvtest_MainActivity #ifdef __cplusplus extern "C" { #endif /* * Class: kr_co_linsoo_opencvtest_MainActivity * Method: hello * Signature: ()Ljava/lang/String; */ JNIEXPORT jint JNICALL Java_kr_co_linsoo_opencvtest_MainActivity_convertNativeGray(JNIEnv*, jobject, jlong addrRgba, jlong addrGray); #ifdef __cplusplus } #endif #endif
이정도 소스 넣어주고 빌드 하면 실행된다.
OpenCV는 윈도우에서 카메라 영상 받아서 뿌려주는거 밖에 안해봐서 잘은 모르지만
요거 좀 응용하면 윈도우에서 쓰던거 처럼 쓸수는 있을듯 싶음.
다음엔 NDK 가지고 예전에 java로 이미지 확대 하던 소스 두개 성능 비교하는거 만들어 봐야 겠음.
똑같은 소스 가지고 돌렸을때 차이가 있는지… (내가 코드 못만들어서 느린건지 java라 느렸던건지 궁금했음)
답글 남기기