local5 commited on
Commit
2ae7213
·
verified ·
1 Parent(s): c9b197d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +133 -0
app.py ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import torchvision.transforms as T
4
+ from torchvision.models.detection import maskrcnn_resnet50_fpn
5
+ from PIL import Image
6
+ import numpy as np
7
+ import cv2
8
+
9
+ # Load pretrained model for segmentation
10
+ model = maskrcnn_resnet50_fpn(pretrained=True)
11
+ model.eval()
12
+
13
+ # Function to segment human from input photo
14
+ def segment_human(image_path):
15
+ input_image = Image.open(image_path).convert("RGB")
16
+ preprocess = T.Compose([
17
+ T.ToTensor(),
18
+ ])
19
+ input_tensor = preprocess(input_image)
20
+
21
+ with torch.no_grad():
22
+ output = model([input_tensor])
23
+
24
+ # Get person class mask (COCO classes, person is class 1)
25
+ masks = output[0]['masks']
26
+ scores = output[0]['scores']
27
+ indices = [i for i, score in enumerate(scores) if score > 0.5] # Threshold for confidence
28
+ masks = masks[indices]
29
+
30
+ if masks.size(0) == 0:
31
+ raise ValueError("No person found in the image.")
32
+
33
+ # Take the first mask (if multiple persons are found)
34
+ mask = masks[0, 0].cpu().numpy() # Get the first mask and convert to numpy
35
+
36
+ # Convert to binary mask
37
+ binary_mask = (mask > 0.5).astype(np.uint8) # Threshold to create a binary mask
38
+
39
+ # Apply mask to input image
40
+ human_array = np.array(input_image) * binary_mask[..., np.newaxis]
41
+ human = Image.fromarray(human_array, "RGB")
42
+
43
+ # Create alpha channel for transparency
44
+ alpha_channel = Image.fromarray(binary_mask * 255, "L")
45
+ human.putalpha(alpha_channel)
46
+
47
+ return human
48
+
49
+ # Function to add segmented human to stereoscopic image of environment
50
+ def overlay_human(env_img, human_img, x_offset=0, y_offset=0, scale=1.0):
51
+ env_w, env_h = env_img.size
52
+ human_w, human_h = human_img.size
53
+
54
+ # Resize human image
55
+ human_img = human_img.resize((int(human_w * scale), int(human_h * scale)))
56
+ human_w, human_h = human_img.size
57
+
58
+ x = (env_w - human_w) // 2 + x_offset
59
+ y = (env_h - human_h) // 2 + y_offset
60
+
61
+ env_img.paste(human_img, (x, y), human_img)
62
+ return env_img
63
+
64
+ # Function to create an anaglyph image from left and right images
65
+ def create_anaglyph(left_img, right_img):
66
+ # Extract channels
67
+ left_red_channel = left_img[:, :, 2]
68
+ right_green_channel = right_img[:, :, 1]
69
+ right_blue_channel = right_img[:, :, 0]
70
+
71
+ # Create an empty image with the same dimensions
72
+ anaglyph = np.zeros_like(left_img)
73
+
74
+ # Assign the channels accordingly
75
+ anaglyph[:, :, 2] = left_red_channel # Red channel from left image
76
+ anaglyph[:, :, 1] = right_green_channel # Green channel from right image
77
+ anaglyph[:, :, 0] = right_blue_channel # Blue channel from right image
78
+
79
+ return anaglyph
80
+
81
+ def generate_anaglyph(human_image, background_choice, x_offset, y_offset, scale, offset):
82
+ backgrounds = {
83
+ "Environment 1": "env1.jpg",
84
+ "Environment 2": "env2.jpg",
85
+ "Environment 3": "env3.jpg"
86
+ }
87
+ env_img_path = backgrounds[background_choice]
88
+ human_img = segment_human(human_image)
89
+
90
+ # Split environment image into left and right for stereoscopic effect
91
+ stereo_image = cv2.imread(env_img_path)
92
+ height, width, _ = stereo_image.shape
93
+ midpoint = width // 2
94
+ left_image = stereo_image[:, :midpoint]
95
+ right_image = stereo_image[:, midpoint:]
96
+
97
+ left_image_rgb = cv2.cvtColor(left_image, cv2.COLOR_BGR2RGB)
98
+ right_image_rgb = cv2.cvtColor(right_image, cv2.COLOR_BGR2RGB)
99
+
100
+ left_image_rgb = overlay_human(Image.fromarray(left_image_rgb), human_img, x_offset - offset // 2, -y_offset, scale)
101
+ right_image_rgb = overlay_human(Image.fromarray(right_image_rgb), human_img, x_offset + offset // 2, -y_offset, scale)
102
+
103
+ left_image_rgb = cv2.cvtColor(np.array(left_image_rgb), cv2.COLOR_BGR2RGB)
104
+ right_image_rgb = cv2.cvtColor(np.array(right_image_rgb), cv2.COLOR_BGR2RGB)
105
+
106
+ anaglyph = create_anaglyph(left_image_rgb, right_image_rgb)
107
+ anaglyph_rgb = cv2.cvtColor(anaglyph, cv2.COLOR_BGR2RGB)
108
+
109
+ return anaglyph_rgb
110
+
111
+ # Gradio Interface
112
+ with gr.Blocks() as demo:
113
+ gr.Markdown("## Anaglyph Image Generator")
114
+ with gr.Row():
115
+ background_choice = gr.Dropdown(["Environment 1", "Environment 2", "Environment 3"], value="Environment 1", label="Select Background")
116
+ human_image = gr.Image(label="Upload Human Image", type="filepath")
117
+ with gr.Row():
118
+ x_offset = gr.Slider(-500, 500, value=0, step=1, label="Horizontal Offset")
119
+ y_offset = gr.Slider(-500, 500, value=0, step=1, label="Vertical Offset")
120
+ with gr.Row():
121
+ scale = gr.Slider(0.1, 2.0, value=1.0, label="Scale Human")
122
+ offset = gr.Slider(-20, 20, value=0, step=2, label="Depth - Negative is towards from viewer and Positive is away from viewer.")
123
+ generate_button = gr.Button("Generate Anaglyph")
124
+
125
+ output_image = gr.Image(label="Anaglyph Image Output")
126
+
127
+ generate_button.click(
128
+ generate_anaglyph,
129
+ inputs=[human_image, background_choice, x_offset, y_offset, scale, offset],
130
+ outputs=output_image
131
+ )
132
+
133
+ demo.launch()