File size: 6,023 Bytes
70fb032
 
 
 
 
 
 
 
 
7bb0e7b
 
70fb032
 
 
 
 
 
 
 
7bb0e7b
70fb032
 
 
 
 
 
 
 
0f221db
7bb0e7b
0f221db
 
7bb0e7b
 
0f221db
 
 
 
 
 
 
 
 
 
70fb032
0f221db
 
 
 
 
 
 
70fb032
7bb0e7b
 
 
 
 
2023379
 
70fb032
7bb0e7b
 
70fb032
ab55629
 
 
7bb0e7b
 
ab55629
7bb0e7b
ab55629
 
 
 
 
 
70fb032
7bb0e7b
 
 
70fb032
2023379
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70fb032
0f221db
 
 
 
 
 
70fb032
7bb0e7b
70fb032
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7bb0e7b
70fb032
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ab55629
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import gradio as gr
import numpy as np
import PIL.Image as Image
from rembg import remove
from PIL import ImageDraw, ImageFont
import textwrap

# Function to remove background and place text behind person
def text_behind_image(input_image, text, text_color, font_size, text_opacity):
    if input_image is None or text.strip() == "":
        return input_image
    
    # Convert color hex to RGB
    try:
        r = int(text_color[1:3], 16)
        g = int(text_color[3:5], 16)
        b = int(text_color[5:7], 16)
        text_color_rgb = (r, g, b)
    except:
        text_color_rgb = (0, 0, 0)  # Default to black
    
    try:
        # Open the image
        img = Image.fromarray(input_image)
        
        # Get dimensions
        width, height = img.size
        
        # Step 1: Extract the person from the image
        try:
            # Try to use the human segmentation model first
            person_only = remove(img, model_name="u2net_human_seg")
        except:
            # Fallback to default model if human_seg not available
            person_only = remove(img)
            
        # Step 2: Create a mask from the person cutout
        person_mask = Image.new('RGBA', (width, height), (0, 0, 0, 0))
        person_mask.paste(person_only, (0, 0), person_only)
        
        # Step 3: Extract the background (original image without the person)
        # Create inverted mask (where the person is black, background is white)
        inverted_mask = Image.new('L', (width, height), 255)
        inverted_mask.paste(0, (0, 0), person_only)
        
        # Extract just the background
        background = img.copy()
        background.putalpha(inverted_mask)
        
        # Step 4: Create the text layer
        text_layer = Image.new('RGBA', (width, height), (0, 0, 0, 0))
        draw = ImageDraw.Draw(text_layer)
        
        # Prepare the text
        text = text.strip().upper()
        if not text:
            text = "SAMPLE TEXT"
            
        # Set up the font size - make it larger since we're just placing it once
        font_size = max(20, int(min(width, height) * (font_size / 100)))
        
        # Try several fonts
        font = None
        try:
            font_paths = [
                "arial.ttf", 
                "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
                "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
                "/usr/share/fonts/truetype/freefont/FreeSansBold.ttf"
            ]
            
            for font_path in font_paths:
                try:
                    font = ImageFont.truetype(font_path, font_size)
                    break
                except:
                    continue
        except:
            pass
            
        if font is None:
            font = ImageFont.load_default()
        
        # Get text dimensions
        # Try to use getbbox first for newer PIL versions
        try:
            text_width = font.getbbox(text)[2] - font.getbbox(text)[0]
            text_height = font.getbbox(text)[3] - font.getbbox(text)[1]
        except:
            # Fallback for older PIL versions
            try:
                text_width = font.getsize(text)[0]
                text_height = font.getsize(text)[1]
            except:
                # Second fallback - estimate size
                text_width = len(text) * (font_size * 0.6)
                text_height = font_size * 1.2
        
        # Position in the upper middle section
        # Divide the image into a 3x3 grid and put the text in the top-center cell
        grid_width = width // 3
        grid_height = height // 3
        
        # Center horizontally in the middle third
        x_center = width // 2 - text_width // 2
        
        # Position vertically in the top third
        y_top = grid_height // 2 - text_height // 2
        
        # Draw the text with specified opacity and color
        draw.text((x_center, y_top), text, font=font, fill=text_color_rgb + (int(text_opacity * 255),))
        
        # Step 5: Composite all layers together
        # First, composite the text on top of the background
        background_with_text = Image.alpha_composite(background, text_layer)
        
        # Then, composite the person on top
        final_image = Image.alpha_composite(background_with_text, person_mask)
        
        # Convert to RGB for display
        return np.array(final_image.convert('RGB'))
    
    except Exception as e:
        print(f"Error processing image: {e}")
        return input_image  # Return original image on error

# Create Gradio interface
with gr.Blocks(title="Text Behind Image") as demo:
    gr.Markdown("# Text Behind Image")
    gr.Markdown("Upload an image with a person and add text behind them")
    
    with gr.Row():
        with gr.Column():
            input_image = gr.Image(label="Upload Image", type="numpy")
            text_input = gr.Textbox(label="Text to place behind", placeholder="Enter text here...")
            
            with gr.Row():
                text_color = gr.ColorPicker(label="Text Color", value="#000000")
                font_size = gr.Slider(label="Font Size (%)", minimum=1, maximum=30, value=10, step=1)
                text_opacity = gr.Slider(label="Text Opacity", minimum=0.1, maximum=1.0, value=0.8, step=0.1)
            
            submit_btn = gr.Button("Generate", variant="primary")
        
        with gr.Column():
            output_image = gr.Image(label="Result", type="numpy")
    
    submit_btn.click(
        fn=text_behind_image,
        inputs=[input_image, text_input, text_color, font_size, text_opacity],
        outputs=output_image
    )
    
    gr.Markdown("## How it works")
    gr.Markdown("1. Upload an image with a person")
    gr.Markdown("2. Enter the text you want to place behind the person")
    gr.Markdown("3. Customize text color, size, and opacity")
    gr.Markdown("4. Click 'Generate' to create your image")

# Launch the app
demo.launch()