안녕하세요 : )


NDK를 지원하는 안드로이드 프로젝트를 생성한 후, OpenCV 라이브러리를 추가하여 사용하는 방법을 설명합니다. 


간단한 예제로 OpenCV Java API에서 캡처한 영상을 OpenCV C++ API에서 그레이스케일 영상으로 변환하고 다시  OpenCV Java API에서 화면에 보여줍니다. 


OpenCV 4.1.1에서 기존 자바 코드가 문제 있어서 수정했습니다.

(카메라 권한 관련 함수가 OpenCV의 카메라 API에 추가되어 있네요.)


OpenCV 4.1.0 이하에서 사용하던 코드도 혹시 몰라 남겨둡니다.




2016.11.20 : 최초 작성 


2019. 8. 8 : 최종 업데이트

OpenCV 4.1.1를 위해 카메라 코드를 수정하고 android.support 대신에 androidx를 사용합니다.  


2020. 1. 19

OpenCV 4.2.0과 최신 안드로이드 환경에서 테스트 해봤습니다.

별문제 없이 동작합니다.


Windows 10

OpenCV 4.2.0

Android Studio 3.5.3

Android 10

NDK 21




Andrid 3.5.1, OpenCV 4.1.2에서 문제 없이 동작했습니다.

OpenCV 4.1.1 이상에서 사용하세요.


테스트 환경


Windows 10

OpenCV 4.1.2

Android Studio 3.5.1

Android 10.0(API 29)

NDK 20




아래에 영상에서 사용한 코드를  모아두었습니다. 



1. bit.ly/88-01


<!-- No Title Bar-->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>




2. bit.ly/88-02


<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:orientation="vertical"
    tools:context=".MainActivity">

    <org.opencv.android.JavaCameraView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        opencv:camera_id="any"
        android:visibility="gone"
        android:id="@+id/activity_surface_view" />

</LinearLayout>




3. bit.ly/88-03


<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"/>

<supports-screens android:resizeable="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />




4. bit.ly/88-04


<activity android:name=".MainActivity"
android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">




5. bit.ly/88-05


import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.DialogInterface;
import android.os.Bundle;
import android.annotation.TargetApi;
import android.content.pm.PackageManager;
import android.os.Build;
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 java.util.Collections;
import java.util.List;

import static android.Manifest.permission.CAMERA;


public class MainActivity extends AppCompatActivity
        implements CameraBridgeViewBase.CvCameraViewListener2 {

    private static final String TAG = "opencv";
    private Mat matInput;
    private Mat matResult;

    private CameraBridgeViewBase mOpenCvCameraView;

    public native void ConvertRGBtoGray(long matAddrInput, long matAddrResult);


    static {
        System.loadLibrary("opencv_java4");
        System.loadLibrary("native-lib");
    }



    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    mOpenCvCameraView.enableView();
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.activity_main);

        mOpenCvCameraView = (CameraBridgeViewBase)findViewById(R.id.activity_surface_view);
        mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);
        mOpenCvCameraView.setCameraIndex(0); // front-camera(1),  back-camera(0)
    }

    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume()
    {
        super.onResume();

        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "onResume :: Internal OpenCV library not found.");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_2_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "onResum :: 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) {

        matInput = inputFrame.rgba();

        if ( matResult == null )

            matResult = new Mat(matInput.rows(), matInput.cols(), matInput.type());

        ConvertRGBtoGray(matInput.getNativeObjAddr(), matResult.getNativeObjAddr());

        return matResult;
    }


    protected List<? extends CameraBridgeViewBase> getCameraViewList() {
        return Collections.singletonList(mOpenCvCameraView);
    }


    //여기서부턴 퍼미션 관련 메소드
    private static final int CAMERA_PERMISSION_REQUEST_CODE = 200;


    protected void onCameraPermissionGranted() {
        List<? extends CameraBridgeViewBase> cameraViews = getCameraViewList();
        if (cameraViews == null) {
            return;
        }
        for (CameraBridgeViewBase cameraBridgeViewBase: cameraViews) {
            if (cameraBridgeViewBase != null) {
                cameraBridgeViewBase.setCameraPermissionGranted();
            }
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        boolean havePermission = true;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (checkSelfPermission(CAMERA) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
                havePermission = false;
            }
        }
        if (havePermission) {
            onCameraPermissionGranted();
        }
    }

    @Override
    @TargetApi(Build.VERSION_CODES.M)
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            onCameraPermissionGranted();
        }else{
            showDialogForPermission("앱을 실행하려면 퍼미션을 허가하셔야합니다.");
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }


    @TargetApi(Build.VERSION_CODES.M)
    private void showDialogForPermission(String msg) {

        AlertDialog.Builder builder = new AlertDialog.Builder( MainActivity.this);
        builder.setTitle("알림");
        builder.setMessage(msg);
        builder.setCancelable(false);
        builder.setPositiveButton("예", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id){
                requestPermissions(new String[]{CAMERA}, CAMERA_PERMISSION_REQUEST_CODE);
            }
        });
        builder.setNegativeButton("아니오", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface arg0, int arg1) {
                finish();
            }
        });
        builder.create().show();
    }


}




6. bit.ly/88-06


안드로이드 스튜디오 또는 NDK 버전에 따라 matAddrInput 대신에 mat_addr_input를

matAddrResult 대신에 mat_addr_result를 적어야 하는 경우가 있습니다. 


함수의 파라미터 이름과 비교해서 적으세요. 


#include <opencv2/opencv.hpp>

using namespace cv;




Mat &matInput = *(Mat *)matAddrInput;
Mat &matResult = *(Mat *)matAddrResult;

cvtColor(matInput, matResult, COLOR_RGBA2GRAY);




7. bit.ly/88-07


# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

set(pathPROJECT C:/Users/webnautes/AndroidStudioProjects/UseOpenCVwithCMake) # 수정필요
set(pathOPENCV ${pathPROJECT}/opencv)
set(pathLIBOPENCV_JAVA ${pathOPENCV}/native/libs/${ANDROID_ABI}/libopencv_java4.so)

set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

include_directories(${pathOPENCV}/native/jni/include)


# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ${pathPROJECT}/app/src/main/cpp/native-lib.cpp )



add_library( lib_opencv SHARED IMPORTED )

set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${pathLIBOPENCV_JAVA})


# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        native-lib

        lib_opencv

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib} )






아래 부분은 OpenCV 4.1.0 이하에서 사용가능합니다.

테스트 환경은 다음과 같습니다.


Windows 10

OpenCV 4.1.0

Android Studio 3.4

Android 9.0 (API 28)

NDK 19




메뉴에서 Help > Check for Updates를 선택하여

Android Studio 3.4로 업데이트후 진행하세요




아래에 영상에서 사용한 코드를 모아두었습니다.


bit.ly/1054-01


<!-- No Title Bar-->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>



bit.ly/1054-02


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
   tools:context=".MainActivity" >
   
   <org.opencv.android.JavaCameraView
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:id="@+id/activity_surface_view" />

</LinearLayout>



bit.ly/1054-03


<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"/>

<supports-screens android:resizeable="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />



bit.ly/1054-04


<activity android:name=".MainActivity"
android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">



bit.ly/1054-05


import android.annotation.TargetApi;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
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;


public class MainActivity extends AppCompatActivity
       implements CameraBridgeViewBase.CvCameraViewListener2 {

   private static final String TAG = "opencv";
   private CameraBridgeViewBase mOpenCvCameraView;
   private Mat matInput;
   private Mat matResult;

   public native void ConvertRGBtoGray(long matAddrInput, long matAddrResult);


   static {
       System.loadLibrary("opencv_java4");
       System.loadLibrary("native-lib");
   }



   private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
       @Override
       public void onManagerConnected(int status) {
           switch (status) {
               case LoaderCallbackInterface.SUCCESS:
               {
                   mOpenCvCameraView.enableView();
               } break;
               default:
               {
                   super.onManagerConnected(status);
               } break;
           }
       }
   };


   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);

       getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
               WindowManager.LayoutParams.FLAG_FULLSCREEN);
       getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
               WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

       setContentView(R.layout.activity_main);


       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
           //퍼미션 상태 확인
           if (!hasPermissions(PERMISSIONS)) {

               //퍼미션 허가 안되어있다면 사용자에게 요청
               requestPermissions(PERMISSIONS, PERMISSIONS_REQUEST_CODE);
           }
       }

       mOpenCvCameraView = (CameraBridgeViewBase)findViewById(R.id.activity_surface_view);
       mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
       mOpenCvCameraView.setCvCameraViewListener(this);
       mOpenCvCameraView.setCameraIndex(0); // front-camera(1),  back-camera(0)
       mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
   }

   @Override
   public void onPause()
   {
       super.onPause();
       if (mOpenCvCameraView != null)
           mOpenCvCameraView.disableView();
   }

   @Override
   public void onResume()
   {
       super.onResume();

       if (!OpenCVLoader.initDebug()) {
           Log.d(TAG, "onResume :: Internal OpenCV library not found.");
           OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_2_0, this, mLoaderCallback);
       } else {
           Log.d(TAG, "onResum :: 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) {

       matInput = inputFrame.rgba();

        //if ( matResult != null ) matResult.release(); fix 2018. 8. 18

        if ( matResult == null )

           matResult = new Mat(matInput.rows(), matInput.cols(), matInput.type());

       ConvertRGBtoGray(matInput.getNativeObjAddr(), matResult.getNativeObjAddr());

       return matResult;
   }



   //여기서부턴 퍼미션 관련 메소드
   static final int PERMISSIONS_REQUEST_CODE = 1000;
   String[] PERMISSIONS  = {"android.permission.CAMERA"};


   private boolean hasPermissions(String[] permissions) {
       int result;

       //스트링 배열에 있는 퍼미션들의 허가 상태 여부 확인
       for (String perms : permissions){

           result = ContextCompat.checkSelfPermission(this, perms);

           if (result == PackageManager.PERMISSION_DENIED){
               //허가 안된 퍼미션 발견
               return false;
           }
       }

       //모든 퍼미션이 허가되었음
       return true;
   }



   @Override
   public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                          @NonNull int[] grantResults) {
       super.onRequestPermissionsResult(requestCode, permissions, grantResults);

       switch(requestCode){

           case PERMISSIONS_REQUEST_CODE:
               if (grantResults.length > 0) {
                   boolean cameraPermissionAccepted = grantResults[0]
                           == PackageManager.PERMISSION_GRANTED;

                   if (!cameraPermissionAccepted)
                       showDialogForPermission("앱을 실행하려면 퍼미션을 허가하셔야합니다.");
               }
               break;
       }
   }


   @TargetApi(Build.VERSION_CODES.M)
   private void showDialogForPermission(String msg) {

       AlertDialog.Builder builder = new AlertDialog.Builder( MainActivity.this);
       builder.setTitle("알림");
       builder.setMessage(msg);
       builder.setCancelable(false);
       builder.setPositiveButton("예", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface dialog, int id){
               requestPermissions(PERMISSIONS, PERMISSIONS_REQUEST_CODE);
           }
       });
       builder.setNegativeButton("아니오", new DialogInterface.OnClickListener() {
           public void onClick(DialogInterface arg0, int arg1) {
               finish();
           }
       });
       builder.create().show();
   }


}



bit.ly/1054-05-2


#include <opencv2/opencv.hpp>

using namespace cv;




Mat &matInput = *(Mat *)matAddrInput;
Mat &matResult = *(Mat *)matAddrResult;

cvtColor(matInput, matResult, COLOR_RGBA2GRAY);



bit.ly/1054-06


# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

set(pathPROJECT C:/Users/webnautes/AndroidStudioProjects/UseOpenCVwithCMake) # 수정필요
set(pathOPENCV ${pathPROJECT}/opencv)
set(pathLIBOPENCV_JAVA ${pathOPENCV}/native/libs/${ANDROID_ABI}/libopencv_java4.so)

set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

include_directories(${pathOPENCV}/native/jni/include)


# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
       native-lib

       # Sets the library as a shared library.
       SHARED

       # Provides a relative path to your source file(s).
       ${pathPROJECT}/app/src/main/cpp/native-lib.cpp )



add_library( lib_opencv SHARED IMPORTED )

set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${pathLIBOPENCV_JAVA})


# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
       log-lib

       # Specifies the name of the NDK library that
       # you want CMake to locate.
       log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
       native-lib

       lib_opencv

       # Links the target library to the log library
       # included in the NDK.
       ${log-lib} )



참고


https://developer.android.com/ndk/guides/index.html


https://developer.android.com/studio/projects/add-native-code.html


https://github.com/googlesamples/android-ndk


http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html


http://docs.opencv.org/2.4/doc/tutorials/introduction/android_binary_package/dev_with_OCV_on_Android.html





포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

유튜브 구독하기

  1. 이전 댓글 더보기
  2. it응용 2019.08.07 18:03

    혹시나 OpenCV 4.0.1 버전을 사용한게 문제가 될까요..?
    그리고 cvtcolor 함수를 주석처리하고 빌드해보니 아래와 같은 오류가 뜹니다.

    [1/2] Building CXX object CMakeFiles/native-lib.dir/native-lib.cpp.o
    [2/2] Linking CXX shared library C:\Users\SIALAB\AndroidStudioProjects\OpenCVExample\app\build\intermediates\cmake\debug\obj\x86\libnative-lib.so
    ...
    D:/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin\ld: error: C:/Users/SIALAB/AndroidStudioProjects/OpenCVExample/opencv/native/libs/arm64-v8a/libopencv_java4.so: incompatible target
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.
    이와 같이 오류가 뜨는데 결국 경로가 문제인걸까요 java4.so가 있는것도 확인 다 했는데..

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.08.07 18:14 신고

      혹시 OpenCV 빌드한 플랫폼과 지금 앱을 작성하여 테스트 중인 플랫폼이 다른가요?

      포스트대로 진행하면 arm64-v8a용만 만들기 때문에 에뮬레이터에서는 테스트가 안됩니다.
      따로 에뮬레이터용으로도 빌드를 진행해야 합니다.

  3. ujeon9 2019.08.13 22:12

    정말 도움이 됐습니다. 좋은 글 감사합니다!

  4. 2019.08.13 23:40

    비밀댓글입니다

  5. 임서영 2019.08.13 23:49

    글 잘봤습니다. 저도 이것처럼 opencv로 유사도 검사를 하고 그 결과를 블루투스로 보내주는 프로젝트를 개발하고싶습니다. 그럴려면 어느 부분을 수정해야하나요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.08.13 23:59 신고

      cpp 파일의 ConvertRGBtoGray 함수의 matAddrInput로 받는 컬러 영상을 입력으로 사용하고 결과는 matAddrResult로 넘겨줍니다.

      cpp 코드내에서 작업한 최종 결과를 matAddrResult로 넘겨주면 안드로이드폰의 프리뷰 화면에 보여지게 됩니다.

    • 임서영 2019.08.14 21:21

      Cpp 파일내에서는 c++로 작성하면 되나요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.08.14 21:24 신고

      C++코드로 작성하면 됩니다. 클래스를 사용할 필요는 없습니다.

    • 2019.08.31 10:18

      다른거 수정없이 cpp 파일만 히스토그램을 이용한 유사도 검사 코드로 수정하면 될까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.08.31 15:20 신고

      현재는 입력 영상 matAddrInput을 받아서 영상처리 후 결과 영상 matAddrResult을 반환하게 되어 있습니다.

      ConvertRGBtoGray(matAddrInput, matAddrResult)


      필요시 유사도 검사를 위해 필요한 입력과 출력으로 수정해야 할듯합니다.


  6. 김민정 2019.10.01 11:28

    안녕하세요!
    훌륭한 게시글 올려주신거 너무 감사드립니다!.
    그런데 ㅠㅠ 제가 CMakeList.txt에 복붙한 후 에,
    native-lib.cpp에서

    Mat &matResult = *(Mat *)matAddrResult;
    ^
    이 matAddrResult 이 아직도 빨간색으로 뜨고 있는데요.. 제가 한 프로젝트를 6번정도 만들었는데 여전히 변화가 없어서ㅠㅠ
    혹시 어떻게 해결해야 할까요.. 도와주세요ㅠㅠㅠ...

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.01 13:09 신고

      안드로이드 스튜디오의 메뉴에서 File > Sync Project with Gradle Files를 선택했나요?

      이후 cpp 파일의 빨간색 코드들이 사라지게되는데..

      현재 cpp 파일에서 빨간색으로 표시되는 코드가 사라졌나요?

      혹시 matAddrResult만 빨간색인가요?

    • 김민정 2019.10.01 14:20

      네 sync는 했습니다!
      나머지는 빨간게 사라졌고
      마지막부분에 matAddrResult만 빨간색입니다..

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.01 14:32 신고

      혹시 함수 선언에 오타가 있는건 아닌지 보세요.

      자바나 OpenCV에서 가져오는 변수가 아니라 해당 변수가 속해있는 함수에 선언이 되있습니다.

    • 2019.10.01 14:55

      비밀댓글입니다

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.01 18:54 신고

      에러나는 부분인 matAddrResult가 포함된 함수를 올려줘보세요..

      실시간 1:1 질의는 힘들듯합니다.

    • webn 2019.12.18 12:38

      안녕하세요 저도 같은 문제가 있었는데, Java_com_example_opencvcameraexample_MainActivity_ConvertRGBtoGray(JNIEnv *env, jobject thiz,
      jlong mat_addr_input,
      jlong mat_addr_result){
      //Todo Implement ConvertRGBtoGray() 있잖아요? 여기서 변수들이랑 맞추어주면 빨간 표시 없어지더라구요
      즉 matAddrInput이 아닌 mat_addr_input 으로 변경해주시고, matAddrResult는 mat_addr_result로 변경해주시면 될거같아요!

      (밑에 보니까 답이 다 있었네요..ㅎㅎㅎ)

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.18 14:23 신고

      다행입니다

  7. Favicon of https://dirrito.tistory.com BlogIcon 유령2세 2019.10.01 18:03 신고

    안녕하세요. 따라서 학습하다가 막히는 부분이 있는데 해결하지 못해서 질문드립니다.

    cvtColor(inputMat, outputMat, COLOR_RGB2GRAY);

    이 부분에서 빌드가 실패합니다. (이 구문을 삭제하면 빌드가 성공하고 에뮬레이터에서 실행됩니다.)

    혹시 몰라서 프로젝트를 새로 만들고 처음부터 다시 했는데도 똑같더군요.

    저만 이상한 건가요.. ㅠ;

    참고로
    app과 opencv의 gradle

    minSdkVersion 21
    targetSdkVersion 29
    입니다.

    아래는 전체 오류 코드입니다.

    (하얀색 글씨)
    > Task :app:externalNativeBuildDebug
    Build native-lib_x86
    ninja: Entering directory `C:\Users\ohmin\Desktop\knu\cvtest\app\.cxx\cmake\debug\x86'
    [1/2] Building CXX object CMakeFiles/native-lib.dir/native-lib.cpp.o
    [2/2] Linking CXX shared library C:\Users\ohmin\Desktop\knu\cvtest\app\build\intermediates\cmake\debug\obj\x86\libnative-lib.so
    FAILED: C:/Users/ohmin/Desktop/knu/cvtest/app/build/intermediates/cmake/debug/obj/x86/libnative-lib.so
    cmd.exe /C "cd . && C:\Users\ohmin\AppData\Local\Android\Sdk\ndk\20.0.5594570\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=i686-none-linux-android16 --gcc-toolchain=C:/Users/ohmin/AppData/Local/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/ohmin/AppData/Local/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -mstackrealign -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -std=gnu++11 -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -shared -Wl,-soname,libnative-lib.so -o C:\Users\ohmin\Desktop\knu\cvtest\app\build\intermediates\cmake\debug\obj\x86\libnative-lib.so CMakeFiles/native-lib.dir/native-lib.cpp.o -llog -latomic -lm && cd ."
    C:/Users/ohmin/Desktop/knu/cvtest/app/src/main/cpp/native-lib.cpp:22: error: undefined reference to 'cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int)'
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.

    > Task :app:externalNativeBuildDebug FAILED

    (여기서부터 빨간색 글자들)
    FAILURE: Build failed with an exception.

    * What went wrong:
    Execution failed for task ':app:externalNativeBuildDebug'.
    > Build command failed.
    Error while executing process C:\Users\ohmin\AppData\Local\Android\Sdk\cmake\3.10.2.4988404\bin\ninja.exe with arguments {-C C:\Users\ohmin\Desktop\knu\cvtest\app\.cxx\cmake\debug\x86 native-lib}
    ninja: Entering directory `C:\Users\ohmin\Desktop\knu\cvtest\app\.cxx\cmake\debug\x86'
    [1/2] Building CXX object CMakeFiles/native-lib.dir/native-lib.cpp.o
    [2/2] Linking CXX shared library C:\Users\ohmin\Desktop\knu\cvtest\app\build\intermediates\cmake\debug\obj\x86\libnative-lib.so
    FAILED: C:/Users/ohmin/Desktop/knu/cvtest/app/build/intermediates/cmake/debug/obj/x86/libnative-lib.so
    cmd.exe /C "cd . && C:\Users\ohmin\AppData\Local\Android\Sdk\ndk\20.0.5594570\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=i686-none-linux-android16 --gcc-toolchain=C:/Users/ohmin/AppData/Local/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/ohmin/AppData/Local/Android/Sdk/ndk/20.0.5594570/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -mstackrealign -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -std=gnu++11 -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -shared -Wl,-soname,libnative-lib.so -o C:\Users\ohmin\Desktop\knu\cvtest\app\build\intermediates\cmake\debug\obj\x86\libnative-lib.so CMakeFiles/native-lib.dir/native-lib.cpp.o -llog -latomic -lm && cd ."
    C:/Users/ohmin/Desktop/knu/cvtest/app/src/main/cpp/native-lib.cpp:22: error: undefined reference to 'cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int)'
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.01 19:07 신고

      올려주신 에러는 OpenCV의 라이브러리 파일이 인식되지 않아서 발생한 에러입니다.

      error: undefined reference to 'cv::cvtColor


      CMakeLists.txt 에서 OpenCV 위치를 잘못 적었거나 OpenCV를 프로젝트에 잘못 임포트해서 일 수도 있습니다.

      또는 에뮬레이터용 x86 플랫폼 라이브러리가 없어서 발생한게 아닌가 싶습니다.

      스마트폰으로 해도 같은 결과인지 확인할 필요가 있어보입니다.

    • Favicon of https://dirrito.tistory.com BlogIcon 유령2세 2019.10.02 00:23 신고

      아 ㅠㅠ 알고 보니 CMakeLists.txt에서
      target_link_libraries에 lib_opencv를 빠트렸습니다... (이걸로 삽질 6시간 ㅎ)

      답변 감사드립니다!!

      추가로 System.loadLibrary("opencv_java4");
      에서

      java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found

      오류가 발생했었는데, 수동으로 libc++_shared.so 파일을 해당 경로(
      프로젝트 경로/opencv/build/intermediates/cmake/debug/obj/x86)에 추가하니 해결되었습니다.

      답변 감사드리고 좋은 글 감사합니다!!

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.02 14:49 신고

      해결되서 다행입니다 : ) 감사합니다.

    • Favicon of https://dirrito.tistory.com BlogIcon 유령2세 2019.10.03 01:32 신고

      혹시 파이썬 스크립트도 동일한 방식으로 실행할 수 있나요??

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.03 11:03 신고

      현재는 C++코드를 위한 NDK만 제공되고 있어서 같은 방식으로 파이썬은 사용불가입니다.

      다른 방법을 찾아봐야 합니다.
      아래 링크를 참고해보세요.

      https://towardsdatascience.com/tools-to-run-python-on-android-9060663972b4

  8. 고르고 2019.10.07 21:31

    저도 윗분과 같이 matAddrResult 부분에서 오류가 나는데 해결법 알 수 있을까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.07 21:51 신고

      cpp 함수에서 matAddrResult 만 빨간색으로 보이나요 ? 아님 다른 OpenCV 관련 헤더파일이나 함수들도 빨간색으로 보이나요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.15 17:35 신고

      cpp 파일에 함수 생성시 파라미터 값이 변경되었네요.

      matAddrInput 대신에 mat_addr_input를
      matAddrResult 대신에 mat_addr_result를 적으세요.

  9. ㅎㅎ 2019.10.08 12:05

    저기 궁금한게 있는데 저기 마지막에 결과화면을 보았을때 단순히 안드로이드 스튜디오로 구현하는 카메라와 이 카메라의 다른점이 뭔가요? Opencv를 연계해서 저 카메라가 구현할수 있는 기능이 무엇인가요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.08 13:24 신고

      OpenCV에서 제공하는 카메라 API를 사용하면 영상을 실시간으로 Mat 구조체로 받을 수 있습니다.
      Mat 구조체를 OpenCV의 함수에 바로 입력으로 사용할 수 있습니다.


      또한 코드도 안드로이드 카메라 API를 사용할때에 비해 간단합니다.

  10. Kill1 2019.10.08 12:08

    혹시 이미지를 찍었을때 그 이미지와 가장 유사한 이미지를 앱에 띄우게 만드려고 하는데 가이드 좀 알 수 있을까요 딥러닝을 통해 1천장의 사진을 학습시킬건데 opencv가 활용이 되는지.. 의견이 궁금합니다

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.08 13:28 신고

      이미지 크기를 일정하게 만든다든가 잡음을 없애거나 히스토그램 평활화랄 적용하는 등의 이미지 전처리에 사용할 수 있일듯합니다.

    • Kill1 2019.10.08 15:31

      포스팅글이 많은데 제가말한 앱에 관련된 글이 없을까요??

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.08 17:25 신고

      Tensorflow lite를 사용하면 될듯한데 아직 준비가 안되어 있습니다.

  11. BlogIcon ㅎㅎ 2019.10.08 15:11

    Mat 구조체 그쪽은 처음들어서 잘 모르겠는데 이거를 이용한 포스팅글도 있나요?? 좀더 심화된과정의 내용이 필요해서.. ㅜㅜ 카메라로 찍은 이미지를 활용하는 앱이라던지 더 나아가는 포스팅글이 있으면 정독하고 싶습니다 그리고 영상을 분석하는게 아닌 카메라로 찍었을때 이미지를 분석하는 앱을 만드려고 하는데 영상분석보다는 이미지분석이 쉬운걸로 알고 있습니다 혹시 도움이될만한 깃허브 소스라던가 글이 있으면 추천해주시면 감사하겠습니다 ㅠ

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.08 17:24 신고

      현재는 OpenCV/Android 개발 환경 및 예제 카테고리에 있는게 전부입니다.

      대부분의 경우 C++로 작성된 것을 cpp 함수에 추가하면 동작하기 때문에 심화라고 할게 없을 듯합니다.

  12. 황재현 2019.10.15 14:28

    안녕하세요 저도 윗분과같이 native-lib.cpp 파일에
    Mat &matInput = *(Mat *)matAddrInput;
    Mat &matResult = *(Mat *)matAddrResult;
    코드중 matAddrInput; 과 matAddrResult; 부분이 빨강색글씨로 뜹니다.
    다른 함수들은 Sync project with Gradle files 하니 다 돌아왔는데 이 두개만 이러네요 해결방법이 있나요??

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.15 17:34 신고

      cpp 파일에 함수 생성시 파라미터 값이 변경되었네요.

      matAddrInput 대신에 mat_addr_input를
      matAddrResult 대신에 mat_addr_result를 적으세요.

    • 황재현 2019.10.15 19:10

      정말 감사합니다 이문제는 해결되었고,

      안드로이드 어플을 실행시키고, 권한 apply
      해주니깐 이상한 픽셀로 된 캐릭터 얼굴이 흔들리는 화면이 나옵니다.
      이건 코드문제가 아닌건가요??

      사진 첨부할수있으면 종을텐데 아쉽네요

      또 궁금한게 어느프로그램에서 캡쳐를 해야 이 어플에 화면이 뜨는 것인지도 궁금합니다.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.15 21:33 신고

      혹시 에뮬레이터 아닌가요?

    • 황재현 2019.10.16 08:41

      아 그냥 기존에있던 안드로이드 프로그램말고 녹스나 모모같은 에뮬레이터를 사용해야하는건가요??

      만약 맞다면 사용방법도 알려주실 수 있나요??

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.16 13:56 신고

      가급적이면 실제 폰에서 하는게 좋습니다. Genymotion이 괜찮습니다. 제 블로그 검색하면 관련 글이 있습니다.

    • 황재현 2019.10.16 14:37

      감사합니다 지니모션 설치 후 연동까지완료하였는데,
      지니모션에서 사진이나 동영상촬영 후 안드로이드 스튜디오에서 구동을시키면
      지니모션 앱에서 흰 화면만 나옵니다.혹시 무슨문제일까요...?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.16 16:28 신고

      지니모션 설정에서 카메라 설정을 했나요?

    • 황재현 2019.10.16 17:15

      네 on으로 설정하고, 프론트카메라 웹캠으로 설정 후 프리뷰해보니 캠은 이상없는데, 프로그램을 실행시키면 흰 화면만 나오네요 ㅜㅜ

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.16 18:09 신고

      코드에서 사용하는 카메라는 전면이 아닌 후면입니다. 지니모션에서 후면에 웹캠을 연결하세요.

    • 황재현 2019.10.16 19:14

      네 친절한답변 감사합니다 !!

  13. 체리블루 2019.10.24 15:58

    저는 구동은 되는데 화면이 흑배모드로 나오고, 촬영 버틍이라든가 버튼이 나타나질 안습니다.

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.24 17:59 신고

      포스트는 흑백으로 바꾸는 예제입니다.

      컬러영상을 보려면 onCameraFrame 함수의 아래 두줄을 주석처리하고 다음처럼 수정하면 됩니다.

      //ConvertRGBtoGray(matInput.getNativeObjAddr(), matResult.getNativeObjAddr());
      //return matResult;
      return matInput;


      버튼을 추가하려면 다음 포스트의 3번을 참고하세요
      https://webnautes.tistory.com/1087

  14. student02 2019.10.25 10:12

    안녕하세요. 덕분에 opencv공부하는데 많은 도움이 되고있습니다. 감사합니다.
    다름이 아니라 중간에 c++로 영상을 변환하는 이유가 뭔가요?? java만 이용해서 할수는 없는건가요??
    cmake를 써야 하는 이유가 궁금합니다..ㅠㅠ

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.25 10:56 신고

      java코드보다 c++코드가 빠르게 실행됩니다. 포스트의 코드는 같이 사용하는 예를 보여주는 겁니다.

    • student02 2019.10.25 11:28

      아.. 영상처리하는 시간을 단축시키려고 하는건가요??

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.10.25 17:21 신고

      맞습니다.

      java코드로 돌리기엔 너무 느린 코드들을 C++로 작성하여 돌리면 상대적으로 빠르게 동작합니다.

  15. CityRock 2019.10.29 09:41

    이유는 모르지만 안드로이드 스튜디오 3.5에서 cmake error가 나서 3.4.2 로 하니 잘되는군요. 자료 감사합니다. 유투브 구독과 좋아요 클릭할게요:-)

  16. upright 2019.11.26 04:36

    안녕하세요 고수님 자세한 설명 감사합니다
    저번 예제는 잘 됐는데 이번 예제는 실행하면 바로 꺼지네요..

    run에서
    --------- beginning of crash
    A/libc: Fatal signal 4 (SIGILL), code 1, fault addr 0xdee5f502 in tid 8249 (cvcameraexample)

    logcat에서
    2019-11-26 04:32:13.347 817-2597/? E/IzatSvc_PassiveLocListener: Exiting with error onLocationChanged line 154 "1"
    2019-11-26 04:32:37.797 1133-1403/? E/storaged: getDiskStats failed with result NOT_SUPPORTED and size 0
    2019-11-26 04:32:42.841 29564-29564/? E/android.youtub: Not starting debugger since process cannot load the jdwp agent.
    2019-11-26 04:32:43.062 29564-29589/? E/GEL_DELAYED_EVENT_DEBUG: Failed delayed event dispatch, no dispatchers.
    2019-11-26 04:32:48.893 787-813/? E/vendor.lge.hardware.lgmd@1.0-service: readFile: Could not open /sys/class/power_supply/usb/is_ocp

    이런식으로 뜨는데 어떻게 해야 할까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.11.26 09:28 신고

      올려주신 로그캣에 에러 원인이 포함되지 않은 듯합니다.

  17. orz 2019.12.16 14:47

    위의 소스들을 따라해서 실제 스마트폰에서 실행해봤더니 별다른 이상 없이 작동하고, 카메라 권한도 제대로 가져왔지만 어째서인지 흑백 화면이 아니라 온통 새까만 화면만 보입니다.

    실행에 오류는 나오지 않았고 카메라 권한은 제대로 가져왔고 소스를 그대로 복사도 해봤고, openCV 라이브러리도 안에 제대로 추가되어 있어서 뭐가 문제인지 모르겠네요.


    혼자서 소스 뒤적거려가며 원인을 찾으려 했지만 도저히 찾을 수 없어서 도움을 요청합니다. 도와주세요...

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.16 15:39 신고

      4.1.1 이상에서하는 코드를보면 자바코드에 있는 권한코드가 이전버전과 다릅니다.
      증세로 봐서는 권한 문제 같습니다.
      로그캣에 관련 오류가 있아보세요

      안드로이드 스튜디오 버전과 OpenCV 그리고 안드로이드 버전을 어떻게해서 진행했나요?

    • orz 2019.12.16 15:58

      안드로이드 스튜디오 버전 3.5.1, OpenCV 버전은 4.1.2, 안드로이드 버전은 8.1.0입니다.

      카메라를 사용하지 않는 OpenCV 예제를 찾아서 해보니까 이건 또 잘되네요... 카메라 문제인가...

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.16 16:08 신고

      로그캣의ㅜ필터를 에러로 바꾼 상태에서 앱 실행시 보이는 로그를 봐야할듯합니다

    • orz 2019.12.16 16:17

      로그캣에 찍히는 로그 중 에러는
      E/OpenCV/StaticHelper: OpenCV error: Cannot load info library for OpenCV
      이것 한 줄 뿐이로군요.

      그 밑으로는

      D/OpenCV/StaticHelper: Library list: ""
      D/OpenCV/StaticHelper: First attempt to load libs
      D/OpenCV/StaticHelper: Trying to init OpenCV libs
      D/OpenCV/StaticHelper: Trying to load library opencv_java4
      D/OpenCV/StaticHelper: Library opencv_java4 loaded
      D/OpenCV/StaticHelper: First attempt to load libs is OK

      이렇게 찍히고요.

      진짜 뭐가 문제지...

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.12.16 16:19 신고

      안드로이드 버전을 포스트와.맞춰보세요

    • orz 2019.12.16 16:32

      안드로이드 버전 10(API 29) 지원 기기가 없습니다...orz

      안드로이드 버전 9(API 28)인 기기는 있어서 실행시켜보면 마찬가지로
      E/OpenCV/StaticHelper: OpenCV error: Cannot load info library for OpenCV
      한줄만 뜨고요.

      내일 안드로이드 버전 10 지원 기기 대여해와서 돌려봐야겠습니다.

      도와주셔서 감사합니다.

  18. hello 2020.01.16 17:40

    sync를 맞추는 부분에서 ERROR: Cause: executing external native build for cmake C:\(경로)\CMakeLists.txt
    다음과 같은에러가 나옵니다..ㅜㅜ

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.01.16 23:28 신고

      사용한 환경을 포스트와 맞추지 않았다면 맞추어서 해보세요.

    • hello 2020.01.16 23:33

      댓글 감사합니다!
      OpenCV 4.1.1, 4.1.2, 안드로이드 스튜디오 3.5.1, NDK 19,20까지 해봤습니다.
      stackoverflow에서 NDK 버전을 낮추라는 말을 듣고 17년도 버전을 받아서도 사용해봤지만 같은 결과가 나옵니다..

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.01.16 23:34 신고

      혹시 프로젝트 경로에 한글 이름이 포함되있나 요

    • hello 2020.01.17 09:17

      아뇨.. 전부 영어입니다.
      또 어디서는 app gradle에서 externalNativeBuild를 통채로 지우라길래 지웠다가 sync는 맞춰졌지만 java에서 native-lib을 인식하지 못하는 상황도 있었습니다..

    • hello 2020.01.17 14:18

      Event Log를 확인해보니 경로를 설정했음에도 NDK 21로 적용돼있었습니다.. 그래서 그냥 21을 지워버리고 다시하니 Sync는 적용이 됐습니다!!

      근데 중간중간 AppCompatActivity, nonnull같은 부분은 빨간표시가 떠서 alt+enter로 import class를 해서 적용을 했는데 단말기에 올리니 까만 화면에서 멈추고 에러 로그에는 OpenCV error: Cannot load info library for OpenCV 라고 나옵니다..

      댓글들을 보니 안드로이드 버전도 맞추라고 하셨는데 그럼 낮은 버전에서는 돌릴 수 없나요? 6.0, 7.0입니다 버전은

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.01.18 08:24 신고

      낮은 버전에서는 문제가 생길 수 있습니다.

  19. 김당근 2020.01.30 07:25

    선생님, 안녕하세요.
    이 게시글을 보고난 뒤, 그동안 안드로이드 실행이 안 되어서 몸속에 쌓아 놨던 사리 다 털어냈네요...껄껄
    정말 감사드립니다. 영상으로 보니까 파일 경로를 정확히 알 수 있어서 참 좋았어요.
    설명도 좋고, 목소리도 밝고, 우렁차셔서 즐거웠어요.
    다시 한번 감사드립니다. 앞으로도 블로그와 유튜브 채널 통해서 많은 정보와 지식 얻고 가겠습니다!
    파이팅!!

  20. 캡스톤중 2020.02.24 14:47

    안녕하세요 제가 이번에 안드로이드 스튜디오에서 제작한 어플과 아두이노를 이용한 라인 트레이싱을 하는 중인데요
    그래서 이 카메라 예제를 따라서 해보려는데 create fuction부분에서 다른게 나오고 그래서인지 app-cpp에 cmake가 없어요 ㅠㅠ
    그리고 혹시 라인트레이싱관련도 알수잇을까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.02.24 22:54 신고

      문제가 생겼을땐 프로젝트를 새로 생성하는게 좋습니다. 안드로이드 스튜디오에서 처리가 끝났을때 다음 단계로 넘어가야 합니다

  21. 삽질중 2020.03.19 08:39

    안녕하세요, 따라했더니, 화면은 잘 나오는데요.... 세로 모드에서는 90도 돌아가 있고, 가로모드 한쪽은 잘 나오는데, 반대로 돌린 가로모드에서는 화면이 뒤집혀있는데요.. 이 부분은 왜 그런걸까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.03.19 08:44 신고

      핸드폰의 화면 방향을 잡아주는 센서가 제때 동작못해서 발생하는 문제 같습니다. 안드로이드 폰 기종에 따라 발생하는 문제로 보입니다

    • 삽질중 2020.03.19 10:03

      혹시 화면 돌리는 방법이 있을까요? 제가 폰 3개에서 해봤는데, 모두 똑같은 증상으로 봐서.. 화면을 돌려야할거 같습니다.

      아니면, 핸드폰을 돌리는 거에 따라서 화면이 바뀌지 않고, 그냥 세로 모드로만 볼 수 있는 방법이 있을까요? 제가 굳이 화면이 회전될 필요는 없거든요

      혹시 opencv를 4점대가 아닌, 제가 opencv를 3.4.5를 사용하고 있는데, 이게 문제가 될 수는 있을까요?

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2020.03.19 11:15 신고

      OpenCV 버전 문제는 아닌듯합니다. OpenCV의 카메라 API의 문제인듯 싶습니다. 그리고 세로방향으로 고정하면 카메라 프리뷰가 전체화면이 안됩니다.

      안드로이드API로 작성한 카메라앱을 사용해보는건 어떨까 싶네요

+ Recent posts