Hướng dẫn tạo hình ảnh cho Android

Tác vụ Trình tạo hình ảnh của MediaPipe cho phép bạn tạo hình ảnh dựa trên một câu lệnh dạng văn bản. Tác vụ này sử dụng mô hình chuyển văn bản sang hình ảnh để tạo hình ảnh bằng kỹ thuật khuếch tán.

Tác vụ này chấp nhận một câu lệnh dạng văn bản làm đầu vào, cùng với một hình ảnh điều kiện không bắt buộc mà mô hình có thể tăng cường và sử dụng làm tài liệu tham khảo để tạo. Công cụ tạo hình ảnh cũng có thể tạo hình ảnh dựa trên các khái niệm cụ thể được cung cấp cho mô hình trong quá trình huấn luyện hoặc huấn luyện lại. Để biết thêm thông tin, hãy xem bài viết tuỳ chỉnh bằng LoRA.

Bạn có thể xem mã mẫu được mô tả trong các hướng dẫn này trên GitHub. Để biết thêm thông tin về các chức năng, mô hình và lựa chọn cấu hình của tác vụ này, hãy xem phần Tổng quan.

Ví dụ về mã

Mã ví dụ về MediaPipe Tasks là một cách triển khai cơ bản của ứng dụng Trình tạo hình ảnh cho Android. Bạn có thể dùng ứng dụng này làm điểm bắt đầu cho ứng dụng Android của riêng mình hoặc tham khảo ứng dụng này khi sửa đổi một ứng dụng hiện có. Mã ví dụ về Trình tạo hình ảnh được lưu trữ trên GitHub.

Tải mã xuống

Hướng dẫn sau đây cho bạn biết cách tạo bản sao cục bộ của mã ví dụ bằng công cụ dòng lệnh git.

Cách tải mã ví dụ xuống:

  1. Sao chép kho lưu trữ git bằng lệnh sau:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Bạn cũng có thể định cấu hình phiên bản git để sử dụng tính năng kiểm xuất thưa thớt, nhờ đó bạn chỉ có các tệp cho ứng dụng mẫu Trình tạo hình ảnh:
    cd mediapipe-samples
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_generation/android
    

Sau khi tạo một phiên bản cục bộ của mã ví dụ, bạn có thể nhập dự án vào Android Studio và chạy ứng dụng. Để biết hướng dẫn, hãy xem Hướng dẫn thiết lập cho Android.

Thành phần chính

Các tệp sau đây chứa mã quan trọng cho ứng dụng mẫu tạo hình ảnh này:

  • ImageGenerationHelper.kt: Khởi động tác vụ và xử lý việc tạo hình ảnh.
  • DiffusionActivity.kt: Tạo hình ảnh khi không bật các trình bổ trợ hoặc trọng số LoRA.
  • PluginActivity.kt: Triển khai các mô hình trình bổ trợ, cho phép người dùng cung cấp hình ảnh điều kiện làm dữ liệu đầu vào.
  • LoRAWeightActivity.kt: Truy cập và xử lý các trọng số LoRA. Các trọng số này được dùng để tuỳ chỉnh các mô hình cơ sở và cho phép các mô hình này tạo ra hình ảnh về các khái niệm cụ thể.

Thiết lập

Phần này mô tả các bước chính để thiết lập môi trường phát triển và dự án mã của bạn, đặc biệt là để sử dụng Trình tạo hình ảnh. Để biết thông tin chung về cách thiết lập môi trường phát triển để sử dụng các tác vụ MediaPipe, bao gồm cả các yêu cầu về phiên bản nền tảng, hãy xem Hướng dẫn thiết lập cho Android.

Phần phụ thuộc

Tác vụ Trình tạo hình ảnh sử dụng thư viện com.google.mediapipe:tasks-vision-image-generator. Thêm phần phụ thuộc này vào tệp build.gradle của ứng dụng Android:

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

Đối với các thiết bị chạy Android 12 (API 31) trở lên, hãy thêm phần phụ thuộc thư viện OpenCL gốc. Để biết thêm thông tin, hãy xem tài liệu về thẻ uses-native-library.

Thêm các thẻ uses-native-library sau vào tệp AndroidManifest.xml:

<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" />

Mô hình

Tác vụ Trình tạo hình ảnh MediaPipe yêu cầu một mô hình cơ sở đã được huấn luyện và tương thích với tác vụ này. Sau khi tải một mô hình xuống, hãy cài đặt các phần phụ thuộc bắt buộc và chuyển đổi mô hình đó thành một định dạng phù hợp. Sau đó, hãy đẩy mô hình đã chuyển đổi sang thiết bị Android.

Để biết thêm thông tin về các mô hình đã được huấn luyện hiện có cho Trình tạo hình ảnh, hãy xem phần Mô hình trong phần tổng quan về tác vụ.

Tải mô hình cơ sở xuống

Trình tạo hình ảnh yêu cầu mô hình cơ sở phải khớp với định dạng mô hình stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only, dựa trên mô hình sau: stable-diffusion-v1-5/stable-diffusion-v1-5 EMA-only.

Cài đặt các phần phụ thuộc và chuyển đổi mô hình

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

Chạy tập lệnh convert.py:

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

Đẩy mô hình đã chuyển đổi sang thiết bị

Đẩy nội dung của thư mục <output_path> vào thiết bị 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

Tải các mô hình Plugin xuống và thêm trọng số LoRA (Không bắt buộc)

Nếu bạn dự định sử dụng một mô hình trình bổ trợ, hãy kiểm tra xem có cần tải mô hình xuống hay không. Đối với các trình bổ trợ yêu cầu một mô hình bổ sung, các mô hình trình bổ trợ phải được kết hợp trong APK hoặc tải xuống theo yêu cầu. Các mô hình trình bổ trợ có dung lượng nhỏ (~23 MB) và có thể được kết hợp trực tiếp trong tệp APK. Tuy nhiên, bạn nên tải các mô hình trình bổ trợ xuống theo yêu cầu.

Nếu bạn đã tuỳ chỉnh một mô hình bằng LoRA, hãy tải chúng xuống theo yêu cầu. Để biết thêm thông tin, hãy xem mô hình trình bổ trợ về trọng số LoRA.

Tạo việc cần làm

Tác vụ Trình tạo hình ảnh của MediaPipe sử dụng hàm createFromOptions() để thiết lập tác vụ. Hàm createFromOptions() chấp nhận các giá trị cho lựa chọn cấu hình. Để biết thêm thông tin về các lựa chọn cấu hình, hãy xem phần Các lựa chọn cấu hình.

Các lựa chọn về cấu hình

Tác vụ này có các lựa chọn cấu hình sau đây cho ứng dụng Android:

Tên tuỳ chọn Mô tả Phạm vi giá trị
imageGeneratorModelDirectory Thư mục mô hình trình tạo hình ảnh lưu trữ các trọng số mô hình. PATH
loraWeightsFilePath Đặt đường dẫn đến tệp trọng số LoRA. Không bắt buộc và chỉ áp dụng nếu mô hình được tuỳ chỉnh bằng LoRA. PATH
errorListener Đặt một trình nghe lỗi không bắt buộc. N/A

Tác vụ này cũng hỗ trợ các mô hình bổ trợ, cho phép người dùng đưa hình ảnh điều kiện vào dữ liệu đầu vào của tác vụ. Mô hình cơ sở có thể tăng cường và sử dụng hình ảnh này làm tài liệu tham khảo để tạo. Những hình ảnh điều kiện này có thể là các điểm đánh dấu trên khuôn mặt, đường viền và ước tính độ sâu mà mô hình sử dụng làm ngữ cảnh và thông tin bổ sung để tạo hình ảnh.

Khi thêm một mô hình trình bổ trợ vào mô hình nền tảng, hãy định cấu hình các lựa chọn trình bổ trợ. Trình bổ trợ Điểm đánh dấu trên khuôn mặt sử dụng faceConditionOptions, trình bổ trợ Canny edge sử dụng edgeConditionOptions và trình bổ trợ Độ sâu sử dụng depthConditionOptions.

Các lựa chọn về cạnh Canny

Định cấu hình các lựa chọn sau trong edgeConditionOptions.

Tên tuỳ chọn Mô tả Phạm vi giá trị Giá trị mặc định
threshold1 Ngưỡng đầu tiên cho quy trình trễ. Float 100
threshold2 Ngưỡng thứ hai cho quy trình trễ. Float 200
apertureSize Kích thước khẩu độ cho toán tử Sobel. Phạm vi thông thường là từ 3 đến 7. Integer 3
l2Gradient Có sử dụng chuẩn L2 để tính độ lớn của độ dốc hình ảnh hay không, thay vì chuẩn L1 mặc định. BOOLEAN False
EdgePluginModelBaseOptions Đối tượng BaseOptions đặt đường dẫn cho mô hình trình bổ trợ. Đối tượng BaseOptions N/A

Để biết thêm thông tin về cách hoạt động của các lựa chọn cấu hình này, hãy xem phần Công cụ phát hiện cạnh Canny.

Các lựa chọn về điểm đánh dấu trên khuôn mặt

Định cấu hình các lựa chọn sau trong faceConditionOptions.

Tên tuỳ chọn Mô tả Phạm vi giá trị Giá trị mặc định
minFaceDetectionConfidence Điểm tin cậy tối thiểu để tính năng phát hiện khuôn mặt được coi là thành công. Float [0.0,1.0] 0.5
minFacePresenceConfidence Điểm số tin cậy tối thiểu của điểm số hiện diện khuôn mặt trong tính năng phát hiện điểm đánh dấu trên khuôn mặt. Float [0.0,1.0] 0.5
faceModelBaseOptions Đối tượng BaseOptions đặt đường dẫn cho mô hình tạo hình ảnh điều kiện. Đối tượng BaseOptions N/A
FacePluginModelBaseOptions Đối tượng BaseOptions đặt đường dẫn cho mô hình trình bổ trợ. Đối tượng BaseOptions N/A

Để biết thêm thông tin về cách hoạt động của các lựa chọn cấu hình này, hãy xem tác vụ Face Landmarker.

Các lựa chọn về chiều sâu

Định cấu hình các lựa chọn sau trong depthConditionOptions.

Tên tuỳ chọn Mô tả Phạm vi giá trị Giá trị mặc định
depthModelBaseOptions Đối tượng BaseOptions đặt đường dẫn cho mô hình tạo hình ảnh điều kiện. Đối tượng BaseOptions N/A
depthPluginModelBaseOptions Đối tượng BaseOptions đặt đường dẫn cho mô hình trình bổ trợ. Đối tượng BaseOptions N/A

Tạo chỉ bằng mô hình cơ sở

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Tạo bằng trình bổ trợ

Nếu bạn đang áp dụng một mô hình trình bổ trợ không bắt buộc, hãy đặt các lựa chọn cơ bản cho mô hình trình bổ trợ bằng setPluginModelBaseOptions. Nếu mô hình trình bổ trợ yêu cầu một mô hình đã tải xuống bổ sung để tạo hình ảnh điều kiện, hãy chỉ định đường dẫn trong BaseOptions.

Điểm đánh dấu trên khuôn mặt

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)
    

Chiều sâu

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)
    

Sáng tạo bằng trọng số LoRA

Nếu bạn đang thêm trọng số LoRA, hãy sử dụng tham số loraWeightsFilePath để chỉ đến vị trí đường dẫn.

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

imageGenerator = ImageGenerator.createFromOptions(context, options)

Chuẩn bị dữ liệu

Trình tạo hình ảnh chấp nhận các dữ liệu đầu vào sau:

  • prompt (bắt buộc): Câu lệnh dạng văn bản mô tả hình ảnh sẽ được tạo.
  • iterations (bắt buộc): Tổng số lần lặp lại để tạo hình ảnh. Điểm bắt đầu phù hợp là 20.
  • seed (bắt buộc): Giá trị ban đầu ngẫu nhiên được dùng trong quá trình tạo hình ảnh.
  • hình ảnh điều kiện (không bắt buộc): Hình ảnh mà mô hình dùng làm tài liệu tham khảo để tạo. Chỉ áp dụng khi sử dụng mô hình trình bổ trợ.
  • condition type (không bắt buộc): Loại mô hình trình bổ trợ được dùng với tác vụ. Chỉ áp dụng khi sử dụng mô hình trình bổ trợ.

Đầu vào chỉ có mô hình nền tảng

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

Đầu vào có trình bổ trợ

Nếu bạn đang áp dụng một mô hình trình bổ trợ không bắt buộc, hãy sử dụng tham số conditionType để chọn mô hình trình bổ trợ và tham số sourceConditionImage để tạo hình ảnh điều kiện.

Tên tuỳ chọn Mô tả Giá trị
conditionType Mô hình trình bổ trợ được áp dụng cho mô hình nền tảng. {"FACE", "EDGE", "DEPTH"}
sourceConditionImage Hình ảnh nguồn dùng để tạo hình ảnh điều kiện. Đối tượng MPImage

Nếu bạn đang sử dụng mô hình trình bổ trợ, hãy dùng createConditionImage để tạo hình ảnh điều kiện:

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

Sau khi tạo hình ảnh điều kiện, hãy đưa hình ảnh đó vào làm dữ liệu đầu vào cùng với câu lệnh, giá trị ban đầu và số lần lặp lại.

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

Đầu vào có trọng số LoRA

Nếu bạn đang sử dụng trọng số LoRA, hãy đảm bảo rằng mã thông báo nằm trong câu lệnh dạng văn bản nếu bạn dự định tạo hình ảnh có khái niệm cụ thể do trọng số thể hiện.

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

Chạy tác vụ

Sử dụng phương thức generate() để tạo hình ảnh bằng các dữ liệu đầu vào được cung cấp trong phần trước. Thao tác này sẽ tạo ra một hình ảnh duy nhất.

Tạo chỉ bằng mô hình cơ sở

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

Tạo bằng trình bổ trợ

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
}

Tạo bằng trọng số LoRA

Quy trình tạo hình ảnh bằng một mô hình được tuỳ chỉnh bằng trọng số LoRA tương tự như quy trình tạo hình ảnh bằng một mô hình cơ sở tiêu chuẩn. Đảm bảo rằng mã thông báo có trong câu lệnh và chạy cùng một mã.

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

Tạo theo vòng lặp

Trình tạo hình ảnh cũng có thể xuất các hình ảnh trung gian được tạo trong mỗi lần lặp, như được xác định trong tham số đầu vào iterations. Để xem các kết quả trung gian này, hãy gọi phương thức setInputs, sau đó gọi execute() để chạy từng bước. Đặt tham số showResult thành true để hiển thị kết quả trung gian.

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

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

    return bitmap
}

Xử lý và hiển thị kết quả

Trình tạo hình ảnh trả về một ImageGeneratorResult, bao gồm hình ảnh được tạo, dấu thời gian hoàn thành và hình ảnh có điều kiện (nếu có) được cung cấp làm dữ liệu đầu vào.

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

Hình ảnh sau đây được tạo từ các dữ liệu đầu vào sau đây, chỉ sử dụng một mô hình cơ sở.

Thiết bị đầu vào:

  • Câu lệnh: "một chú gấu mèo hoạt hình đầy màu sắc đang đội chiếc mũ rộng vành mềm mại, tay cầm một chiếc gậy đi bộ xuyên rừng, ảnh động, góc nhìn ba phần tư, tranh vẽ"
  • Số ngẫu nhiên: 312687592
  • Số lần lặp lại: 20

Hình ảnh được tạo:

Hình ảnh được tạo về một con gấu trúc phù hợp với câu lệnh