gaur3009 commited on
Commit
c67b8fa
·
verified ·
1 Parent(s): 45a2032

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -98
app.py CHANGED
@@ -1,107 +1,126 @@
1
  import cv2
2
  import numpy as np
3
- import gradio as gr
4
  from PIL import Image, ImageDraw, ImageFont
 
 
 
 
 
5
 
6
-
7
- def generate_text_image(text, style, width, height, font_scale):
8
- """Generate an image of the input text with the selected style and scale."""
9
- font_path = {
10
- "Bold": "arialbd.ttf",
11
- "Italic": "ariali.ttf",
12
- "Graffiti": "graffiti.ttf", # Provide custom font if needed
13
- "Calligraphy": "calligraphy.ttf" # Provide custom font if needed
14
- }
15
-
16
- img = Image.new("RGBA", (width, height), (255, 255, 255, 0))
17
- draw = ImageDraw.Draw(img)
18
-
19
- # Dynamically calculate font size based on user-defined font scale
20
- font_size = int(min(width, height) * font_scale)
21
- try:
22
- font = ImageFont.truetype(font_path[style], size=font_size)
23
- except:
24
- font = ImageFont.load_default()
25
-
26
- text_bbox = draw.textbbox((0, 0), text, font=font)
27
- text_width = text_bbox[2] - text_bbox[0]
28
- text_height = text_bbox[3] - text_bbox[1]
29
-
30
- position = ((width - text_width) // 2, (height - text_height) // 2)
31
-
32
- draw.text(position, text, font=font, fill=(0, 0, 0, 255))
33
-
34
- return img
35
-
36
-
37
- def apply_displacement_map(text_img, clothing_img, strength=20):
38
- """Apply displacement map to blend text onto clothing."""
39
- gray = cv2.cvtColor(clothing_img, cv2.COLOR_BGR2GRAY)
40
- grad_x = cv2.Sobel(gray, cv2.CV_32F, 1, 0, ksize=5)
41
- grad_y = cv2.Sobel(gray, cv2.CV_32F, 0, 1, ksize=5)
42
-
43
- grad_x = cv2.normalize(grad_x, None, 0, 1, cv2.NORM_MINMAX)
44
- grad_y = cv2.normalize(grad_y, None, 0, 1, cv2.NORM_MINMAX)
45
-
46
- displacement_map = np.zeros_like(clothing_img, dtype=np.float32)
47
- displacement_map[:, :, 0] = grad_x * strength
48
- displacement_map[:, :, 1] = grad_y * strength
49
-
50
- text_warped = cv2.remap(
51
- text_img,
52
- displacement_map[:, :, 0].astype(np.float32),
53
- displacement_map[:, :, 1].astype(np.float32),
54
- interpolation=cv2.INTER_LINEAR
55
- )
56
-
57
- return text_warped
58
-
59
-
60
- def overlay_text_on_clothing(clothing_image, text_input, style, font_scale, strength=20, alpha=0.7, photo=None, blend_alpha=0.5):
61
- """Blend generated text and optional photo onto the clothing image."""
62
- clothing_img = cv2.imread(clothing_image) # Read image from file path
63
-
64
- # Generate text image dynamically
65
- text_img_pil = generate_text_image(text_input, style, clothing_img.shape[1], clothing_img.shape[0], font_scale)
66
- text_img = cv2.cvtColor(np.array(text_img_pil), cv2.COLOR_RGBA2BGRA)
67
-
68
- alpha_channel = text_img[:, :, 3] / 255.0
69
- text_img = text_img[:, :, :3]
70
-
71
- # Apply displacement map
72
- text_warped = apply_displacement_map(text_img, clothing_img, strength)
73
-
74
- for c in range(3):
75
- clothing_img[:, :, c] = (1 - alpha_channel) * clothing_img[:, :, c] + alpha_channel * text_warped[:, :, c]
76
-
77
- # Blend optional photo if provided
78
- if photo:
79
- photo_img = Image.open(photo).resize((clothing_img.shape[1], clothing_img.shape[0]))
80
- photo_img = cv2.cvtColor(np.array(photo_img), cv2.COLOR_RGBA2BGR)
81
- clothing_img = cv2.addWeighted(clothing_img, 1 - blend_alpha, photo_img, blend_alpha, 0)
82
-
83
- # Convert the final blended image back to a PIL Image and return
84
- blended_img = Image.fromarray(cv2.cvtColor(clothing_img, cv2.COLOR_BGR2RGB))
85
- return blended_img
86
-
87
-
88
- interface = gr.Interface(
89
- fn=overlay_text_on_clothing,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  inputs=[
91
- gr.Image(type="filepath", label="Upload Clothing Image", interactive=True),
92
- gr.Textbox(label="Enter Text for Design"),
93
- gr.Radio(["Bold", "Italic", "Graffiti", "Calligraphy"], label="Select Style", value="Bold"),
94
- gr.Slider(0.05, 0.5, step=0.05, value=0.1, label="Text Size (Scale)"),
95
- gr.Slider(10, 50, step=5, value=20, label="Displacement Strength"),
96
- gr.Slider(0.1, 1.0, step=0.1, value=0.7, label="Alpha Blending"),
97
- gr.Image(type="filepath", label="Optional Photo for Blending", interactive=True),
98
- gr.Slider(0.0, 1.0, step=0.1, value=0.5, label="Photo Blend Alpha")
99
  ],
100
- outputs=gr.Image(type="pil", label="Final Design"),
101
- title="AI-Powered Clothing Text and Photo Overlay",
102
- description="Upload a clothing image, enter a text design, and select a style. Adjust text size, blending, and optional photo overlay for enhanced designs.",
103
- allow_flagging="never"
104
  )
105
 
106
  if __name__ == "__main__":
107
- interface.launch()
 
1
  import cv2
2
  import numpy as np
 
3
  from PIL import Image, ImageDraw, ImageFont
4
+ import torch
5
+ import torchvision.transforms as T
6
+ from torchvision.models import resnet50
7
+ from scipy.ndimage import gaussian_filter
8
+ import gradio as gr
9
 
10
+ class TextClothBlender:
11
+ def __init__(self, font_path: str):
12
+ self.font_path = font_path
13
+ self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
14
+ self.model = resnet50(pretrained=True).to(self.device)
15
+ self.model.eval()
16
+
17
+ def preprocess_cloth_image(self, cloth_image_path: str):
18
+ # Load the cloth image
19
+ cloth_image = cv2.imread(cloth_image_path)
20
+ gray_image = cv2.cvtColor(cloth_image, cv2.COLOR_BGR2GRAY)
21
+
22
+ # Detect texture using edge detection
23
+ edges = cv2.Canny(gray_image, 50, 150)
24
+
25
+ # Extract features using ResNet
26
+ preprocess = T.Compose([
27
+ T.ToPILImage(),
28
+ T.Resize((224, 224)),
29
+ T.ToTensor(),
30
+ T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
31
+ ])
32
+ input_tensor = preprocess(cloth_image).unsqueeze(0).to(self.device)
33
+ with torch.no_grad():
34
+ features = self.model(input_tensor)
35
+
36
+ return cloth_image, edges, features
37
+
38
+ def render_text(self, text: str, font_size: int, text_color: tuple):
39
+ # Create a blank image for text
40
+ font = ImageFont.truetype(self.font_path, font_size)
41
+ text_size = font.getsize(text)
42
+ text_image = Image.new('RGBA', text_size, (255, 255, 255, 0))
43
+ draw = ImageDraw.Draw(text_image)
44
+ draw.text((0, 0), text, font=font, fill=text_color)
45
+
46
+ return np.array(text_image)
47
+
48
+ def apply_perspective_transform(self, text_image: np.ndarray, cloth_image_shape: tuple):
49
+ # Define points for perspective transformation
50
+ h, w, _ = cloth_image_shape
51
+ src_points = np.float32([[0, 0], [text_image.shape[1], 0], [0, text_image.shape[0]], [text_image.shape[1], text_image.shape[0]]])
52
+ dst_points = np.float32([[50, 50], [w - 50, 30], [50, h - 100], [w - 50, h - 120]])
53
+
54
+ matrix = cv2.getPerspectiveTransform(src_points, dst_points)
55
+ warped_text = cv2.warpPerspective(text_image, matrix, (w, h), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=(0, 0, 0, 0))
56
+
57
+ return warped_text
58
+
59
+ def blend_text_with_cloth(self, cloth_image: np.ndarray, text_image: np.ndarray, edges: np.ndarray):
60
+ # Convert cloth and text images to the same size
61
+ h, w, _ = cloth_image.shape
62
+ text_resized = cv2.resize(text_image, (w, h), interpolation=cv2.INTER_AREA)
63
+
64
+ # Convert text to grayscale for masking
65
+ text_gray = cv2.cvtColor(text_resized, cv2.COLOR_RGBA2GRAY)
66
+ _, text_mask = cv2.threshold(text_gray, 1, 255, cv2.THRESH_BINARY)
67
+
68
+ # Apply displacement mapping using the edges
69
+ displace_map = gaussian_filter(edges, sigma=5)
70
+ displaced_text = cv2.addWeighted(text_resized, 0.5, displace_map[..., None], 0.5, 0)
71
+
72
+ # Blend text and cloth using overlay mode
73
+ blended = cv2.addWeighted(cloth_image, 0.7, displaced_text[..., :3], 0.3, 0)
74
+
75
+ return blended
76
+
77
+ def refine_output(self, blended_image: np.ndarray):
78
+ # Apply Gaussian blur for smooth edges
79
+ refined = cv2.GaussianBlur(blended_image, (5, 5), 0)
80
+ return refined
81
+
82
+ def process(self, cloth_image_path: str, text: str, font_size: int, text_color: tuple):
83
+ # Step 1: Preprocess the cloth image
84
+ cloth_image, edges, _ = self.preprocess_cloth_image(cloth_image_path)
85
+
86
+ # Step 2: Render the text
87
+ text_image = self.render_text(text, font_size, text_color)
88
+
89
+ # Step 3: Apply perspective transformation
90
+ warped_text = self.apply_perspective_transform(text_image, cloth_image.shape)
91
+
92
+ # Step 4: Blend text with the cloth
93
+ blended_image = self.blend_text_with_cloth(cloth_image, warped_text, edges)
94
+
95
+ # Step 5: Refine the output
96
+ final_image = self.refine_output(blended_image)
97
+
98
+ return final_image
99
+
100
+ # Define the Gradio interface
101
+ def blend_text_on_cloth(cloth_image, text, font_size, text_color):
102
+ font_path = "path/to/font.ttf" # Ensure the font file exists in the deployed environment
103
+ blender = TextClothBlender(font_path)
104
+ text_color = tuple(map(int, text_color.strip('()').split(','))) # Convert string to tuple
105
+ cloth_image_path = "temp_cloth_image.jpg"
106
+
107
+ # Save the uploaded cloth image temporarily
108
+ cv2.imwrite(cloth_image_path, cv2.cvtColor(np.array(cloth_image), cv2.COLOR_RGB2BGR))
109
+
110
+ # Process the image
111
+ result = blender.process(cloth_image_path, text, int(font_size), text_color)
112
+ return result[:, :, ::-1] # Convert BGR to RGB for display
113
+
114
+ iface = gr.Interface(
115
+ fn=blend_text_on_cloth,
116
  inputs=[
117
+ gr.Image(type="pil", label="Upload Cloth Image"),
118
+ gr.Textbox(label="Text to Blend"),
119
+ gr.Slider(10, 100, step=1, label="Font Size"),
120
+ gr.Textbox(label="Text Color (R,G,B,A)", placeholder="e.g., 255,0,0,255")
 
 
 
 
121
  ],
122
+ outputs=gr.Image(type="numpy", label="Blended Output")
 
 
 
123
  )
124
 
125
  if __name__ == "__main__":
126
+ iface.launch()