Сегодня крупными мазками я опишу процесс тренировки модели Stable Diffusion для генерации изображений с лицом обученным на фотографиях, написание и деплой смартконтракта ERC721, заливки картинки в сеть IPFS, минт NFT и установки токена на аватарку в VK через VK NFT Hub.
Предупреждение
Данный гайд не содержит подробного описания "шаг за шагом", но позволит сопоставить весь процесс в голове от начала до конца. Требователен к знанию python, js, solidity и работе с командной строкой. В основном я буду ссылаться на документацию и останавливаться лишь на ключевых моментах.
Содержание
- Stable Diffusion - линки и рекомендации по установке софта для генерации изображений, моделей, конфигов и др.
- Обучение с Dreambooth - подготовка изображений, запуск Jupyter Notebook на удаленной машине и обучение модели.
- Генерация изображений - основные моменты по работе с SD.
- Подготовка и деплой смартконтракта - последовательность действий и лучшие практики для написания и заливки смартконтракта в блокчейн.
- Загрузка данных в IPFS и минт токена - заливка изображения и метаданных токена в сеть IPFS, выпуск NFT токена.
- Установка аватара VK.
Stable Diffusion
Первым делом мы установим Stable Diffusion на нашу локальную машину. Следующие две ссылки приведены для ознакомления, по началу я работал с ними через консоль с возможностью покопаться в коде. Но для практического применения они мало эффективны и лучше использовать сборку от AUTOMATIC1111 или InvokeAI.
Супер комбайн SD с отличным веб-интерфейсом и уже добавленными плагинами https://github.com/AUTOMATIC1111/stable-diffusion-webui.
Нам потребуются модели для генерации и обучения:
При скачивании моделей будьте аккуратны и загружайте ckpt только от достоверных пользователей, они все содержат pickle imports, куда можно при желании внедрить вредоносный код.
YML файлы под 2.1 модель:
Под 1.5 подойдет стандартный YML конфиг, который идет с репозиторием Stable Diffusion от AUTOMATIC1111.
Для Data Science хорошим тоном считается использование Anaconda в качестве виртуального окружения, но по удивительной причине в репозитории AUTOMATIC1111 используется обычный venv питона. Поэтому, чтобы подружить виртуальное окружение conda с SD необходимо внести небольшие изменения, как в этом коммите https://github.com/kompotkot/stable-diffusion-webui/commit/e448531fe56c8364ec81d79bb06c4301279429b7
После того как все зависимости установлены и SD запущен через ./webui-user, переходим на http://127.0.0.1:7860.
Полезные ссылки
LDSR - улучшит детализацию, источник - https://github.com/Hafiidz/latent-diffusion.
ESRGAN - улучшит детализацию и позволит увеличить разрешения выходной картинки, источник и модели - https://github.com/xinntao/Real-ESRGAN/releases.
GFPGAN - корректировка человеческих лиц, источник и модели - https://github.com/TencentARC/GFPGAN/releases.
Protogen x3.4 модель - https://civitai.com/models/3666/protogen-x34-official-release.
Обучение с Dreambooth
Для обучения нашей модели мы подготовим 20 изображений в хорошем качестве на однотонном фоне:
- Фотографии лица с близкого расстояния
- Фотографии со средней дистанции с лицом и торсом
- Фотографии всей фигуры
Все фотографии нам необходимо привести к одному размеру, для чего воспользуемся https://www.birme.net. Я обучал на модели SD 1.5 512х512, так что и размер фотографий должен быть соответствующий.
Далее необходимо арендовать мощности на https://www.runpod.io с видеокартой минимум 24Gb GPU VRAM (например RTX A5000) и запустить машину с настройками:
- Container Disk 50
- Volume Disk 50
- Template RunPod SD Auto1111 v1.5
- Галочка на Start Jupyter Notebook
Жмем Deploy и по готовности Connect to Jupyter Lab [Port 8888]. Последующие шаги будут осуществляться в открытой вкладке Jupyter Lab.
Нам необходимо склонировать репозиторий https://github.com/JoePenna/Dreambooth-Stable-Diffusion с Dreambooth на удаленную машину с помощью команды:
!git clone https://github.com/JoePenna/Dreambooth-Stable-Diffusion.git
Загрузим наши фотографии и базовую модель SD 1.5 для обучения. Так как модель весит порядка 7.7Gb советую это делать с помощью gdown предварительно залив файл на ваш Google Drive и создав публичную ссылку.
Далее в файле dreambooth_runpod_joepenna.ipynb необходимо закомментировать первый блок кода с клонированием репозитория, третий и четвертый блок с загрузкой модели из huggingface.
По неизвестной причине для заливки обучающих изображений в коде используется imgur, также удалим связанные с этим два первых блока кода в разделе Upload your training images. И заменим на:
images = []
save_path = "./training_images"
for path in os.listdir(save_path):
if os.path.isfile(os.path.join(save_path, path)):
images.append(path)
print(f"List of training images: {images}")
Далее в разделе Training задать project_name, class_word и token. Значение max_training_steps равное 2000 в целом излишне, можно остановиться на 1000, тут уже на ваше усмотрение, главное помнить изменяя параметры, что, модель мы можем как недоучить, так и переобучить.
После исполнения последних блоков кода, мы обучим, сожмем и останется только загрузить модель себе на пк.
Полезные ссылки
https://github.com/nitrosocke/dreambooth-training-guide - хорошие советы по обучению модели.
https://github.com/XavierXiao/Dreambooth-Stable-Diffusion/issues/33#issuecomment-1260470949 - поможет решить баг, если обучение модели будет прерываться после первой итерации.
Генерация изображений
В целом, это полностью зависит от вашего воображения и цели, которую вы хотите достичь. Из инструментов, которые могут быть полезны:
https://lexica.art - хороший источник inputs.
https://github.com/Dalabad/stable-diffusion-prompt-templates - примеры как организовать последовательность слов в зависимости от желаемого результата.
Во время генерации лучше указывать список авторов или применять embeddings с желаемым стилем:
https://www.artstation.com - источник имен художников.
https://civitai.com - источник embeddings, если отфильтровать поиск по Textual Inversion.
Для себя я вывел примерную последовательность действий:
- Генерирую с помощью txt2img по 6 изображений с Sampling Steps равным 60 попеременно меняя input и negative input, при необходимости добавляя embeddings.
- Обычно среди 20 генераций я выбираю пару изображений которые мне нравятся.
- Загружаю удачные изображения в img2img inpaint и с помощью маски, input, denoising strength и seed - добиваюсь изменения необходимых частей изображения, как фон, одежда, части лица и тд.
Также существует полезный скрипт Depth aware img2img mask позволяющий генерировать и менять объекты в зависимости от их положения на сцене и множество других скриптов.
Подготовка и деплой смартконтракта
Для того чтобы выпустить (mint) токен NFT нам необходимо задеплоить смартконтракт ERC721 в блокчейн Polygon (Matic).
Вначале мы создадим проект с помощью мультитула hardhat https://hardhat.org/hardhat-runner/docs/guides/project-setup.
Сгенерируем болванку ERC721 контракта с помощью https://wizard.openzeppelin.com/#erc721.
Выберем Features:
- Mintable - добавит возможность выпускать новые токены.
- Auto Increment Ids - будет вести счетчик выпущенных токенов.
- Burnable - позволит сжигать (уничтожать) токены собственниками.
- URI Storage - добавит возможность хранить ссылку на json метаданные токена.
Выберем Access Control:
- Ownable - кроме собственника смартконтракта никто не сможет выпускать токены.
Если в вашем контракте необходимо пробрасывать bytes в аргументах функции, обратите внимание на ReentrancyGuard защищающий от вложенных функций. Но для нашего варианта, можно обойтись без него.
Далее воспользуемся скриптом для деплоя https://hardhat.org/hardhat-runner/docs/guides/deploying предварительно создав переменную окружения с нашим приватным ключом, который можно импортировать из метамаска или сгенерировать при помощи утилы geth в консоли. URL до ноды можно сгенерировать в Infura или QuickNode.
После деплоя смартконтракта удостоверимся, что контракт существует на https://polygonscan.com и выпущено 0 токенов.
Полезные ссылки
https://github.com/bugout-dev/moonworm - позволит сгенерировать CLI для взаимодействия со смартконтрактом, благодаря чему можно обойтись без написания отдельных скриптов для hardhat.
Загрузка данных в IPFS и минт токена
Воспользуемся базовым CLI приложением Kubo https://docs.ipfs.tech/install/command-line/ для загрузки изображения:
ipfs add AVASTG-img-0.png
Полученный CID добавим в json:
{
"name": "User 0",
"description": "Avatar of User 0.",
"image": "ipfs://<CID_to_AVASTG_img_0>"
}
Загрузим в сеть файл с метаданными:
ipfs add AVASTG-metadata-0.json
Далее нам нужно запустить демон IPFS чтобы синхронизироваться с сетью:
ipfs daemon
Если вы не планируете держать ноду IPFS онлайн все время, то нам понадобится сервис который будет так же хранить нашу картинку и файл с метаданными. В противном случае наши данные будут вычищены с помощью Garbage Collector и станут недоступны.
Воспользуемся сервисом https://www.pinata.cloud/, для чего нам понадобиться создать аккаунт и сгенерировать Api key. У ключа должны быть права pinByHash. Нам останется "запинить" (выкачать с нашей ноды) файлы и разместить на сервисе Pinata:
curl --location --request POST 'https://api.pinata.cloud/pinning/pinByHash' --header "Authorization: Bearer <your_pinata_jwt_api_key>" --header 'Con
tent-Type: application/json' --data-raw '{
"hashToPin": "<CID_to_file_on_your_local_node>",
"pinataMetadata": {
"name": "<name_of_the_file>"
}
}'
Осталось выпустить (minting) токен, для чего можно воспользоваться сгенерированным CLI с помощью moonworm или hardhat скриптом, например:
const avatarStorage = await ethers.getContractAt("AvatarStorage", contractAddress)
const signers = await ethers.getSigners()
const contractOwner = signers[0].address
let tx = await avatarStorage.safeMint(signers[0].address, "ipfs://<CID_to_metadata_json_file>")
await tx.wait()
console.log(`NFT minted to: ${contractOwner}\n`)
Установка аватара VK
С недавнего времени VKontakte добавил возможность привязать свой кошелек Metamask к аккаунту. Для этого вас попросят сгенерировать подпись на основании которой VK удостоверятся, что вы являетесь владельцем крипто-кошелька. Далее ваш адрес будет привязан и последующее взаимодействие с кошельком более не понадобиться.
После привязки вы сможете отображать выбранные вами токены у вас на страничке во вкладке NFT витрина. И установить любой токен на свой аватар, где мы можем выбрать нами выпущенный токен в предыдущих шагах.