|
--- |
|
base_model: stabilityai/stable-diffusion-2 |
|
library_name: diffusers |
|
license: openrail++ |
|
tags: |
|
- text-to-image |
|
- text-to-image |
|
- diffusers-training |
|
- diffusers |
|
- stable-diffusion-2 |
|
- stable-diffusion-2-diffusers |
|
- science |
|
- materiomics |
|
- bio-inspired |
|
- materials science |
|
- text-to-3D |
|
- text-to-STL |
|
- text-t-mesh |
|
- additive manufacturing |
|
- 3D |
|
- 3D printing |
|
instance_prompt: <leaf microstructure> |
|
widget: [] |
|
--- |
|
|
|
# Stable Diffusion 2.x Fine-tuned with Leaf Images: Text-to-image and text-to-3D |
|
|
|
DreamBooth is an advanced technique designed for fine-tuning text-to-image diffusion models to generate personalized images of specific subjects. By leveraging a few reference images (around 5 or so), DreamBooth integrates unique visual features of the subject into the model's output domain. |
|
|
|
This is achieved by binding a unique identifier "\<..IDENTIFIER..\>", such as \<leaf microstructure\> in this work, to the subject. An optional class-specific prior preservation loss can be used to maintain high fidelity and contextual diversity. The result is a model capable of synthesizing novel, photorealistic images of the subject in various scenes, poses, and lighting conditions, guided by text prompts. In this project, DreamBooth has been applied to render images with specific biological patterns, making it ideal for applications in materials science and engineering where accurate representation of biological material microstructures is crucial. |
|
|
|
For example, an original prompt might be: "a vase with intricate patterns, high quality." With the fine-tuned model, using the unique identifier, the prompt becomes: "a vase that resembles a \<leaf microstructure\>, high quality." This allows the model to generate images that specifically incorporate the desired biological pattern. |
|
|
|
## Model description |
|
|
|
These are fine-tuned weights for the ```stabilityai/stable-diffusion-2``` model. This is a full fine-tune of the model using DreamBooth. |
|
|
|
|
|
## Trigger keywords |
|
|
|
The following image were used during fine-tuning using the keyword \<leaf microstructure\>: |
|
|
|
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/#fileId=https://huggingface.co/lamm-mit/SD2x-leaf-inspired/blob/main/SD2x_leaf_inspired_inference.ipynb) |
|
|
|
Please use \<leaf microstructure\> to trigger the image generation. |
|
|
|
## How to use |
|
|
|
Defining some helper functions: |
|
|
|
```python |
|
from diffusers import DiffusionPipeline |
|
import torch |
|
import os |
|
from datetime import datetime |
|
from PIL import Image |
|
|
|
def generate_filename(base_name, extension=".png"): |
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
|
return f"{base_name}_{timestamp}{extension}" |
|
|
|
def save_image(image, directory, base_name="image_grid"): |
|
|
|
filename = generate_filename(base_name) |
|
file_path = os.path.join(directory, filename) |
|
image.save(file_path) |
|
print(f"Image saved as {file_path}") |
|
|
|
def image_grid(imgs, rows, cols, save=True, save_dir='generated_images', base_name="image_grid", |
|
save_individual_files=False): |
|
|
|
if not os.path.exists(save_dir): |
|
os.makedirs(save_dir) |
|
|
|
assert len(imgs) == rows * cols |
|
|
|
w, h = imgs[0].size |
|
grid = Image.new('RGB', size=(cols * w, rows * h)) |
|
grid_w, grid_h = grid.size |
|
|
|
for i, img in enumerate(imgs): |
|
grid.paste(img, box=(i % cols * w, i // cols * h)) |
|
if save_individual_files: |
|
save_image(img, save_dir, base_name=base_name+f'_{i}-of-{len(imgs)}_') |
|
|
|
if save and save_dir: |
|
save_image(grid, save_dir, base_name) |
|
|
|
return grid |
|
``` |
|
|
|
### Text-to-image |
|
|
|
Model loading: |
|
|
|
```python |
|
|
|
import torch |
|
from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler |
|
|
|
repo_id='lamm-mit/SD2x-leaf-inspired' |
|
|
|
pipe = StableDiffusionPipeline.from_pretrained(repo_id, |
|
scheduler = DPMSolverMultistepScheduler.from_pretrained(repo_id, subfolder="scheduler"), |
|
torch_dtype=torch.float16, |
|
).to("cuda") |
|
|
|
``` |
|
|
|
Image generation: |
|
|
|
```python |
|
prompt = "a vase that resembles a <leaf microstructure>, high quality" |
|
num_samples = 4 |
|
num_rows = 4 |
|
|
|
all_images = [] |
|
for _ in range(num_rows): |
|
images = pipe(prompt, num_images_per_prompt=num_samples, num_inference_steps=50, guidance_scale=15).images |
|
all_images.extend(images) |
|
|
|
grid = image_grid(all_images, num_rows, num_samples) |
|
grid |
|
``` |
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/SI5aYv2dygJn0Y12LIqqe.png) |
|
|
|
### Image-to-Image |
|
|
|
The model can be used also for image-to-image tasks. For instance, we can first generate a draft image and then further modify it. |
|
|
|
Create draft image: |
|
``` |
|
prompt = "a vase that resembles a <leaf microstructure>, high quality" |
|
num_samples = 4 |
|
num_rows = 1 |
|
|
|
all_images = [] |
|
for _ in range(num_rows): |
|
images = pipe(prompt, num_images_per_prompt=num_samples, num_inference_steps=50, guidance_scale=15).images |
|
all_images.extend(images) |
|
|
|
grid = image_grid(all_images, num_rows, num_samples, save_individual_files=True) |
|
grid |
|
``` |
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/MkOXQIpdhl_zWM3QySYMY.png) |
|
|
|
Now we use one of the images (second from left) and modify it using the image-to-image pipeline. You can get the image as follows (if you run the generate code yourself, the generated images will be in the subdirectory ```generated_images```): |
|
|
|
``` |
|
wget https://huggingface.co/lamm-mit/SD2x-leaf-inspired/resolve/main/image_grid_1-of-4__20240722_144702.png |
|
``` |
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/l4WCC3PoZ6OpiSN-E66i3.png) |
|
|
|
Now, generate: |
|
``` |
|
fname='image_grid_1-of-4__20240722_144702.png' |
|
init_image = Image.open(fname).convert("RGB") |
|
init_image = init_image.resize((768, 768)) |
|
|
|
prompt = "A vase made out of a spongy material, high quality photograph, full frame." |
|
num_samples = 4 |
|
num_rows = 1 |
|
|
|
all_images = [] |
|
for _ in range(num_rows): |
|
images = img2imgpipe(prompt, image=init_image, |
|
num_images_per_prompt=num_samples, strength=0.8, num_inference_steps=75, guidance_scale=25).images |
|
all_images.extend(images) |
|
|
|
grid = image_grid(images, num_rows, num_samples, save_individual_files=True) |
|
grid |
|
``` |
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/0ROO1Ob2Z-GYPepYyyAGg.png) |
|
|
|
|
|
We can further edit the image by introducing another feature. We start from this image |
|
``` |
|
wget https://huggingface.co/lamm-mit/SD2x-leaf-inspired/resolve/main/image_grid_2-of-4__20240722_150458.png |
|
``` |
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/c-1b4J-as6b2p9ZQSSLjK.png) |
|
``` |
|
fname='image_grid_2-of-4__20240722_150458.png' |
|
init_image = Image.open(fname).convert("RGB") |
|
init_image = init_image.resize((768, 768)) |
|
|
|
prompt = "A nicely connected white spider web." |
|
num_samples = 4 |
|
num_rows = 1 |
|
|
|
all_images = [] |
|
for _ in range(num_rows): |
|
images = img2imgpipe(prompt, image=init_image, |
|
num_images_per_prompt=num_samples, strength=0.8, num_inference_steps=10, guidance_scale=20).images |
|
all_images.extend(images) |
|
|
|
grid = image_grid(images, num_rows, num_samples, save_individual_files=True) |
|
grid |
|
``` |
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/izv21tOqJntVAwes0TEzu.png) |
|
|
|
A detailed view of one of them: |
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/Ik7RkGzrx0N8gkNfkei3j.png) |
|
|
|
## Text-to-3D |
|
|
|
Download this notebook: [Convert-text-to-3D.ipynb](https://huggingface.co/lamm-mit/SD2x-leaf-inspired/resolve/main/Convert-text-to-3D.ipynb) |
|
|
|
This notebook includes the code to convert text to 3D, using an algorithm that involves a fine-tuned Stable Diffusion model and InstantMesh. |
|
|
|
``` |
|
repo_id_load= 'lamm-mit/SD2x-leaf-inspired' |
|
input_image=text_to_image_SD2x (base_model=repo_id_load, n_steps=75, guidance_scale=15, |
|
prompt = "Small chair that resembles a <leaf microstructure>.", negative_prompt="" ) |
|
display (input_image) |
|
processed_image, mv_images, mv_show_images= generate_multiviews (input_image, seed=None) |
|
display (mv_show_images) |
|
output_video, output_model_obj = make_multi_views_into_3D (mv_images, target_dir='output') |
|
Video(output_video, embed=True) |
|
``` |
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/cXI8HutHviEhRd7oerPhe.png) |
|
|
|
![image/gif](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/sWB2ecbrnMwL7Zx9kzxnK.gif) |
|
|
|
### 3D printed samples |
|
|
|
In this example, we generated a 3D model and created a physical sample using additive manufacturing. |
|
|
|
``` |
|
repo_id_load= 'lamm-mit/SD2x-leaf-inspired' |
|
input_image=text_to_image_SD2x (base_model=repo_id_load, n_steps=50, guidance_scale=15, |
|
prompt = "a conch shell on black background that resembles a <leaf microstructure>, high quality", negative_prompt="" ) |
|
display (input_image) |
|
processed_image, mv_images, mv_show_images= generate_multiviews (input_image, seed=None) |
|
display (mv_show_images) |
|
output_video, output_model_obj = make_multi_views_into_3D (mv_images, target_dir='output') |
|
Video(output_video, embed=True) |
|
``` |
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/pNSU8_e9ntmIFElmn84Y-.png) |
|
|
|
|
|
![image/gif](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/im5ECrFTYVGkgJ8uYlL_3.gif) |
|
|
|
3D printing: Slicing using Cura and resulting physical sample with gyroid infill: |
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/jKEZVX8s76ZeyOvZAp0In.png) |
|
|
|
## Fine-tuning script |
|
|
|
Download this script: [SD2x DreamBooth-Fine-Tune.ipynb](https://huggingface.co/lamm-mit/SD2x-leaf-inspired/resolve/main/SD2x_DreamBooth_Fine-Tune.ipynb) |
|
|
|
You need to create a local folder ```leaf_concept_dir``` and add the leaf images (provided in this repository, see subfolder), like so: |
|
|
|
```python |
|
save_path='leaf_concept_dir' |
|
urls = [ |
|
"https://www.dropbox.com/scl/fi/4s09djm4nqxmq6vhvv9si/13_.jpg?rlkey=3m2f90pjofljmlqg5uc722i6y&dl=1", |
|
"https://www.dropbox.com/scl/fi/w4jsrf0qmrcro37nxutbx/25_.jpg?rlkey=e52gnoqaar33kwrd01h1mwcnk&dl=1", |
|
"https://www.dropbox.com/scl/fi/x0xgavduor4cbxz0sdcd2/33_.jpg?rlkey=5htaicapahhn66wnsr23v1nxz&dl=1", |
|
"https://www.dropbox.com/scl/fi/2grt40acypah9h9ok607q/72_.jpg?rlkey=bl6vfv0rcas2ygsz6o3behlst&dl=1", |
|
"https://www.dropbox.com/scl/fi/ecaf9agzdj2cawspmyt5i/117_.jpg?rlkey=oqxyk9i1wtu1wtkqadd6ylyjj&dl=1", |
|
"https://www.dropbox.com/scl/fi/gw3p73r99fleozr6ckfa3/126_.jpg?rlkey=6n7kqaklczshht1ntyqunh2lt&dl=1", |
|
## You can add additional images here |
|
] |
|
images = list(filter(None,[download_image(url) for url in urls])) |
|
|
|
if not os.path.exists(save_path): |
|
os.mkdir(save_path) |
|
|
|
[image.save(f"{save_path}/{i}.jpeg") for i, image in enumerate(images)] |
|
image_grid(images, 1, len(images)) |
|
``` |
|
|
|
The training script is included in the Jupyter notebook. |
|
|
|
## More examples |
|
|
|
```python |
|
prompt = "a conch shell on black background that resembles a <leaf microstructure>, high quality" |
|
num_samples = 4 |
|
num_rows = 4 |
|
all_images = [] |
|
for _ in range(num_rows): |
|
images = pipe(prompt, num_images_per_prompt=num_samples, num_inference_steps=50, guidance_scale=15).images |
|
all_images.extend(images) |
|
grid = image_grid(all_images, num_rows, num_samples) |
|
grid |
|
``` |
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/eE1xBqyVA4sP4gx6tAEGc.png) |
|
|
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/Ga808aW5H27f0hPq_RNme.png) |
|
|
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/r0dUyA-Gh_biy5d-4lTl0.png) |
|
|
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/iEjozBWOQQwxNVuKWZ7TT.png) |
|
|
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/ESvd6cCkyJZ52Cu3iYfoP.png) |
|
|
|
|
|
![image/png](https://cdn-uploads.huggingface.co/production/uploads/623ce1c6b66fedf374859fe7/2FExqoj8TSjJoIiw4wCm6.png) |
|
|