1. 구글에서 yolov3 android 로 검색해보면 나오는 사이트이긴 하나 아주 간략히만 되어 있다.
github.com/ivangrov/Android-Deep-Learning-with-OpenCV
2. 검색해서 찾았으나 위의 1번을 참고해서 돌린것으로 판단된다.
m.blog.naver.com/bdg9412/221795234705
3. 구글에서 안드로이드 스튜디오 opencv를 검색해서 찾아보았다. 자세히 되어 있다. 1,2번에 녹여 넣어야 한다.
Yolo를 안드로이드 스튜디오에서 적용되도록 코드를 작성한다.
위의 Git을 참고해서 작성하려고 하는데 뭔가 끊어져 있다.
하나씩 모아서 붙여서 작성해 보자
- Create New Project -> Native C++
- Language : Java
- Minimum SDK : API 21 선택
- Finish
안드로이드용 OpenCV 설치
opencv github release 검색
여러 버전별로 파일들이 있으나 opencv-4.4.0-android-sdk.zip 다운로드
압축풀어 C드라이브에 이동
- 다운받은 압축파일을 푼다 : OpenCV-android-sdk 폴더가 생성된다.
- C:\ 루트 드라이브에 폴더를 이동 : C:\OpenCV-android-sdk
안드로이드 스튜디오에 적용
- File -> New -> Import Module...
- C:\OpenCV-android-sdk\sdk 선택
- File -> Projcet Structure...
- Dependencies -> app -> + -> 3 Module Dependency
- sdk 체크 -> OK
- 이전메뉴(Project Structure)에서 OK를 누르고 마무리
코드 붙여넣기 # 1 : app>res>values>styles.xml
<!-- No Title Bar-->
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
- styles.xml 이 없으면 다음과 같이 생성
- app > res > values > 에서 마우스 오른쪽 > New -> XML -> Values XML File
- 'styles' 타이핑 -> Finish
코드 붙여넣기 # 2 : app>res>layout>activity_main.xml
- activity_main.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"
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, #4 : app>manifests>AndroidManifest.xml
- AndroidManifest.xml 파일을 수정
- 5번 라인 ~ 15번 라인까지 삽입됨
<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" />
- AndroidManifest.xml 파일을 수정
- <activity android:name=".MainActivity"> 라인을 찾아 아래 코드로 수정
위의 코드를 아래코드로 수정
<activity android:name=".MainActivity">
=>
<activity android:name=".MainActivity"
android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation">
코드 붙여넣기 # 5 : app>java > ... > MainActivity.java
- 중요한것은 첫번째 줄은 남겨야 함
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();
}
}
- ConvertRGBtoGray function 수정
코드 붙여넣기 # 6 : native-lib.cpp
- MainActivity.java파일에서 Create JNI function for ConvertRGBtoGRay 로 생성된 함수
- 불필요한 부분을 지우고
- 위 2줄은 위쪽에
- 아래 3줄은 //TODO 아래에 삽입
#include <opencv2/opencv.hpp>
using namespace cv;
Mat &matInput = *(Mat *)mat_addr_input;
Mat &matResult = *(Mat *)mat_addr_result;
cvtColor(matInput, matResult, COLOR_RGBA2GRAY);
코드 붙여넣기 # 7: app>cpp>CMakeLists.txt
- CMakeLists.txt파일을 아래 파일로 바꾸기
- 기존 파일내용을 모두 삭제
- 아래 코드를 복사하여 붙이기
# 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}/sdk) # 수정 필요
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} )
프로젝트 경로 수정하기
- 내가 생성한 프로젝트의 경로로 수정하기
Sync Project
- 수정한 내용을 동기화하기
'PROGRAM > Bigdata-AI' 카테고리의 다른 글
공공데이터 받기 - LOCALDATA (0) | 2020.09.16 |
---|---|
columns / index 이름바꾸기 (0) | 2020.09.11 |
Jupyter Notebook 단축키 (0) | 2020.09.10 |