mostlycached commited on
Commit
7bb0e7b
·
verified ·
1 Parent(s): 867ba48

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -82
app.py CHANGED
@@ -8,8 +8,8 @@ import textwrap
8
 
9
  # Function to remove background and place text behind person
10
  def text_behind_image(input_image, text, text_color, font_size, text_opacity):
11
- if input_image is None:
12
- return None
13
 
14
  # Convert color hex to RGB
15
  try:
@@ -18,7 +18,7 @@ def text_behind_image(input_image, text, text_color, font_size, text_opacity):
18
  b = int(text_color[5:7], 16)
19
  text_color_rgb = (r, g, b)
20
  except:
21
- text_color_rgb = (255, 255, 255) # Default to white
22
 
23
  try:
24
  # Open the image
@@ -27,104 +27,97 @@ def text_behind_image(input_image, text, text_color, font_size, text_opacity):
27
  # Get dimensions
28
  width, height = img.size
29
 
30
- # Create a new image with white background (this will be the canvas)
31
- background = Image.new('RGBA', (width, height), (255, 255, 255, 255))
 
 
 
 
32
 
33
- # Create a drawing context for the text
34
- draw = ImageDraw.Draw(background)
 
35
 
36
- # Determine font size (relative to image size)
37
- font_size = int(min(width, height) * (font_size / 100)) # Convert percentage to actual size
38
- if font_size < 10: # Ensure font is at least 10 pixels
39
- font_size = 10
 
 
 
40
 
41
- # Try to load a nice font, fall back to default if not available
 
42
  try:
43
- # Try different common fonts
44
  font_paths = [
45
  "arial.ttf",
46
  "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
47
- "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf"
 
48
  ]
49
- font = None
50
  for font_path in font_paths:
51
  try:
52
  font = ImageFont.truetype(font_path, font_size)
53
  break
54
  except:
55
  continue
56
-
57
- if font is None:
58
- font = ImageFont.load_default()
59
  except:
 
 
 
60
  font = ImageFont.load_default()
61
-
62
- # Prepare the text - make it ALL CAPS for better visual impact
63
- text = text.upper()
64
-
65
- # Fill the entire background with repeating text pattern
66
- # Word wrap the text to fit within the image width
67
- margin = 20
68
- max_chars = max(10, int(width / (font_size/2)) - 2*margin)
69
- wrapper = textwrap.TextWrapper(width=max_chars)
70
- word_list = wrapper.wrap(text)
71
-
72
- # If text is too short, repeat it to fill the background
73
- if len(word_list) == 1 and len(text) < 10:
74
- repeated_text = (text + " ") * 10
75
- word_list = []
76
- for i in range(0, height, font_size + 5):
77
- word_list.append(repeated_text)
78
-
79
- # Calculate text block height
80
- line_spacing = int(font_size * 1.2)
81
- text_height = len(word_list) * line_spacing
82
-
83
- # Position text in the center
84
- y_text = (height - text_height) // 2
85
-
86
- # Draw text with specified opacity
87
- for line in word_list:
88
- # Get line width
89
- try:
90
- line_width = font.getbbox(line)[2] - font.getbbox(line)[0]
91
- except:
92
- # Fallback method to estimate width
93
- line_width = len(line) * (font_size // 2)
94
 
95
- # Center the line
96
- x_text = (width - line_width) // 2
 
 
97
 
98
- # Draw text with specified opacity
99
- text_color_with_opacity = text_color_rgb + (int(text_opacity * 255),)
100
- draw.text((x_text, y_text), line, font=font, fill=text_color_with_opacity)
101
- y_text += line_spacing
102
-
103
- # Ensure the text is very visible by drawing it multiple times with different Y positions
104
- if len(word_list) < 5:
105
- for offset in [-line_spacing*2, line_spacing*2]:
106
- y_text = (height - text_height) // 2 + offset
107
- for line in word_list:
108
- try:
109
- line_width = font.getbbox(line)[2] - font.getbbox(line)[0]
110
- except:
111
- line_width = len(line) * (font_size // 2)
112
- x_text = (width - line_width) // 2
113
- draw.text((x_text, y_text), line, font=font, fill=text_color_with_opacity)
114
- y_text += line_spacing
115
-
116
- # Remove background from the original image to get the person silhouette
117
- # Use the u2net_human_seg model specifically for better human segmentation
118
- try:
119
- person_img = remove(img, model_name="u2net_human_seg")
120
- except:
121
- # Fallback to default model if human_seg not available
122
- person_img = remove(img)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
- # Composite the images: text in background, then person on top
125
- final_image = Image.alpha_composite(background.convert('RGBA'), person_img.convert('RGBA'))
 
126
 
127
- # Convert back to RGB for display
128
  return np.array(final_image.convert('RGB'))
129
 
130
  except Exception as e:
@@ -142,7 +135,7 @@ with gr.Blocks(title="Text Behind Image") as demo:
142
  text_input = gr.Textbox(label="Text to place behind", placeholder="Enter text here...")
143
 
144
  with gr.Row():
145
- text_color = gr.ColorPicker(label="Text Color", value="#FFFFFF")
146
  font_size = gr.Slider(label="Font Size (%)", minimum=1, maximum=30, value=10, step=1)
147
  text_opacity = gr.Slider(label="Text Opacity", minimum=0.1, maximum=1.0, value=0.8, step=0.1)
148
 
 
8
 
9
  # Function to remove background and place text behind person
10
  def text_behind_image(input_image, text, text_color, font_size, text_opacity):
11
+ if input_image is None or text.strip() == "":
12
+ return input_image
13
 
14
  # Convert color hex to RGB
15
  try:
 
18
  b = int(text_color[5:7], 16)
19
  text_color_rgb = (r, g, b)
20
  except:
21
+ text_color_rgb = (0, 0, 0) # Default to black
22
 
23
  try:
24
  # Open the image
 
27
  # Get dimensions
28
  width, height = img.size
29
 
30
+ # First, remove background from the original image to get the person silhouette
31
+ try:
32
+ person_img = remove(img, model_name="u2net_human_seg")
33
+ except:
34
+ # Fallback to default model if human_seg not available
35
+ person_img = remove(img)
36
 
37
+ # Create a new image with white background for the text
38
+ text_bg = Image.new('RGBA', (width, height), (255, 255, 255, 255))
39
+ draw = ImageDraw.Draw(text_bg)
40
 
41
+ # Prepare the text
42
+ text = text.strip().upper()
43
+ if not text:
44
+ text = "SAMPLE TEXT"
45
+
46
+ # Set up the font
47
+ font_size = max(10, int(min(width, height) * (font_size / 100)))
48
 
49
+ # Try several fonts
50
+ font = None
51
  try:
 
52
  font_paths = [
53
  "arial.ttf",
54
  "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
55
+ "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
56
+ "/usr/share/fonts/truetype/freefont/FreeSansBold.ttf"
57
  ]
58
+
59
  for font_path in font_paths:
60
  try:
61
  font = ImageFont.truetype(font_path, font_size)
62
  break
63
  except:
64
  continue
 
 
 
65
  except:
66
+ pass
67
+
68
+ if font is None:
69
  font = ImageFont.load_default()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
+ # For short text, create a repeating pattern across the entire image
72
+ if len(text) < 20:
73
+ repeated_text = (text + " ") * 20
74
+ line_height = int(font_size * 1.5)
75
 
76
+ # Draw text in a grid pattern covering the entire image
77
+ for y in range(0, height, line_height):
78
+ # Offset each line for a more interesting pattern
79
+ offset = (y // line_height) % 20
80
+ line = repeated_text[offset:] + repeated_text[:offset]
81
+
82
+ # Draw the text
83
+ draw.text((10, y), line, font=font, fill=text_color_rgb + (int(text_opacity * 255),))
84
+
85
+ else:
86
+ # For longer text, do proper word wrapping
87
+ margin = 20
88
+ max_width = width - 2 * margin
89
+
90
+ # Calculate approx chars per line (estimating 0.6 × font_size per char width)
91
+ chars_per_line = max(10, int(max_width / (font_size * 0.6)))
92
+
93
+ # Word wrap
94
+ wrapper = textwrap.TextWrapper(width=chars_per_line)
95
+ lines = wrapper.wrap(text)
96
+
97
+ # Calculate total text height
98
+ line_height = int(font_size * 1.5)
99
+ text_height = len(lines) * line_height
100
+
101
+ # Calculate starting Y position (centered)
102
+ start_y = (height - text_height) // 2
103
+
104
+ # Draw each line
105
+ for i, line in enumerate(lines):
106
+ # Estimate line width (better than using font.getbbox which can fail)
107
+ line_width = min(max_width, len(line) * int(font_size * 0.6))
108
+
109
+ # Center the line
110
+ x = (width - line_width) // 2
111
+ y = start_y + (i * line_height)
112
+
113
+ # Draw the text with opacity
114
+ draw.text((x, y), line, font=font, fill=text_color_rgb + (int(text_opacity * 255),))
115
 
116
+ # Now combine the text background with the person
117
+ # The text goes behind the person, so we composite person on top of text
118
+ final_image = Image.alpha_composite(text_bg, person_img)
119
 
120
+ # Convert to RGB for display
121
  return np.array(final_image.convert('RGB'))
122
 
123
  except Exception as e:
 
135
  text_input = gr.Textbox(label="Text to place behind", placeholder="Enter text here...")
136
 
137
  with gr.Row():
138
+ text_color = gr.ColorPicker(label="Text Color", value="#000000")
139
  font_size = gr.Slider(label="Font Size (%)", minimum=1, maximum=30, value=10, step=1)
140
  text_opacity = gr.Slider(label="Text Opacity", minimum=0.1, maximum=1.0, value=0.8, step=0.1)
141