Android용 이미지 생성 가이드

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

이 작업은 모델이 보강하고 생성을 위한 참조로 사용할 수 있는 선택적 조건 이미지와 함께 텍스트 프롬프트를 입력으로 받습니다. 이미지 생성기는 학습 또는 재학습 중에 모델에 제공된 특정 개념을 기반으로 이미지를 생성할 수도 있습니다. 자세한 내용은 LoRA로 맞춤설정을 참고하세요.

이 안내에 설명된 코드 샘플은 GitHub에서 제공됩니다. 이 태스크의 기능, 모델, 구성 옵션에 대한 자세한 내용은 개요를 참조하세요.

코드 예시

MediaPipe 작업 예시 코드는 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_generator/android
    

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

주요 구성요소

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

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

설정

이 섹션에서는 특히 이미지 생성기를 사용하도록 개발 환경과 코드 프로젝트를 설정하는 주요 단계를 설명합니다. 플랫폼 버전 요구사항을 포함하여 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 라이브러리 종속 항목을 AndroidManifest.xml에 추가합니다. 자세한 내용은 uses-native-library 태그에 관한 문서를 참고하세요.

일부 Android 기기에는 추가 라이브러리가 필요할 수도 있습니다.

<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를 사용하고, Canny Edge 플러그인은 edgeConditionOptions를, Depth 플러그인은 depthConditionOptions를 사용합니다.

Canny Edge 옵션

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 Edge 감지기를 참조하세요.

얼굴 특징 옵션

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)
    

캐니 에지

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)

데이터 준비

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

  • prompt (필수): 생성할 이미지를 설명하는 텍스트 프롬프트입니다.
  • iterations (필수): 이미지를 생성하기 위한 총 반복 횟수입니다. 처음에는 20 정도가 좋습니다.
  • 시드 (필수): 이미지 생성 중에 사용되는 임의의 시드입니다.
  • 조건 이미지 (선택사항): 모델이 생성을 위한 참조로 사용하는 이미지입니다. 플러그인 모델을 사용할 때만 적용됩니다.
  • 조건 유형 (선택사항): 작업과 함께 사용되는 플러그인 모델 유형입니다. 플러그인 모델을 사용할 때만 적용됩니다.

기반 모델만 사용한 입력

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())

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

입력:

  • 프롬프트: '막대형 모자를 쓰고 막대기를 들고 숲을 걷고 있는 다채로운 색상의 만화 너구리, 애니메이션, 4분의 1 보기, 그림'
  • 시드: 312687592
  • 반복: 20

생성된 이미지: