yaseengoldfinchpc commited on
Commit
e3d5df0
·
1 Parent(s): bdd54be

Git Push Some update

Browse files
Files changed (3) hide show
  1. Dockerfile +7 -0
  2. app.py +136 -128
  3. example_client.py +1 -1
Dockerfile CHANGED
@@ -10,6 +10,9 @@ RUN apt-get update && apt-get install -y \
10
  python3-pip \
11
  && rm -rf /var/lib/apt/lists/*
12
 
 
 
 
13
  # Copy requirements first for better caching
14
  COPY --chown=user:user requirements.txt .
15
  RUN pip3 install --no-cache-dir -r requirements.txt
@@ -20,6 +23,10 @@ COPY --chown=user:user . .
20
  # Switch to non-root user
21
  USER user
22
 
 
 
 
 
23
  # Expose port
24
  EXPOSE 7860
25
 
 
10
  python3-pip \
11
  && rm -rf /var/lib/apt/lists/*
12
 
13
+ # Install accelerate for better GPU performance
14
+ RUN pip3 install --no-cache-dir accelerate
15
+
16
  # Copy requirements first for better caching
17
  COPY --chown=user:user requirements.txt .
18
  RUN pip3 install --no-cache-dir -r requirements.txt
 
23
  # Switch to non-root user
24
  USER user
25
 
26
+ # Set environment variables for GPU
27
+ ENV NVIDIA_VISIBLE_DEVICES all
28
+ ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
29
+
30
  # Expose port
31
  EXPOSE 7860
32
 
app.py CHANGED
@@ -1,129 +1,137 @@
1
- from fastapi import FastAPI, File, UploadFile, HTTPException
2
- from fastapi.middleware.cors import CORSMiddleware
3
- import torch
4
- from PIL import Image
5
- import io
6
- import base64
7
- from diffusers import StableDiffusionInpaintPipeline
8
- import gc
9
- from fastapi.responses import JSONResponse
10
- import logging
11
-
12
- app = FastAPI()
13
-
14
- # Add CORS middleware
15
- app.add_middleware(
16
- CORSMiddleware,
17
- allow_origins=["*"],
18
- allow_credentials=True,
19
- allow_methods=["*"],
20
- allow_headers=["*"],
21
- )
22
-
23
- # Global variable for the model
24
- pipe = None
25
-
26
- def load_model():
27
- global pipe
28
- if pipe is None:
29
- model_id = "Uminosachi/realisticVisionV51_v51VAE-inpainting"
30
- try:
31
- # Try CUDA first
32
- if torch.cuda.is_available():
33
- device = "cuda"
34
- dtype = torch.float16
35
- else:
36
- # Fallback to CPU
37
- device = "cpu"
38
- dtype = torch.float32
39
-
40
- pipe = StableDiffusionInpaintPipeline.from_pretrained(
41
- model_id,
42
- torch_dtype=dtype,
43
- safety_checker=None
44
- ).to(device)
45
-
46
- if device == "cuda":
47
- pipe.enable_attention_slicing(slice_size="max")
48
- pipe.enable_sequential_cpu_offload()
49
-
50
- print(f"Model loaded on {device}")
51
-
52
- except Exception as e:
53
- print(f"Error loading model: {str(e)}")
54
- raise
55
- return pipe
56
-
57
- @app.on_event("startup")
58
- async def startup_event():
59
- try:
60
- load_model()
61
- except Exception as e:
62
- print(f"Startup error: {str(e)}")
63
-
64
- def image_to_base64(image: Image.Image) -> str:
65
- buffered = io.BytesIO()
66
- image.save(buffered, format="PNG")
67
- return base64.b64encode(buffered.getvalue()).decode()
68
-
69
- @app.post("/inpaint")
70
- async def inpaint(
71
- image: UploadFile = File(...),
72
- mask: UploadFile = File(...),
73
- prompt: str = "add some flowers and a fountain",
74
- negative_prompt: str = "blurry, low quality, distorted"
75
- ):
76
- try:
77
- # Add file size check (10MB limit)
78
- max_size = 10 * 1024 * 1024 # 10MB
79
- if len(await image.read()) > max_size or len(await mask.read()) > max_size:
80
- return JSONResponse(
81
- status_code=400,
82
- content={"error": "File size too large. Maximum size is 10MB"}
83
- )
84
-
85
- # Reset file positions
86
- await image.seek(0)
87
- await mask.seek(0)
88
-
89
- # Read and process input image
90
- image_data = await image.read()
91
- mask_data = await mask.read()
92
-
93
- original_image = Image.open(io.BytesIO(image_data))
94
- mask_image = Image.open(io.BytesIO(mask_data))
95
-
96
- # Resize to multiple of 8
97
- width, height = (dim - dim % 8 for dim in original_image.size)
98
- original_image = original_image.resize((width, height))
99
- mask_image = mask_image.resize((width, height))
100
- mask_image = mask_image.convert("L")
101
-
102
- # Reduce steps for CPU
103
- num_steps = 10 if not torch.cuda.is_available() else 20
104
-
105
- with torch.cuda.amp.autocast():
106
- output_image = pipe(
107
- prompt=prompt,
108
- negative_prompt=negative_prompt,
109
- image=original_image,
110
- mask_image=mask_image,
111
- num_inference_steps=num_steps, # Reduced steps
112
- guidance_scale=7.5,
113
- ).images[0]
114
-
115
- # Convert output image to base64
116
- output_base64 = image_to_base64(output_image)
117
-
118
- # Clean up
119
- torch.cuda.empty_cache()
120
- gc.collect()
121
-
122
- return {"status": "success", "image": output_base64}
123
-
124
- except Exception as e:
125
- raise HTTPException(status_code=500, detail=str(e))
126
-
127
- @app.get("/health")
128
- async def health_check():
 
 
 
 
 
 
 
 
129
  return {"status": "healthy", "cuda_available": torch.cuda.is_available()}
 
1
+ from fastapi import FastAPI, File, UploadFile, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ import torch
4
+ from PIL import Image
5
+ import io
6
+ import base64
7
+ from diffusers import StableDiffusionInpaintPipeline
8
+ import gc
9
+ from fastapi.responses import JSONResponse
10
+ import logging
11
+
12
+ app = FastAPI()
13
+
14
+ # Add CORS middleware
15
+ app.add_middleware(
16
+ CORSMiddleware,
17
+ allow_origins=["*"],
18
+ allow_credentials=True,
19
+ allow_methods=["*"],
20
+ allow_headers=["*"],
21
+ )
22
+
23
+ # Global variable for the model
24
+ pipe = None
25
+
26
+ # Add max size limit
27
+ MAX_SIZE = 512
28
+
29
+ def load_model():
30
+ global pipe
31
+ if pipe is None:
32
+ model_id = "Uminosachi/realisticVisionV51_v51VAE-inpainting"
33
+ try:
34
+ device = "cuda" if torch.cuda.is_available() else "cpu"
35
+ pipe = StableDiffusionInpaintPipeline.from_pretrained(
36
+ model_id,
37
+ torch_dtype=torch.float16,
38
+ safety_checker=None
39
+ ).to(device)
40
+
41
+ if device == "cuda":
42
+ pipe.enable_attention_slicing()
43
+
44
+ print(f"Model loaded on {device} with optimizations")
45
+
46
+ except Exception as e:
47
+ print(f"Error loading model: {str(e)}")
48
+ raise
49
+ return pipe
50
+
51
+ @app.on_event("startup")
52
+ async def startup_event():
53
+ try:
54
+ load_model()
55
+ except Exception as e:
56
+ print(f"Startup error: {str(e)}")
57
+
58
+ def image_to_base64(image: Image.Image) -> str:
59
+ buffered = io.BytesIO()
60
+ image.save(buffered, format="PNG")
61
+ return base64.b64encode(buffered.getvalue()).decode()
62
+
63
+ def resize_for_condition_image(input_image: Image.Image, resolution: int):
64
+ input_width, input_height = input_image.size
65
+ aspect_ratio = input_height / input_width
66
+
67
+ if input_height > input_width:
68
+ # vertical image
69
+ width = resolution
70
+ height = int(resolution * aspect_ratio)
71
+ else:
72
+ # horizontal image
73
+ height = resolution
74
+ width = int(resolution / aspect_ratio)
75
+
76
+ return input_image.resize((width, height))
77
+
78
+ @app.post("/inpaint")
79
+ async def inpaint(
80
+ image: UploadFile = File(...),
81
+ mask: UploadFile = File(...),
82
+ prompt: str = "add some flowers and a fountain",
83
+ negative_prompt: str = "blurry, low quality, distorted"
84
+ ):
85
+ try:
86
+ # Add file size check (10MB limit)
87
+ max_size = 10 * 1024 * 1024 # 10MB
88
+ if len(await image.read()) > max_size or len(await mask.read()) > max_size:
89
+ return JSONResponse(
90
+ status_code=400,
91
+ content={"error": "File size too large. Maximum size is 10MB"}
92
+ )
93
+
94
+ # Reset file positions
95
+ await image.seek(0)
96
+ await mask.seek(0)
97
+
98
+ # Read and process input image
99
+ image_data = await image.read()
100
+ mask_data = await mask.read()
101
+
102
+ original_image = Image.open(io.BytesIO(image_data))
103
+ mask_image = Image.open(io.BytesIO(mask_data))
104
+
105
+ # Resize images to smaller size
106
+ original_image = resize_for_condition_image(original_image, MAX_SIZE)
107
+ mask_image = resize_for_condition_image(mask_image, MAX_SIZE)
108
+ mask_image = mask_image.convert("L")
109
+
110
+ # Reduce steps even more for CPU
111
+ num_steps = 5 if not torch.cuda.is_available() else 20
112
+
113
+ with torch.cuda.amp.autocast():
114
+ output_image = pipe(
115
+ prompt=prompt,
116
+ negative_prompt=negative_prompt,
117
+ image=original_image,
118
+ mask_image=mask_image,
119
+ num_inference_steps=num_steps,
120
+ guidance_scale=7.0, # Slightly reduced for speed
121
+ ).images[0]
122
+
123
+ # Convert output image to base64
124
+ output_base64 = image_to_base64(output_image)
125
+
126
+ # Clean up
127
+ torch.cuda.empty_cache()
128
+ gc.collect()
129
+
130
+ return {"status": "success", "image": output_base64}
131
+
132
+ except Exception as e:
133
+ raise HTTPException(status_code=500, detail=str(e))
134
+
135
+ @app.get("/health")
136
+ async def health_check():
137
  return {"status": "healthy", "cuda_available": torch.cuda.is_available()}
example_client.py CHANGED
@@ -39,7 +39,7 @@ def main():
39
  # Replace these with your actual image paths
40
  image_path = r"C:\Users\M. Y\Downloads\t2.png" # Replace with your image path
41
  mask_path = "generated_mask_1.png" # Replace with your mask path
42
- prompt = "add some flowers and a fountain"
43
 
44
  result = call_inpaint_api(image_path, mask_path, prompt)
45
  if result:
 
39
  # Replace these with your actual image paths
40
  image_path = r"C:\Users\M. Y\Downloads\t2.png" # Replace with your image path
41
  mask_path = "generated_mask_1.png" # Replace with your mask path
42
+ prompt = "add some Chair tables and a fountain"
43
 
44
  result = call_inpaint_api(image_path, mask_path, prompt)
45
  if result: