메뉴 건너뛰기

개발강좌/정보

  • 텐서플로우로 이미지인식 모바일앱 만들어보기 - 5-1 (안드로이드용 예제 앱 실행해보기 - 기본예제 그대로) [머신러닝/딥러닝]
  • 공돌이
    조회 수: 7540, 2017.05.26 15:40:18
  • 지난시간에 그래프를 만들었는데요...

     

    이번시간에는 간략히 안드로이드용 앱의 구조를 살펴보기 위해 예제에서 제공하는 그래프를 다운로드받아서 사용해 보도록 하겠습니다.

    예제 앱은 잘 만든 앱이긴 하지만, 전체적인 안드로이드용 텐서플로우 적용앱의 구조를 설명하기에는 좀 복잡한 감이 있어서, 실행 테스트 후 다음시간에 좀 더 구조가 단순한 앱을 하나 만들어서 우리가 만든 그래프를 직접 올려보도록 하겠습니다.

     

    텐서플로우 github에서 다운로드 받은것을 보시면 잘 만들어진 안드로이드 예제가 있습니다.

     

    안드로이드용 예제코드는, 세개의 예제가 하나로 묶여 들어가 있습니다. (ImageDetector, ImageClassifier, Sytler)

    1. TF Classify: 구글 인셉션 모델(이미지인식)을 이용해서 카메라에 잡히는 물체를 실시간으로 인식하고, 결과(추측)를 화면에 오버레이해서 표시해주는 앱
    2. TF Detect: Scalable Object Detection using Deep Neural Networks 모델을 기반으로 카메라 프리뷰에 잡히는 사람을 실시간으로 추적
    3. TF Stylize:  A Learned Representation For Artistic Style 모델을 기반으로 카메라 프리뷰에 잡히는 이미지를 여러 예술가의 느낌으로 리스타일링

     

    안드로이드 텐서플로우 공식 예제 앱 돌려보기

     

    안드로이드에서 학습된 그래프를 사용해 입력받은 이미지를 인식하기 위해서 현재 순수하게 java로 만들어진 라이브러리는 없고, c++을 이용해서 만들어진 추론엔진을 가지고 와서 사용해야 합니다(아마 성능상의 이슈나 java에서 직접 처리하기 쉽지않은 부분들이 있겠죠?). 이를 위해서 텐서플로우에서는 c++라이브러리와 java에서 이 라이브러리를 사용할 수 있도록 JNI 라이브러리를 제공하고 있습니다.

     

    c++로 작성된 native library :libtensorflow_inference.so (하나 더 있는데, 데모를 위해서 만든거라, 나중에 자체 앱제작시에는 필요없으므로 설명은 생략합니다) 

    JNI library :  libandroid_tensorflow_inference_java.jar

     

    이를 준비하는 방법은 세가지가 있습니다

    a) JCenter에서 자동으로 다운로드 받는 방법( r1.2.0 프리뷰 버전부터 가능)

        : 제일 간단한데 얼마전 릴리즈된 1.2.0 프리뷰,rc0 버전에서 가능합니다. 지금 튜토리얼은 1.1.0 버전 기준으로 진행되던 건데, 내용이 약간 바뀌어서 이 튜토리얼 마무리하고 1.2프리뷰기준으로 좀 추가하려고 합니다. ㅠㅜ 

          이 옵션을 사용하면 소스에서 패키지 ( *.so 파일과 *.jar 파일)들을 빌드하는게 아니라 JCenter에서 패키지를 다운받게 됩니다. 아마 제일 빠르고 간단한 방법이겠지요.

          만약 github 소스를 1.2.0 버전을 받으셨다면 간단히 build.gradle 파일에서  nativeBuildSsystem 값만 none 으로 아래처럼 변경해주시면 됩니다.

       def nativeBuildSystem = 'none'

      만약 기존의 github 소스를 사용하고 계신거라면, build.gradle 의 dependency부분에 아래 의존성을 직접 추가해주시거나

     

    dependencies {
        ...
        compile 'org.tensorflow:tensorflow-android:1.2.0-rc0'
    }
    

     

    아니면 안드로이드스튜디오 메뉴에서 File -> Project Structure... 를 선택하시고 app -> dependencies 탭을 선택한 후 + 버튼을 누르시고

    Project Structure 2017-05-26 11-31-15.png

     

     

    표시되는 검색창에서 tensorflow 라고 치고 검색하시면 라이브러리가 나옵니다. (첫번째에 나오네요) 그걸 선택하셔도 됩니다.

     

    Choose Library Dependency 2017-05-26 11-31-59.png

     

    요기까지만 하시면 이제 바로 실행해보실 수 있습니다...^^ (빌드하면서 모델파일을 다운로드 받습니다)

     

    이렇게 하면 JNI 들을 빌드 따로 하지 않고 그냥 다운로드 받아버리니까 엄청 빨리 되겠죠. 

    다만, 기존 1.1.0 버전 안드로이드 소스를 가지고 하는 경우에는 버전이 바뀌면서 호출방식 등 변경된 부분이 있을수 있어서 오류 가능성이 있습니다. (이거는 제가 테스트해보고 따로 올릴게요) 1.2.0 버전 다운받으신 분들은 이 방법이 제일 쉽고 빠릅니다.

     

    이 방법의 유일한 단점은, 기존의 JNI 소스를 변경해서 사용하려고 하면 이 방법은 사용할 수 없고, 직접 다 빌드해야 한다는 점 정도겠지요.

    나중에 익숙해지면 직접빌드할 필요성이 있겠지만, 한동안은 그럴 필요성이 없을거예요.

     

    b) nightly build 되어있는거 가져다 쓰기 :

    a) 방법보다는 약간 수작업이 들어가지만 이것도 상당히 빠르고 간편합니다.a 방법에 비해 가지는 장점은, 최신의 변경사항이 거의 바로바로 반영된다는 점입니다. (나이틀리 빌드) 

    http://ci.tensorflow.org/view/Nightly/job/nightly-android/ 

     

    여기 가셔서 가장 last successful build 를 다운로드 받으시면 됩니다. (zip 파일로 압축해서 받으시면 간편하죠)

    nightly-android [Jenkins] 2017-05-26 11-44-28.png

     

    다운받으신 후 압축파일을 풀면 아래와 같은 폴더구조가 보이실겁니다.

    :Users:jpkim:Downloads:archive 4:out:native:libtensorflow_inference.so:armeabi-v7a 2017-05-26 11-50-08.png

     

    급하신 분은 여기 있는 tensorflow_demo.apk 파일을 직접 설치해서 바로 실행해보셔도 되지만, 구조를 알기 위해서 하나하나 넣어서 직접 apk를 만들어보겠습니다.

    텐서플로우 모바일인식을 위해 공통적으로 필요한 파일은 우선 libandroid_tensorflow_inference_java.jar (JNI interface 라이브러리) 파일과 libtensorflow_inference.so 파일입니다. 그리고 이 데모 앱을 실행하기 위해서는 (카메라에서 들어온 이미지 YUV 값을 RGB로 변환하는 등의 작업을 하는) libtensorflow_demo.so 파일도 필요하겠네요.

    *.so 파일은 해당 폴더를 보시면 아키텍쳐별로 서브폴더가 만들어져서 그 안에 각각 동일한 기능의 so 파일이 만들어져 있습니다.

    이 방법에 대한 자세한 설명은 다음번 튜토리얼에서 자세히 설명하고, 지금은 간단히 넘어가겠습니다.

    libs, jniLibs 폴더에 각각 넣어주고, dependency 설정해주면 됩니다.

     

    c) 소스로부터 직접 빌드하는 방법  :

    약간 복잡하고 시간이 오래걸립니다. 하지만, 나중에 뭔가 core 의 내용을 수정하고 싶다거나 할땐 이방법밖에 없겠죠. 나중에 기회가 되면 또 설명하겠지만, 현재버전의 안드로이드 라이브러리에서는 몇가지 지원되지 않는 것(Multicore, memmapped graph 등) 들이 있어서, 이거 해결하려면 jni쪽을 좀 수정해줘야 합니다...ㅠㅜ 

     

    직접 빌드하기 위해서는 우선 또 한두가지를 다운로드 받으셔야 합니다...^_^ 

     

    1) Android SDK Build tool API 버전 23 이상 (안드로이드 스튜디오를 쓰시면 거기 포함되어 있을테니 경로와 버전확인만 한번 하시면 될듯)

       ==> 별도로 다운로드받으시려면: 여기로

    2) Android NDK : 최신버전 말고 이전버전인 버전 12b 가 필요합니다. 아마 별도로 다운로드 받으셔야 할듯 (여기)

     

    Android SDK와 NDK 가 설치된 경로를 적어두시고...

    (저는 SDK는 안드로이드스튜디오에서 설치한 라이브러리폴더인 /Users/내아이디/Library/Android/sdk 에 있는걸 사용하고,

    NDK만 별도로 다운로드 받아서  /Users/내아이디/Library/Android 밑에 ndk-r12b 라는 폴더에 설치했습니다)

     

    우선 다운로드 받았던 github source folder (~/tensor/tensorflow) 밑에 있는 WORKSPACE 라는 파일을 열어주세요.

    터미널에서는 vi 나 nano 등 손에 익은걸로 여시고, 파인더를 통해서 여신다면 맥의 텍스트편집기 말고 plain text를 편집할 수 있는 에디터를 사용하셔야 합니다.

     

    열어서 보시면 아래처럼 안드로이드 SDK와 NDK 경로를 지정해주는 부분이 위쪽에 보이실겁니다

     

     

    # Uncomment and update the paths in these entries to build the Android demo.

     #android_sdk_repository(

     #    name = "androidsdk",

     #    api_level = 23,

     #    # Ensure that you have the build_tools_version below installed in the 

     #    # SDK manager as it updates periodically.

     #    build_tools_version = "25.0.2",

     #    # Replace with path to Android SDK on your system

     #    path = "<PATH_TO_SDK>",

     #)

     #

    # Android NDK r12b is recommended (higher may cause issues with Bazel)

     #android_ndk_repository(

     #    name="androidndk",

     #    path="<PATH_TO_NDK>",

     #    # This needs to be 14 or higher to compile TensorFlow. 

     #    # Note that the NDK version is not the API level.

     #    api_level=14)

     

     

    여기 주석으로 되어있는 부분을 주석해제하시고 아래와 같이 만들어주세요.  (*** 는 제 아이디 모자이크처리한겁니다...^^ 경로는 각자 환경에 맞게)

     

     # Uncomment and update the paths in these entries to build the Android demo.

     android_sdk_repository(

         name = "androidsdk",

         api_level = 23,

         # Ensure that you have the build_tools_version below installed in the 

         # SDK manager as it updates periodically.

         build_tools_version = "25.0.2",

         # Replace with path to Android SDK on your system

         path = "/Users/***/Library/Android/sdk",

     )

     #

     # Android NDK r12b is recommended (higher may cause issues with Bazel)

     android_ndk_repository(

         name="androidndk",

         path="/Users/***/Library/Android/ndk-r12b",

         # This needs to be 14 or higher to compile TensorFlow. 

         # Note that the NDK version is not the API level.

         api_level=14)

     

     

    여기까지 다 하셨다면,  이제 빌드 하시면 됩니다.

     

    몇가지 주의하실 점은,

    1) 현재 소스빌드 설정은 armeabi-v7 로만 빌드하도록 되어있습니다. 즉, 에뮬레이터에서 돌리면 오류나요...ㅠㅜ 실 기기에 설치해서 돌려보셔야 합니다.

    2) 그래프파일/라벨파일: 각 앱에서 사용할  .pb 파일과 .txt 파일은 빌드하면서 다운로드받도록 설정되어있습니다. 별도로 다운받거나 자기가 만든 파일로 바꿔치기하실 수도 있습니다만, 여기서는 생략할게요. 

     

    이제, 안드로이드 스튜디오에서 직접 빌드 혹은 (실기기 연결한 상태에서) Run 하시거나,

     

    터미널에서 WORKSPACE 파일이 있는 깃헙 소스 루트폴더 (튜토리얼대로 하셨다면 ~/tensor/tensorflow ) 로 가셔서 아래의 명령을 수행해 줍니다.

     

    bazel build -c opt //tensorflow/examples/android:tensorflow_demo

     

    시간이 꽤 걸리는 작업이니 커피한잔 드시고, 담배태우시면 담배도 한대 태우시고 잠시 노닥거리다가 오셔도 좋습니다.

     

    터미널로 빌드하셨다면, 깃헙 소스 루트 밑에 bazel-bin 폴더 (~/tensor/tensorflow/bazel-bin/tensorflow/examples/android/ ) 안에  APK 파일이 생성되어 있을테니

    아래의 명령어로 기기에 직접 설치하실 수 있습니다.

    adb install -r bazel-bin/tensorflow/examples/android/tensorflow_demo.apk

     

     

    기기를 살펴보시면 3개의 앱이 설치된 걸 확인하실 수 있습니다 (TFDetector, TFClassifier, TFStyler)

    각각 실행해서 가지고 놀아보시면 됩니다...^^

     

     

    자, 여기까지 했으면 기본적인거는 한번 해보신 셈인데요... 이제 슬슬 내가 따로 그래프 만들어서 나만의 앱을 만들고 싶어! 하시는 분들이 계실거라고 봅니다. (저도 그랬거든요)

     

    그거를 다음시간에 할텐데, 그 전에 잠시 앱에서 필요한 부분들의 구조를 잠시 살펴보고 넘어가겠습니다.

     

     

    jar 파일을 디컴파일해서 보시면 텐서플로우 inference(인식) 부분의 코어기능들이 JNI로 만들어져 있는것을 확인하실 수 있을겁니다.(몇개 빠져있어요 근데 ㅠㅜ)

    Tensor 환경 생성, inference 엔진에 데이터 피딩하기 등등... 복잡하고 저도 자세히 아는게 아니니 관심있는 분들은 한번씩 살펴보시고,

    (TensorflowInferenceInterface.java 부분이 직접 사용하는 핵심부분이니 요놈만 좀 살펴보셔도 좋아요)

     

    실제로 우리가 관심을 가져야 할 소스는 (다음번 튜토리얼에서 거의 그대로 가져다 쓸거임)

    인터페이스인 Classifier.java와 얘를 implement 한 TensorflowImageClassifier.java 입니다.

     

    TensorflowImageClassifier 를 이용해서, 좀 더 편하게 텐서플로우 인퍼런스인터페이스를 사용할 수가 있지요.

    그 중에 두개 메서드가 가장 중요합니다...ㅇㅇ

     

    create 메서드 : 텐서플로우 환경을 특정값으로 초기화하고, 모델로 쓸 그래프파일과 라벨파일을 메모리로 올려두는 역할을 합니다. 그래프파일의 용량이 큰 관계로, 호출할때는 executor를이용해서 비동기로 로드합니다. (예제기준)

    recognizeImage 메서드 : 핵심입니다. 비트맵(그림)을 입력값으로 받아서, 텐서가 연산할 수 있도록 float 값들의 행렬(일종의 패턴화된 숫자들)로 변환하여 텐서 객체에 feed 하고, 결과값( 라벨값과 확률치의 배열 - 여러개가 나올 수 있으므로)을 리턴하는 형태입니다.

     

    * 참고: 로직을 잘 보시면, 현재는 인셉션엔진(이미지인식)을 사용하는 거니까, 엔진에서 학습시 그래픽을 행렬로 변환하는 것과 동일한 방식으로 수치화->행렬화 해서 인식시키고 있지요? 즉, 다시말해서 다른 인식엔진(문자인식, 음성인식 등등)을 이용하면 (혹은 새로 만들면) 그 형태대로 수치화->행렬화 해주고 feed만 해주면 무엇이든 배우고 인식할 수 있게 되겠지요? 응용은 각자 익숙해진 후에 아이디어를 내서 알아서...^^

     

     

     

    이번시간은 여기까지입니다...휴

     

    여행갔다왔다가 다시 귀차니즘으로 차일피일 미루다가, 이제 다시 쓰네요. 그동안 1.2.0rc0 버전이 나와서 튜토리얼도 개정을 좀 해야할것 같아요 

    (아마, 기존거는 제목만 1.1.0 으로 수정하고 1.2.0 은 복붙애서 새로 쓰는 형태가 될듯)

     

     

     

    * 참고2: 위에꺼 따라해보기 엄청 귀찮으신 분들은 jenkins nightly에서 prebuilt된 apk 파일만 다운로드받아서 직접 실행해보셔도 됩니다만, 그럼 이 튜토리얼 보시는 의미가 별로 없겠지요...ㅎㅎ

     

     

     

     

     

     

댓글 13 ...

  • 제자

    2017.05.29 08:56

    좋은정보 감사합니다~~
    iOS가 너무너무 기다려지네요 ㅎㅎ
  • 공돌이

    2017.05.29 10:46

    헉...제가 iOS쪽은 잘 아는게 아니라서, 기존에 있는 예제를 실행해보는 정도입니다...ㅎㅎ 응용은 팁만 드릴 수 있을듯 ㅠㅜ

  • 제자

    2017.05.30 08:36

    그게 어디에요 ㅎㅎ 도움주셔서 감사합니다 ^^

  • 드린

    2017.08.26 16:52

    외람된 질문이지만,
    제가 파이썬을 이용해서 GUI를 구성하고
    버튼을 누르면
    이미지 학습 명령어를 실행하여 이미지 유사도 확률을 보여주려고 하는데요.
    문제가 이미지 학습 명령어 실행을 어떻게 구현할지..(윈도우에서는 os.system(커맨드) 파이썬 소스코드가 작동하질 않더군요...)
    exe파일로 만들어서 윈도우에서 실행시키고 싶은데 잘 안되네요.
    여쭤볼 곳이 이곳 밖에 없어서 많은 질문을 드리고 있네요. 죄송합니다;;
  • 공돌이

    2017.08.26 20:41

    이런형태로 만들어본 적은 없어서 잘 모르겠지만, 단순히 시스템커맨드로 파이썬 스크립트를 실행하시면 필요한 환경값들을 불러올 수 없을것 같습니다. 

    쉘 스크립트에 필요한 환경변수를 설정하고 파이썬을 실행하도록 한 다음 (윈도우라면 bat 이나 cmd 파일이 되겠네요), 그 스크립트를 os.system 명령으로 호출하면 되지 않을까요?

    - 근데 헷갈리는게 학습명령을 수행하는거는 유사도 확률을 보여주는 거와는 조금 다른데요...특정이미지의 유사도를 보여주고 싶으신거라면 컴파일된 tensorflow_inference 라이브러를 GUI에서 직접 호출해주시는게 제일 자연스럽고 빠를거 같습니다. (안드로이드/아이폰용 앱에 적용하는거와 거의 비슷한 방식) - 다만 이 부분은 댓글로 설명드리기에는 너무 길어질 것 같고, 나중에 여력이 되면 별도로 가이드를 한번 만들어보겠습니다.

  • 드린

    2017.08.27 21:43

    앗 제가 질문을 잘못 드렸네요.

    학습 명령어가 아닌 tensorflow/bazel-bin/tensorflow/examples/label_image/label_image --input_layer=Mul --output_layer=final_result --labels=train/output/trademark/retrained_labels.txt --image=test.jpg --graph=train/output/trademark/retrained_graph.pb 과같이 이미지 테스트를 넣으려 합니다. 

    혹시 참고할 만한 자료가 있을까요?

    쉘 스크립트? 스크립트 호출? 이라는 단어가 아직 생소해서요;;

    정성스런 답변에 감탄하고 갑니다!!

  • 공돌이

    2017.08.28 09:47

    쉘스크립트는 유닉스환경에서 bash, sh 등의 shell 에서 제공하는 기본 명령어들과 각종 커맨드라인용 프로그램들을 이용해서 일련의 작업을 수행하도록 하는 명령어의 조합, 쉽게 이야기하자면 파이썬으로 만드신 거와 비슷한 역할을 하는거라고 보시면 될것 같습니다. 윈도우 환경에서는 .BAT 혹은 .CMD 라는 확장자를 가진 뱃치파일로 비슷한 역할을 수행할 수 있습니다만, 저도 간단한거 밖에 모르는 터라...더 자세히 알아보시려면 구글이나 네이버에서 윈도우 스크립트 혹은 batch 이런걸로 검색해보시면 조금 나올 듯 합니다.

    원래 커맨드라인에서 실행하시던 python 어쩌구 retrain 등등의 명령어를 그대로 넣어서 사용하시면 되고, 파일명 같은거는 명령어 인수 (예를 들면 command.bat 파일명 이런식으로)로 처리하시면 될겁니다. batch 파일에 환경변수 (path, ld_library_path 등) 를 넣으시고 원하는 프로그램을 실행하시면 되지않을까 싶습니다.

    지금 검색해보니 http://jangpd007.tistory.com/163 요기를 좀 찬찬히 읽어보시면 윈도우용 뱃치파일 제작에 대한 팁을 얻으실 수 있을것 같네요...

  • 여탕앞자취남

    2018.03.22 02:48

    안녕하세요?글 너무 잘보고 있습니다. 질문 하나만 드리고 싶습니다.
    3번째 방법으로 빌드중인데,
    bazel build -c opt //tensorflow/examples/android:tensorflow_demo 이 명령어를 실행하고, 진행 도중에

    ERROR: /home/hwang/tensorflow/tensorflow/tensorflow/core/BUILD:1090:1: C++ compilation of rule '//tensorflow/core:android_tensorflow_lib_lite' failed (Exit 1)
    In file included from ./tensorflow/core/platform/cupti_wrapper.h:24:0,
    from tensorflow/core/platform/default/device_tracer.cc:27:
    ./tensorflow/core/platform/default/gpu/cupti_wrapper.h:26:45: fatal error: cuda/extras/CUPTI/include/cupti.h: No such file or directory
    #include "cuda/extras/CUPTI/include/cupti.h"
    ^
    compilation terminated.
    Target //tensorflow/examples/android:tensorflow_demo failed to build
    Use --verbose_failures to see the command lines of failed build steps.
    INFO: Elapsed time: 3.017s, Critical Path: 1.73s
    FAILED: Build did NOT complete successfully

    이러한 오류가 발생합니다. 해결을 못하고 있어서 질문드립니다. ㅜㅜ
  • 공돌이

    2018.03.22 03:04

    안녕하세요, cuda gpu 에러가 났네요... 몇가지 사항 확인해봐주세요...

    1) 사용O/S 및 그래픽카드

    2) ./configure 하실때 cuda 사용으로 하셨나요? 

     

    일단 정확한 환경을 제가 잘 모르는 상태에서 임시처방 할만한걸 말씀드리면, GPU사용하지 않고 빌드해보세요.(안드로이드데모빌드할때는 GPU 안하셔도 되거든요)

  • 여탕앞자취남

    2018.03.22 03:12

    1.우분투 16.04 그래픽카드: gtx1070입니다.

    2../configure 할 때 cuda 사용했습니다.

    죄송하지만 gpu를 사용하지않고, 빌드하는 방법을 알수 있을까요? ㅜㅜ

  • 공돌이

    2018.03.22 08:15

    ./configure 하실때 cuda 나 cudnn 관련해서는 다 no 하시면 됩니다. 혹시 빌드도중 또 비슷한 오류가 나면 이전 설정이랑 충돌이 나는걸수도 있으니 bazel clean 하신 후 다시 빌드해보시면 될것 같습니다.

     

     

  • 공돌이

    2018.03.22 08:20

    일단 오류메시지 자체는 cuda 드라이버가 제대로 안 깔려있는듯 합니다.

    설치된 cuda 드라이버를 제거하신 후 http://docs.nvidia.com/cuda/cuda-installation-guide-linux/#axzz4VZnqTJ2A 를 참조하셔서 다시한번 설치를 해주시는게 좋을것 같습니다. 

  • 여탕앞자취남

    2018.03.22 16:33

    답변 정말 감사드립니다. 시도해 보겠습니다. 설명을 매우 알기 쉽게 해주셔서 정말 고맙습니다. 큰 도움이 됬습니다.

    안드로이드 빌드 할 때는 cuda가 없어도 된다는 큰 깨달음이 있었습니다.

https://meisteruser.net/devflow/2367
번호
제목
닉네임
11 프레임워크/기타 공돌이 3 2018.09.20
10 머신러닝/딥러닝 공돌이 2233 2017.07.05
9 머신러닝/딥러닝 공돌이 2397 2017.06.05
머신러닝/딥러닝 공돌이 7540 2017.05.26
7 머신러닝/딥러닝 공돌이 2568 2017.05.02
6 머신러닝/딥러닝 공돌이 8610 2017.04.27
5 머신러닝/딥러닝 공돌이 3877 2017.04.24
4 머신러닝/딥러닝 공돌이 2998 2017.04.23
3 머신러닝/딥러닝 공돌이 6099 2017.04.19
2 머신러닝/딥러닝 공돌이 23421 2017.03.22
1 공지 공돌이 700 2017.03.21
태그
위로