앱에 커스텀 모델 통합

1. 시작하기 전에

이 시리즈의 첫 번째 Codelab에서는 이미지 라벨 지정을 사용하여 이미지 콘텐츠를 파싱하는 매우 간단한 앱을 만들었습니다. 데이지 그림을 지나가면 꽃잎 또는 하늘과 같은 사물이 보인다고 답했습니다. 그런 다음 두 번째 Codelab에서는 Python으로 전환하여 다섯 가지 종류의 꽃을 인식하는 새로운 커스텀 모델을 학습시켰습니다.

이 Codelab에서는 첫 번째 실습의 앱을 두 번째 실습의 모델로 업데이트합니다.

저장소를 클론하면 이 Codelab의 전체 소스 코드를 가져올 수 있습니다. Android 및 iOS의 하위 디렉터리가 표시됩니다. 이전 Codelab의 코드는 ImageClassifierStep1로 사용할 수 있습니다. 이 Codelab의 완성된 코드는 ImageClassifierStep2로 사용할 수 있습니다.

기본 요건

  • 이 학습 과정의 처음 두 Codelab을 완료했어야 합니다.

빌드하고 학습할 내용

  • 이전 실습에서 학습한 커스텀 모델을 Android 또는 iOS 앱에 통합

필요한 항목

  • Android 스튜디오(개발자의 Android 부분은 developer.android.com/studio에서 사용 가능)
  • Xcode(Apple App Store에서 제공, iOS용 실습)

2. 시작 앱 다운로드

먼저 Android 또는 iOS에서 첫 번째 컴퓨터 비전 앱 빌드하기 Codelab의 앱이 필요합니다. 실습을 완료한 경우에는 ImageClassifierStep1이라고 합니다. 실습을 진행하지 않으려면 저장소에서 완료된 버전을 클론하면 됩니다.

Android 스튜디오에서 앱을 열고 필요한 업데이트를 실행한 다음 준비가 되면 앱을 실행하여 작동하는지 확인합니다. 다음과 같은 결과를 확인할 수 있습니다.

f3703d45d1332d1d.png

이것은 상당히 원시적인 앱이지만, 약간의 코드만으로도 매우 강력한 기능을 보여줍니다. 그러나 이 꽃을 꽃뿐만 아니라 데이지로 인식하도록 하려면 이미지 분류기용 맞춤 모델 만들기 Codelab의 맞춤 모델을 사용하도록 앱을 업데이트해야 합니다.

3. 커스텀 ML Kit 모델을 사용하도록 build.gradle 업데이트

  1. Android 스튜디오를 사용하여 앱 수준 build.gradle 파일을 찾습니다. 가장 쉬운 방법은 프로젝트 탐색기를 사용하는 것입니다. 상단에서 Android를 선택하면 하단에 Gradle Scripts 폴더가 표시됩니다.
  2. 모듈용 모듈을 열고 앱 이름과 ‘.app’을 차례로 지정합니다. (모듈: ImageClassifierStep1.app):

8fe1d04b40610047.png

  1. 파일 하단에서 종속 항목 설정을 찾습니다. 여기에 다음 줄이 표시됩니다.
implementation 'com.google.mlkit:image-labeling:17.0.1'

버전 번호가 다를 수 있습니다. 항상 ML Kit 사이트(https://developers.google.com/ml-kit/vision/image-labeling/android)에서 최신 버전 번호를 확인하세요.

  1. 이를 커스텀 이미지 라벨 지정 라이브러리 참조로 바꿉니다. 버전 번호는 https://developers.google.com/ml-kit/vision/image-labeling/custom-models/android에서 확인할 수 있습니다.
implementation 'com.google.mlkit:image-labeling-custom:16.3.1'
  1. 또한 이전 실습에서 만든 .tflite 모델을 추가합니다. Android 스튜디오에서 앱을 컴파일할 때 이 모델이 압축되지 않도록 하려면 동일한 build.gradle 파일의 Android 섹션에서 이 설정을 사용해야 합니다.
aaptOptions{
    noCompress "tflite"
}

다른 설정 내에 있지 않은지 확인합니다. android 태그 바로 아래에 중첩되어야 합니다. 예를 들면 다음과 같습니다.

62d546bff11d2a50.png

4. TFLite 모델 추가

이전 Codelab에서는 커스텀 모델을 만들어 model.tflite로 다운로드했습니다.

프로젝트에서 현재 flower1.jpg이 포함된 assets 폴더를 찾습니다. 다음과 같이 모델을 해당 폴더에 복사합니다.

  1. Android 스튜디오에서 Assets 폴더를 마우스 오른쪽 버튼으로 클릭합니다. 메뉴가 열리면 Finder에서 보기를 선택합니다. (Windows에서는 ‘탐색기에서 표시’, Linux에서는 ‘파일에 표시’)

db30b47e419a326b.png

  1. 파일 시스템의 디렉터리로 이동합니다. model.tflite 파일을 flower1.jpg.와 함께 이 디렉터리에 복사합니다.

36de0c51bec1c19e.png

Android 스튜디오가 업데이트되어 애셋 폴더에 두 파일이 모두 표시됩니다.

e9f4e9f394d9b357.png

이제 코드를 업데이트할 준비가 되었습니다.

5. 커스텀 모델의 코드 업데이트

첫 번째 단계는 커스텀 모델을 로드하는 코드를 추가하는 것입니다.

  1. MainActivity 파일에서 setContentView(R.layout.activity_main)라는 줄 바로 아래의 onCreate에 다음을 추가합니다.

LocalModel을 사용하여 model.tflite 애셋에서 빌드합니다. Android 스튜디오에서 'LocalModel'을 ALT + Enter를 눌러 라이브러리를 가져옵니다. 그러면 com.google.mlkit.common.model.LocalModel에 가져오기가 자동으로 추가됩니다.

val localModel = LocalModel.Builder()
        .setAssetFilePath("model.tflite")
        .build()

이전에는 btn.setOnClickListener 핸들러에서 기본 모델을 사용했습니다. 다음 코드로 설정되었습니다.

val labeler = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS)

커스텀 모델을 사용하기 위해 교체합니다.

  1. 맞춤 옵션 객체를 설정합니다.
val options = CustomImageLabelerOptions.Builder(localModel)
        .setConfidenceThreshold(0.7f)
        .setMaxResultCount(5)
        .build()

이렇게 하면 기본 옵션이 맞춤설정된 세트로 대체됩니다. 신뢰도 임곗값은 반환할 예측 품질에 대한 기준을 설정합니다. 이미지가 데이지였던 이 Codelab 상단의 샘플을 다시 보면 예측이 4개 있고 각 예측에는 'Sky'와 같은 값이 있습니다. 0.7632입니다

높은 신뢰도 임곗값을 사용하여 낮은 품질 결과를 효과적으로 필터링할 수 있습니다. 예를 들어 0.9로 설정하면 우선순위가 이보다 낮은 라벨은 반환되지 않습니다. setMaxResultCount()는 클래스가 많은 모델에서 유용하지만 이 모델에는 5개만 있으므로 5로 둡니다.

이제 라벨러에 관한 옵션이 있으므로 라벨러의 인스턴스화를 다음과 같이 변경할 수 있습니다.

val labeler = ImageLabeling.getClient(options)

나머지 코드는 수정 없이 실행됩니다. 한번 사용해 보세요.

dd40c36c4edbb33.png

여기서 이 꽃이 데이지로 식별되었으며 확률이 0.959임을 알 수 있습니다.

두 번째 꽃 이미지를 추가하고 이 이미지로 재실행했다고 가정해 보겠습니다.

8556a5fbea487842.png

이것은 장미로 식별합니다.

'장미'가 아니라 장미로 표시된 이유가 궁금할 수 있습니다. 데이터 세트에서 라벨은 폴더 이름을 기준으로 하는데 폴더 이름은 약간 일관되지 않아 단수('데이지')를 사용하고 복수형 (예: '장미')을 사용하기 때문입니다. 이 모델을 이미지의 항목 수를 세는 모델과 혼동하지 마세요. 이 모델은 이 데이터보다 훨씬 원시적이며 꽃의 종류만 식별할 수 있습니다.

6. iOS Start 앱 다운로드

  1. 먼저 첫 번째 Codelab의 앱이 필요합니다. 실습을 완료한 경우에는 ImageClassifierStep1이라고 합니다. 실습을 진행하지 않으려면 저장소에서 완료된 버전을 클론하면 됩니다. 저장소에 포드와 .xcworkspace가 없으므로 다음 단계로 진행하기 전에 'pod install'을 실행해야 합니다. .xcproject와 동일한 디렉터리에서 생성됩니다.
  2. Xcode에서 ImageClassifierStep1.xcworkspace를 엽니다. 포드를 사용하여 ML Kit를 번들로 묶고 작업공간에서 이를 로드하므로 .xcproject가 아닌 .xcworkspace를 사용해야 합니다.

이 실습의 나머지 부분에서는 Codelab의 빌드 타겟을 지원해야 하는 iPhone 시뮬레이터에서 앱을 실행합니다. 내 기기를 사용하려면 iOS 버전과 일치하도록 프로젝트 설정에서 빌드 대상을 변경해야 할 수도 있습니다.

실행하면 다음과 같이 표시됩니다.

9e151ed18f99fb98.png

꽃잎, 꽃, 하늘 등 매우 일반적인 분류에 유의하세요. 이전 Codelab에서 만든 모델은 데이지 등 5가지 꽃을 감지하도록 학습되었습니다.

이 Codelab의 나머지 부분에서는 커스텀 모델로 앱을 업그레이드하는 데 필요한 사항을 살펴봅니다.

7. 커스텀 ML Kit 이미지 라벨러 포드 사용

첫 번째 앱은 포드 파일을 사용하여 기본 ML Kit 이미지 라벨러 라이브러리 및 모델을 가져왔습니다. 커스텀 이미지 라벨 지정 라이브러리를 사용하려면 이를 업데이트해야 합니다.

  1. 프로젝트 디렉터리에서 podfile 파일을 찾습니다. 파일을 열면 다음과 같이 표시됩니다.
platform :ios, '10.0'

target 'ImageClassifierStep1' do
        pod 'GoogleMLKit/ImageLabeling'
end
  1. 다음과 같이 포드 선언을 ImageLabeling에서 ImageLabelingCustom로 변경합니다.
platform :ios, '10.0'

target 'ImageClassifierStep1' do
        pod 'GoogleMLKit/ImageLabelingCustom'
end
  1. 완료했으면 터미널을 사용하여 podfile 및 .xcworkspace가 포함된 디렉터리로 이동하고 pod install를 실행합니다.

bb5d78eb7c7ab975.png

잠시 후 MLKitImageLabeling 라이브러리가 삭제되고 커스텀 라이브러리가 추가됩니다. 이제 .xcworkspace를 열어 코드를 수정할 수 있습니다.

8. Xcode에 TFLite 모델 추가

이전 Codelab에서는 커스텀 모델을 만들어 model.tflite로 다운로드했습니다. 아직 준비가 되어 있지 않다면 돌아가서 Codelab을 실행하거나 여기에서 Colab 코드를 진행하세요. Google Colab에 액세스할 수 없는 경우 이 링크에서 노트북을 사용할 수 있습니다.

  1. Xcode에서 작업공간을 열고 model.tflite를 프로젝트로 드래그합니다. 나머지 파일과 동일한 폴더(예: ViewController.swift 또는 Main.storyboard)에 있어야 합니다.
  2. 파일을 추가할 수 있는 옵션이 포함된 대화상자가 표시됩니다. 대상에 추가가 선택되어 있는지 확인하세요. 그렇지 않으면 모델을 기기에 배포할 때 모델이 앱과 번들로 묶이지 않습니다.

‘대상에 추가’ 이것으로 시작해서 이 실습을 단계별로 계속 진행한다면 항목에 ImageClassifierStep1이, 완성된 코드로 이동한 경우에는 ImageClassifierStep2 (그림에 참고)를 갖게 됩니다.

5b6a7f40c73f0f1f.png

이렇게 하면 모델을 로드할 수 있습니다. 다음 단계에서 방법을 확인하실 수 있습니다.

9. 커스텀 모델의 코드 업데이트

  1. ViewController.swift 파일을 엽니다. ‘import MLKitImageLabeling’에 오류가 표시될 수 있습니다 을 클릭합니다. 이는 포드 파일을 업데이트할 때 일반 이미지 라벨 지정 라이브러리를 삭제했기 때문입니다. 이 줄을 삭제하고 다음과 같이 업데이트해도 됩니다.
import MLKitVision
import MLKit
import MLKitImageLabelingCommon
import MLKitImageLabelingCustom

빠르게 읽고 같은 코드를 반복하고 있다고 생각하기 쉽습니다. 하지만 '일반적'인 '맞춤' 끝부분에 있습니다.

  1. 다음으로 이전 단계에서 추가한 커스텀 모델을 로드합니다. getLabels() 함수를 찾습니다. visionImage.orientation = image.imageOrientation 줄 아래에 다음 줄을 추가합니다.
// Add this code to use a custom model
let localModelFilePath = Bundle.main.path(forResource: "model", ofType: "tflite")
let localModel = LocalModel(path: localModelFilePath!)
  1. 일반 ImageLabeler의 옵션을 지정하기 위한 코드를 찾습니다. 이러한 라이브러리가 삭제된 후 오류가 발생할 수 있습니다.
let options = ImageLabelerOptions()

이 코드로 대체하여 CustomImageLabelerOptions를 사용하고 로컬 모델을 지정합니다.

let options = CustomImageLabelerOptions(localModel: localModel)

...이상입니다. 지금 앱을 실행해 보세요. 이미지를 분류하려고 할 때 더 정확해야 하며 높은 확률로 데이지꽃을 보고 있음을 알 수 있습니다.

238cd21748a97cf4.png

두 번째 꽃 이미지를 추가하고 이 이미지로 재실행했다고 가정해 보겠습니다.

75f3970a6b509bfe.png

앱에서 이미지가 '장미' 라벨과 일치하는 것을 감지했습니다.

10. 축하합니다.

이제 일반 모델을 사용하여 이미지 콘텐츠를 인식하는 앱을 빌드한 다음, 꽃과 같은 특정 사물을 인식하는 자체 ML 모델을 만든 다음, 커스텀 모델을 사용하도록 앱을 업데이트하는 단계로 넘어갔습니다.

결과적으로 앱은 번들된 이미지 애셋에 의존했기 때문에 매우 제한됩니다. 하지만 ML 부분은 원활하게 작동합니다. 예를 들어 AndroidX 카메라를 사용하여 실시간 피드에서 프레임을 촬영하고 분류하여 휴대전화가 어떤 꽃을 인식하는지 확인할 수 있습니다.

여기서부터 가능성은 무궁무진합니다. 꽃 이외의 것에 대한 자체 데이터가 있다면 컴퓨터 비전을 사용하여 데이터를 인식하는 앱을 빌드하는 데 필요한 토대를 갖추게 됩니다. 지금까지 더 넓은 세상을 향한 첫걸음에 불과합니다. 지금까지 이 과정을 통해 즐거운 시간을 보내셨기를 바랍니다.