Commit
•
96960b9
1
Parent(s):
dd56770
Update requirements.txt to include boto3
Browse filesUpdate import statement in sdxl_text_to_image.py
Former-commit-id: 7e6049b1f7eb6419a21c1bba333aa4f4dce55d82 [formerly 48e4c31ea496c0f9766f04df160ca8d3f09e980e]
Former-commit-id: 4f4fff33d561560f14bb0b3089f8ca9f12945504
- .github/workflows/build-docker.yml +10 -9
- product_diffusion_api/__pycache__/endpoints.cpython-311.pyc +0 -0
- product_diffusion_api/routers/__pycache__/painting.cpython-310.pyc +0 -0
- product_diffusion_api/routers/__pycache__/sdxl_text_to_image.cpython-310.pyc +0 -0
- product_diffusion_api/routers/__pycache__/sdxl_text_to_image.cpython-311.pyc +0 -0
- product_diffusion_api/routers/painting.py +88 -79
- product_diffusion_api/routers/sdxl_text_to_image.py +1 -1
- requirements.txt +2 -1
- scripts/__pycache__/config.cpython-311.pyc +0 -0
- scripts/__pycache__/s3_manager.cpython-311.pyc +0 -0
- scripts/__pycache__/utils.cpython-311.pyc +0 -0
- scripts/inpainting_pipeline.py +2 -1
.github/workflows/build-docker.yml
CHANGED
@@ -1,8 +1,9 @@
|
|
1 |
-
name:
|
2 |
|
3 |
on:
|
4 |
-
|
5 |
-
|
|
|
6 |
|
7 |
jobs:
|
8 |
build-and-push:
|
@@ -10,23 +11,23 @@ jobs:
|
|
10 |
|
11 |
steps:
|
12 |
- name: Checkout code
|
13 |
-
uses: actions/checkout@
|
14 |
|
15 |
-
- name: Set up Docker
|
16 |
-
uses: docker/setup-buildx-action@
|
17 |
|
18 |
- name: Login to Docker Hub
|
19 |
-
uses: docker/login-action@
|
20 |
with:
|
21 |
username: ${{ secrets.DOCKER_USERNAME }}
|
22 |
password: ${{ secrets.DOCKER_PASSWORD }}
|
23 |
|
24 |
- name: Build and push Docker image
|
25 |
-
uses: docker/build-push-action@
|
26 |
with:
|
27 |
context: .
|
28 |
push: true
|
29 |
-
tags: ${{
|
30 |
|
31 |
- name: Logout from Docker Hub
|
32 |
run: docker logout
|
|
|
1 |
+
name: Push to Docker Image
|
2 |
|
3 |
on:
|
4 |
+
push:
|
5 |
+
branches:
|
6 |
+
- main
|
7 |
|
8 |
jobs:
|
9 |
build-and-push:
|
|
|
11 |
|
12 |
steps:
|
13 |
- name: Checkout code
|
14 |
+
uses: actions/checkout@v4
|
15 |
|
16 |
+
- name: Set up Docker Builds
|
17 |
+
uses: docker/setup-buildx-action@v3.3.0
|
18 |
|
19 |
- name: Login to Docker Hub
|
20 |
+
uses: docker/login-action@v3.2.0
|
21 |
with:
|
22 |
username: ${{ secrets.DOCKER_USERNAME }}
|
23 |
password: ${{ secrets.DOCKER_PASSWORD }}
|
24 |
|
25 |
- name: Build and push Docker image
|
26 |
+
uses: docker/build-push-action@v5.3.0
|
27 |
with:
|
28 |
context: .
|
29 |
push: true
|
30 |
+
tags: ${{secrets.DOCKER_USERNAME}}/my-image:pr-${{github.run_id }}
|
31 |
|
32 |
- name: Logout from Docker Hub
|
33 |
run: docker logout
|
product_diffusion_api/__pycache__/endpoints.cpython-311.pyc
ADDED
Binary file (2.2 kB). View file
|
|
product_diffusion_api/routers/__pycache__/painting.cpython-310.pyc
DELETED
Binary file (243 Bytes)
|
|
product_diffusion_api/routers/__pycache__/sdxl_text_to_image.cpython-310.pyc
DELETED
Binary file (7.17 kB)
|
|
product_diffusion_api/routers/__pycache__/sdxl_text_to_image.cpython-311.pyc
ADDED
Binary file (10.7 kB). View file
|
|
product_diffusion_api/routers/painting.py
CHANGED
@@ -1,37 +1,54 @@
|
|
1 |
-
|
2 |
-
|
|
|
3 |
from pydantic import BaseModel
|
4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
from PIL import Image
|
6 |
-
import
|
7 |
-
from
|
8 |
-
from diffusers.utils import load_image
|
9 |
-
from utils import (accelerator, ImageAugmentation, clear_memory)
|
10 |
import hydra
|
11 |
from omegaconf import DictConfig
|
12 |
-
import lightning.pytorch as pl
|
13 |
-
import io
|
14 |
|
15 |
-
|
|
|
16 |
router = APIRouter()
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
|
28 |
-
class InpaintingBatchRequest(BaseModel):
|
29 |
-
batch_input: List[InpaintingRequest]
|
30 |
|
|
|
|
|
|
|
31 |
|
|
|
|
|
|
|
32 |
|
|
|
|
|
33 |
|
34 |
-
|
35 |
image_id = str(uuid.uuid4())
|
36 |
s3_uploader = S3ManagerService()
|
37 |
image_bytes = io.BytesIO()
|
@@ -40,64 +57,56 @@ def pil_to_s3_json(image: Image.Image, file_name: str):
|
|
40 |
|
41 |
unique_file_name = s3_uploader.generate_unique_file_name(file_name)
|
42 |
s3_uploader.upload_file(image_bytes, unique_file_name)
|
43 |
-
signed_url = s3_uploader.generate_signed_url(
|
|
|
|
|
44 |
return {"image_id": image_id, "url": signed_url}
|
45 |
|
46 |
-
class AutoPaintingPipeline:
|
47 |
-
def __init__(self, model_name: str, image: Image.Image, mask_image: Image.Image, target_width: int, target_height: int):
|
48 |
-
self.model_name = model_name
|
49 |
-
self.device = accelerator()
|
50 |
-
self.pipeline = AutoPipelineForInpainting.from_pretrained(self.model_name, torch_dtype=torch.float16)
|
51 |
-
self.image = load_image(image)
|
52 |
-
self.mask_image = load_image(mask_image)
|
53 |
-
self.target_width = target_width
|
54 |
-
self.target_height = target_height
|
55 |
-
self.pipeline.to(self.device)
|
56 |
-
|
57 |
-
def run_inference(self, prompt: str, negative_prompt: Optional[str], num_inference_steps: int, strength: float, guidance_scale: float):
|
58 |
-
clear_memory()
|
59 |
-
image = load_image(self.image)
|
60 |
-
mask_image = load_image(self.mask_image)
|
61 |
-
output = self.pipeline(
|
62 |
-
prompt=prompt,
|
63 |
-
negative_prompt=negative_prompt,
|
64 |
-
image=image,
|
65 |
-
mask_image=mask_image,
|
66 |
-
num_inference_steps=num_inference_steps,
|
67 |
-
strength=strength,
|
68 |
-
guidance_scale=guidance_scale,
|
69 |
-
height=self.target_height,
|
70 |
-
width=self.target_width
|
71 |
-
).images[0]
|
72 |
-
return output
|
73 |
-
|
74 |
-
@app.post("/inpaint/")
|
75 |
-
async def inpaint(
|
76 |
-
file: UploadFile = File(...),
|
77 |
-
request: InpaintingRequest
|
78 |
-
):
|
79 |
-
image = Image.open(file.file)
|
80 |
-
augmenter = ImageAugmentation(target_width=request.target_width, target_height=request.target_height) # Use fixed size or set dynamically
|
81 |
-
extended_image = augmenter.extend_image(image)
|
82 |
-
mask_image = augmenter.generate_mask_from_bbox(extended_image, 'segmentation_model', 'detection_model')
|
83 |
-
mask_image = augmenter.invert_mask(mask_image)
|
84 |
-
|
85 |
-
pipeline = AutoPaintingPipeline(
|
86 |
-
model_name="model_name",
|
87 |
-
image=extended_image,
|
88 |
-
mask_image=mask_image,
|
89 |
-
target_width=request.target_width,
|
90 |
-
target_height=request.target_height
|
91 |
-
)
|
92 |
-
output_image = pipeline.run_inference(
|
93 |
-
prompt=request.prompt,
|
94 |
-
negative_prompt=request.negative_prompt,
|
95 |
-
num_inference_steps=request.num_inference_steps,
|
96 |
-
strength=request.strength,
|
97 |
-
guidance_scale=request.guidance_scale,
|
98 |
-
|
99 |
-
)
|
100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
|
102 |
-
|
103 |
-
|
|
|
|
1 |
+
import sys
|
2 |
+
sys.path.append("../scripts")
|
3 |
+
from fastapi import APIRouter,File,UploadFile
|
4 |
from pydantic import BaseModel
|
5 |
+
import base64
|
6 |
+
from io import BytesIO
|
7 |
+
from typing import List
|
8 |
+
import uuid
|
9 |
+
from inpainting_pipeline import AutoPaintingPipeline
|
10 |
+
from functools import lru_cache
|
11 |
+
from s3_manager import S3ManagerService
|
12 |
from PIL import Image
|
13 |
+
import io
|
14 |
+
from scripts.utils import ImageAugmentation
|
|
|
|
|
15 |
import hydra
|
16 |
from omegaconf import DictConfig
|
|
|
|
|
17 |
|
18 |
+
|
19 |
+
|
20 |
router = APIRouter()
|
21 |
|
22 |
+
def pil_to_b64_json(image):
|
23 |
+
"""
|
24 |
+
Converts a PIL image to a base64-encoded JSON object.
|
25 |
+
|
26 |
+
Args:
|
27 |
+
image (PIL.Image.Image): The PIL image object to be converted.
|
28 |
+
|
29 |
+
Returns:
|
30 |
+
dict: A dictionary containing the image ID and the base64-encoded image.
|
31 |
+
|
32 |
+
"""
|
33 |
+
image_id = str(uuid.uuid4())
|
34 |
+
buffered = BytesIO()
|
35 |
+
image.save(buffered, format="PNG")
|
36 |
+
b64_image = base64.b64encode(buffered.getvalue()).decode("utf-8")
|
37 |
+
return {"image_id": image_id, "b64_image": b64_image}
|
38 |
|
|
|
|
|
39 |
|
40 |
+
def pil_to_s3_json(image: Image.Image, file_name) -> str:
|
41 |
+
"""
|
42 |
+
Uploads a PIL image to Amazon S3 and returns a JSON object containing the image ID and the signed URL.
|
43 |
|
44 |
+
Args:
|
45 |
+
image (PIL.Image.Image): The PIL image to be uploaded.
|
46 |
+
file_name (str): The name of the file.
|
47 |
|
48 |
+
Returns:
|
49 |
+
dict: A JSON object containing the image ID and the signed URL.
|
50 |
|
51 |
+
"""
|
52 |
image_id = str(uuid.uuid4())
|
53 |
s3_uploader = S3ManagerService()
|
54 |
image_bytes = io.BytesIO()
|
|
|
57 |
|
58 |
unique_file_name = s3_uploader.generate_unique_file_name(file_name)
|
59 |
s3_uploader.upload_file(image_bytes, unique_file_name)
|
60 |
+
signed_url = s3_uploader.generate_signed_url(
|
61 |
+
unique_file_name, exp=43200
|
62 |
+
) # 12 hours
|
63 |
return {"image_id": image_id, "url": signed_url}
|
64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
+
|
67 |
+
class InpaintingRequest(BaseModel):
|
68 |
+
image: File(..., description="The image to be inpainted")
|
69 |
+
prompt: str
|
70 |
+
negative_prompt: str
|
71 |
+
num_inference_steps: int
|
72 |
+
strength: float
|
73 |
+
guidance_scale: float
|
74 |
+
|
75 |
+
|
76 |
+
|
77 |
+
|
78 |
+
|
79 |
+
|
80 |
+
def augment_image(image, target_width, target_height, roi_scale,segmentation_model_name,detection_model_name):
|
81 |
+
"""
|
82 |
+
Augments an image with a given prompt, model, and other parameters.
|
83 |
+
|
84 |
+
Parameters:
|
85 |
+
- image (str): The path to the image file.
|
86 |
+
- target_width (int): The desired width of the augmented image.
|
87 |
+
- target_height (int): The desired height of the augmented image.
|
88 |
+
- roi_scale (float): The scale factor for the region of interest.
|
89 |
+
|
90 |
+
Returns:
|
91 |
+
- augmented_image (PIL.Image.Image): The augmented image.
|
92 |
+
- inverted_mask (PIL.Image.Image): The inverted mask generated from the augmented image.
|
93 |
+
"""
|
94 |
+
image = Image.open(image)
|
95 |
+
image_augmentation = ImageAugmentation(target_width, target_height, roi_scale)
|
96 |
+
image = image_augmentation.extend_image(image)
|
97 |
+
mask = image_augmentation.generate_mask_from_bbox(image,segmentation_model_name,detection_model_name)
|
98 |
+
inverted_mask = image_augmentation.invert_mask(mask)
|
99 |
+
return image, inverted_mask
|
100 |
+
|
101 |
+
|
102 |
+
@hydra.main(version_base="1.3",config_path="conf",config_name="inpainting")
|
103 |
+
def run_inference(cfg,image,prompt,negative_prompt,num_inference_steps,strength,guidance_scale):
|
104 |
+
image, mask_image = augment_image(image, cfg.width, cfg.height, cfg.roi_scale,cfg.segmentation_model_name,cfg.detection_model_name)
|
105 |
+
pipeline = AutoPaintingPipeline(model_name=cfg.model_name, image = image, mask_image=mask_image, target_height=cfg.height, target_width=cfg.width)
|
106 |
+
output = pipeline.run_inference(prompt=prompt, negative_prompt=negative_prompt, num_inference_steps=num_inference_steps, strength=strength, guidance_scale=guidance_scale)
|
107 |
+
pil_to_s3_json(output,file_name="output.jpg")
|
108 |
+
|
109 |
|
110 |
+
@router.post("/inpainting")
|
111 |
+
def inpainting_inference(request: InpaintingRequest):
|
112 |
+
return run_inference(request)
|
product_diffusion_api/routers/sdxl_text_to_image.py
CHANGED
@@ -13,7 +13,7 @@ from functools import lru_cache
|
|
13 |
from s3_manager import S3ManagerService
|
14 |
from PIL import Image
|
15 |
import io
|
16 |
-
from
|
17 |
|
18 |
device = accelerator()
|
19 |
torch._inductor.config.conv_1x1_as_mm = True
|
|
|
13 |
from s3_manager import S3ManagerService
|
14 |
from PIL import Image
|
15 |
import io
|
16 |
+
from utils import accelerator
|
17 |
|
18 |
device = accelerator()
|
19 |
torch._inductor.config.conv_1x1_as_mm = True
|
requirements.txt
CHANGED
@@ -21,4 +21,5 @@ datasets
|
|
21 |
peft
|
22 |
async-batcher
|
23 |
ultralytics
|
24 |
-
opencv-python-headless
|
|
|
|
21 |
peft
|
22 |
async-batcher
|
23 |
ultralytics
|
24 |
+
opencv-python-headless
|
25 |
+
boto3
|
scripts/__pycache__/config.cpython-311.pyc
ADDED
Binary file (3.37 kB). View file
|
|
scripts/__pycache__/s3_manager.cpython-311.pyc
ADDED
Binary file (4 kB). View file
|
|
scripts/__pycache__/utils.cpython-311.pyc
ADDED
Binary file (6.88 kB). View file
|
|
scripts/inpainting_pipeline.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
|
2 |
from diffusers import AutoPipelineForInpainting
|
3 |
from diffusers.utils import load_image
|
4 |
from utils import (accelerator, ImageAugmentation, clear_memory)
|
@@ -29,6 +29,7 @@ class AutoPaintingPipeline:
|
|
29 |
self.target_width = target_width
|
30 |
self.target_height = target_height
|
31 |
self.pipeline.to(self.device)
|
|
|
32 |
|
33 |
|
34 |
|
|
|
1 |
+
import torch
|
2 |
from diffusers import AutoPipelineForInpainting
|
3 |
from diffusers.utils import load_image
|
4 |
from utils import (accelerator, ImageAugmentation, clear_memory)
|
|
|
29 |
self.target_width = target_width
|
30 |
self.target_height = target_height
|
31 |
self.pipeline.to(self.device)
|
32 |
+
self.pipeline.unet = torch.compile(self.pipeline.unet,mode='max-autotune')
|
33 |
|
34 |
|
35 |
|