Android용 이미지 생성 가이드

MediaPipe 이미지 생성기 작업을 사용하면 텍스트 프롬프트를 기반으로 이미지를 생성할 수 있습니다. 이 작업에서는 텍스트-이미지 모델을 사용하여 확산 기법을 통해 이미지를 생성합니다.

이 태스크는 텍스트 프롬프트를 입력으로 받으며, 모델이 보강하여 생성의 참조로 사용할 수 있는 조건 이미지(선택사항)도 받습니다. 이미지 생성기는 학습 또는 재학습 중에 모델에 제공된 특정 개념을 기반으로 이미지를 생성할 수도 있습니다. 자세한 내용은 LoRA로 맞춤설정을 참고하세요.

이 안내에 설명된 코드 샘플은 GitHub에서 확인할 수 있습니다. 이 태스크의 기능, 모델, 구성 옵션에 관한 자세한 내용은 개요를 참고하세요.

코드 예

MediaPipe Tasks 예시 코드는 Android용 이미지 생성기 앱의 기본 구현입니다. 이 앱을 자체 Android 앱의 시작점으로 사용하거나 기존 앱을 수정할 때 참고할 수 있습니다. 이미지 생성기 예시 코드는 GitHub에서 호스팅됩니다.

코드 다운로드

다음 안내에서는 git 명령줄 도구를 사용하여 예시 코드의 로컬 사본을 만드는 방법을 보여줍니다.

예시 코드를 다운로드하려면 다음 안내를 따르세요.

  1. 다음 명령어를 사용하여 git 저장소를 클론합니다.
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. 원하는 경우 이미지 생성기 예시 앱의 파일만 포함되도록 스파스 체크아웃을 사용하도록 git 인스턴스를 구성합니다.
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generation/android
    

예시 코드의 로컬 버전을 만든 후 프로젝트를 Android 스튜디오로 가져와 앱을 실행할 수 있습니다. 안내는 Android 설정 가이드를 참고하세요.

주요 구성요소

다음 파일에는 이 이미지 생성 예시 애플리케이션의 중요한 코드가 포함되어 있습니다.

  • ImageGenerationHelper.kt: 작업을 초기화하고 이미지 생성을 처리합니다.
  • DiffusionActivity.kt: 플러그인 또는 LoRA 가중치가 사용 설정되지 않은 경우 이미지를 생성합니다.
  • PluginActivity.kt: 사용자가 조건 이미지를 입력으로 제공할 수 있는 플러그인 모델을 구현합니다.
  • LoRAWeightActivity.kt: 기반 모델을 맞춤설정하고 특정 개념의 이미지를 생성할 수 있도록 하는 데 사용되는 LoRA 가중치에 액세스하고 이를 처리합니다.

설정

이 섹션에서는 특히 Image Generator를 사용하기 위해 개발 환경 및 코드 프로젝트를 설정하는 주요 단계를 설명합니다. 플랫폼 버전 요구사항을 비롯하여 MediaPipe 작업을 사용하기 위한 개발 환경 설정에 관한 일반적인 정보는 Android 설정 가이드를 참고하세요.

종속 항목

이미지 생성기 작업은 com.google.mediapipe:tasks-vision-image-generator 라이브러리를 사용합니다. Android 앱의 build.gradle 파일에 다음 종속 항목을 추가합니다.

dependencies {
    implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'
}

Android 12 (API 31) 이상을 실행하는 기기의 경우 네이티브 OpenCL 라이브러리 종속 항목을 추가합니다. 자세한 내용은 uses-native-library 태그 문서를 참고하세요.

AndroidManifest.xml 파일에 다음 uses-native-library 태그를 추가합니다.

<uses-native-library android:name="libOpenCL.so" android:required="false" />
<uses-native-library android:name="libOpenCL-car.so" android:required="false"/>
<uses-native-library android:name="libOpenCL-pixel.so" android:required="false" />

모델

MediaPipe 이미지 생성기 태스크에는 이 태스크와 호환되는 학습된 기반 모델이 필요합니다. 모델을 다운로드한 후 필요한 종속 항목을 설치하고 모델을 적절한 형식으로 변환합니다. 그런 다음 변환된 모델을 Android 기기로 푸시합니다.

이미지 생성기에 사용할 수 있는 학습된 모델에 관한 자세한 내용은 작업 개요 모델 섹션을 참고하세요.

기반 모델 다운로드

이미지 생성기에는 다음 모델(runwayml/stable-diffusion-v1-5)을 기반으로 하는 기반 모델이 runwayml/stable-diffusion-v1-5 EMA-only 모델 형식과 일치해야 합니다.

종속 항목 설치 및 모델 변환

$ pip install torch typing_extensions numpy Pillow requests pytorch_lightning absl-py

convert.py 스크립트를 실행합니다.

$ python3 convert.py --ckpt_path <ckpt_path> --output_path <output_path>

변환된 모델을 기기에 푸시

<output_path> 폴더의 콘텐츠를 Android 기기로 푸시합니다.

$ adb shell rm -r /data/local/tmp/image_generator/ # Remove any previously loaded weights
$ adb shell mkdir -p /data/local/tmp/image_generator/
$ adb push <output_path>/. /data/local/tmp/image_generator/bins

플러그인 모델 다운로드 및 LoRA 가중치 추가 (선택사항)

플러그인 모델을 사용하려면 모델을 다운로드해야 하는지 확인합니다. 추가 모델이 필요한 플러그인의 경우 플러그인 모델을 APK에 번들로 묶거나 주문형으로 다운로드해야 합니다. 플러그인 모델은 가볍고 (~23MB) APK에 직접 번들로 묶을 수 있습니다. 하지만 플러그인 모델은 필요할 때 다운로드하는 것이 좋습니다.

LoRA로 모델을 맞춤설정한 경우 주문형으로 다운로드합니다. 자세한 내용은 LoRA 가중치 플러그인 모델을 참고하세요.

할 일 만들기

MediaPipe 이미지 생성기 태스크는 createFromOptions() 함수를 사용하여 태스크를 설정합니다. createFromOptions() 함수는 구성 옵션의 값을 허용합니다. 구성 옵션에 관한 자세한 내용은 구성 옵션을 참고하세요.

구성 옵션

이 작업에는 Android 앱에 관한 다음과 같은 구성 옵션이 있습니다.

옵션 이름 설명 값 범위
imageGeneratorModelDirectory 모델 가중치를 저장하는 이미지 생성기 모델 디렉터리입니다. PATH
loraWeightsFilePath LoRA 가중치 파일의 경로를 설정합니다. 선택사항이며 LoRA로 모델이 맞춤설정된 경우에만 적용됩니다. PATH
errorListener 선택적 오류 리스너를 설정합니다. N/A

이 태스크는 플러그인 모델도 지원합니다. 이를 통해 사용자는 태스크 입력에 조건 이미지를 포함할 수 있으며, 기반 모델은 이를 보강하고 생성의 참조로 사용할 수 있습니다. 이러한 조건 이미지는 얼굴 지형지물, 가장자리 윤곽선, 깊이 추정치일 수 있으며, 모델은 이러한 이미지를 이미지를 생성하기 위한 추가 컨텍스트 및 정보로 사용합니다.

기반 모델에 플러그인 모델을 추가할 때는 플러그인 옵션도 구성합니다. 얼굴 지형지물 플러그인은 faceConditionOptions를 사용하고, 카니니 가장자리 플러그인은 edgeConditionOptions를 사용하며, 깊이 플러그인은 depthConditionOptions를 사용합니다.

Canny 가장자리 옵션

edgeConditionOptions에서 다음 옵션을 구성합니다.

옵션 이름 설명 값 범위 기본값
threshold1 히스테리시스 절차의 첫 번째 임곗값입니다. Float 100
threshold2 히스터시스 절차의 두 번째 임곗값입니다. Float 200
apertureSize Sobel 연산자의 조리개 크기입니다. 일반적인 범위는 3~7입니다. Integer 3
l2Gradient 기본 L1 norm 대신 L2 norm을 사용하여 이미지 기울기 크기를 계산하는지 여부입니다. BOOLEAN False
EdgePluginModelBaseOptions 플러그인 모델의 경로를 설정하는 BaseOptions 객체입니다. BaseOptions 객체 N/A

이러한 구성 옵션의 작동 방식에 관한 자세한 내용은 Canny 가장자리 검출기를 참고하세요.

얼굴 특징 옵션

faceConditionOptions에서 다음 옵션을 구성합니다.

옵션 이름 설명 값 범위 기본값
minFaceDetectionConfidence 얼굴 감지가 성공으로 간주되는 최소 신뢰도 점수입니다. Float [0.0,1.0] 0.5
minFacePresenceConfidence 얼굴 특징 감지에서 얼굴 존재 점수의 최소 신뢰도 점수입니다. Float [0.0,1.0] 0.5
faceModelBaseOptions 조건 이미지를 만드는 모델의 경로를 설정하는 BaseOptions 객체입니다. BaseOptions 객체 N/A
FacePluginModelBaseOptions 플러그인 모델의 경로를 설정하는 BaseOptions 객체입니다. BaseOptions 객체 N/A

이러한 구성 옵션의 작동 방식에 관한 자세한 내용은 얼굴 랜드마커 태스크를 참고하세요.

깊이 옵션

depthConditionOptions에서 다음 옵션을 구성합니다.

옵션 이름 설명 값 범위 기본값
depthModelBaseOptions 조건 이미지를 만드는 모델의 경로를 설정하는 BaseOptions 객체입니다. BaseOptions 객체 N/A
depthPluginModelBaseOptions 플러그인 모델의 경로를 설정하는 BaseOptions 객체입니다. BaseOptions 객체 N/A

기반 모델만 사용하여 만들기

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

플러그인으로 만들기

선택적 플러그인 모델을 적용하는 경우 setPluginModelBaseOptions를 사용하여 플러그인 모델의 기본 옵션을 설정합니다. 플러그인 모델에 조건 이미지를 만들기 위해 다운로드한 추가 모델이 필요한 경우 BaseOptions에 경로를 지정합니다.

얼굴 특징

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val faceModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("face_landmarker.task")
    .build()

val facePluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("face_landmark_plugin.tflite")
    .build()

val faceConditionOptions = FaceConditionOptions.builder()
    .setFaceModelBaseOptions(faceModelBaseOptions)
    .setPluginModelBaseOptions(facePluginModelBaseOptions)
    .setMinFaceDetectionConfidence(0.3f)
    .setMinFacePresenceConfidence(0.3f)
    .build()

val conditionOptions = ConditionOptions.builder()
    .setFaceConditionOptions(faceConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

Canny Edge

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val edgePluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("canny_edge_plugin.tflite")
    .build()

val edgeConditionOptions = EdgeConditionOptions.builder()
    .setThreshold1(100.0f)
    .setThreshold2(100.0f)
    .setApertureSize(3)
    .setL2Gradient(false)
    .setPluginModelBaseOptions(edgePluginModelBaseOptions)
    .build()

val conditionOptions = ConditionOptions.builder()
    .setEdgeConditionOptions(edgeConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

깊이

val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

val depthModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("depth_model.tflite")
    .build()

val depthPluginModelBaseOptions = BaseOptions.builder()
    .setModelAssetPath("depth_plugin.tflite")
    .build()

val depthConditionOptions =
    ConditionOptions.DepthConditionOptions.builder()
        .setDepthModelBaseOptions(depthModelBaseOptions)
        .setPluginModelBaseOptions(depthPluginModelBaseOptions)
        .build()

val conditionOptions = ConditionOptions.builder()
    .setDepthConditionOptions(depthConditionOptions)
    .build()

imageGenerator =
    ImageGenerator.createFromOptions(context, options, conditionOptions)
    

LoRA 가중치로 만들기

LoRA 가중치를 포함하는 경우 loraWeightsFilePath 매개변수를 사용하여 경로 위치를 가리킵니다.

val options = ImageGeneratorOptions.builder()
    .setLoraWeightsFilePath(weightsPath)
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

데이터 준비

이미지 생성기는 다음 입력을 허용합니다.

  • 프롬프트 (필수): 생성할 이미지를 설명하는 텍스트 프롬프트입니다.
  • iterations (필수): 이미지를 생성하는 총 반복 횟수입니다. 적절한 시작점은 20입니다.
  • seed (필수): 이미지 생성 중에 사용되는 무작위 시드입니다.
  • 조건 이미지 (선택사항): 모델이 생성의 참조로 사용하는 이미지입니다. 플러그인 모델을 사용할 때만 적용됩니다.
  • 조건 유형 (선택사항): 태스크에 사용되는 플러그인 모델의 유형입니다. 플러그인 모델을 사용할 때만 적용됩니다.

기반 모델만 있는 입력

fun setInput(prompt: String, iteration: Int, seed: Int) {
    imageGenerator.setInputs(prompt, iteration, seed)
}

플러그인 사용 시 입력

선택적 플러그인 모델을 적용하는 경우 conditionType 매개변수를 사용하여 플러그인 모델을 선택하고 sourceConditionImage 매개변수를 사용하여 조건 이미지를 생성합니다.

옵션 이름 설명
conditionType 기반 모델에 적용된 플러그인 모델입니다. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage 상태 이미지를 만드는 데 사용된 소스 이미지입니다. MPImage 객체

플러그인 모델을 사용하는 경우 createConditionImage를 사용하여 조건 이미지를 만듭니다.

fun createConditionImage(
    inputImage: MPImage,
    conditionType: ConditionType
): Bitmap {
    val result =
        imageGenerator.createConditionImage(inputImage, conditionType)
    return BitmapExtractor.extract(result)
}

조건 이미지를 만든 후 프롬프트, 시드, 반복 횟수와 함께 입력으로 포함합니다.

imageGenerator.setInputs(
    prompt,
    conditionalImage,
    conditionType,
    iteration,
    seed
)

LoRA 가중치가 있는 입력

LoRA 가중치를 사용하는 경우 가중치로 표현된 특정 개념으로 이미지를 생성하려면 토큰이 텍스트 프롬프트에 있는지 확인하세요.

fun setInput(prompt: String, iteration: Int, seed: Int) {
    imageGenerator.setInputs(prompt, iteration, seed)
}

태스크 실행

generate() 메서드를 사용하여 이전 섹션에 제공된 입력을 사용하여 이미지를 생성합니다. 이렇게 하면 단일 생성 이미지가 생성됩니다.

기반 모델만 사용하여 생성

fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
    val result = imageGenerator.generate(prompt, iteration, seed)
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

플러그인으로 생성

fun generate(
    prompt: String,
    inputImage: MPImage,
    conditionType: ConditionType,
    iteration: Int,
    seed: Int
): Bitmap {
    val result = imageGenerator.generate(
        prompt,
        inputImage,
        conditionType,
        iteration,
        seed
    )
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

LoRA 가중치로 생성

LoRA 가중치로 맞춤설정된 모델로 이미지를 생성하는 프로세스는 표준 기반 모델을 사용하는 프로세스와 유사합니다. 토큰이 프롬프트에 포함되어 있는지 확인하고 동일한 코드를 실행합니다.

fun generate(prompt: String, iteration: Int, seed: Int): Bitmap {
    val result = imageGenerator.generate(prompt, iteration, seed)
    val bitmap = BitmapExtractor.extract(result?.generatedImage())
    return bitmap
}

반복 생성

이미지 생성기는 iterations 입력 매개변수에 정의된 대로 각 반복 중에 생성된 중간 이미지를 출력할 수도 있습니다. 이러한 중간 결과를 보려면 setInputs 메서드를 호출한 다음 execute()를 호출하여 각 단계를 실행합니다. showResult 매개변수를 true로 설정하여 중간 결과를 표시합니다.

fun execute(showResult: Boolean): Bitmap {
    val result = imageGenerator.execute(showResult)

    val bitmap =
        BitmapExtractor.extract(result.generatedImage())

    return bitmap
}

결과 처리 및 표시

이미지 생성기는 생성된 이미지, 완료 시간의 타임스탬프, 조건부 이미지(입력으로 제공된 경우)가 포함된 ImageGeneratorResult를 반환합니다.

val bitmap = BitmapExtractor.extract(result.generatedImage())

다음 이미지는 기반 모델만 사용하여 다음 입력에서 생성되었습니다.

입력:

  • 프롬프트: "넓은 챙이 달린 헐렁한 모자를 쓰고 막대기를 들고 숲을 걸어가는 다채로운 색상의 만화 너구리, 애니메이션, 3/4 뷰, 그림"
  • 시드: 312687592
  • 반복: 20

생성된 이미지: