Spaces:
Runtime error
Runtime error
added main files
Browse files- app.py +37 -0
- commons/__pycache__/selfie_seg.cpython-39.pyc +0 -0
- commons/selfie_seg.py +230 -0
- flagged/file/0.mp4 +0 -0
- flagged/file/1.mp4 +0 -0
- flagged/log.csv +4 -0
- flagged/output/0.mp4 +0 -0
- flagged/output/1.mp4 +0 -0
- requirements.txt +5 -0
app.py
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import numpy as np
|
3 |
+
import gradio as gr
|
4 |
+
|
5 |
+
from commons.selfie_seg import (
|
6 |
+
load_from_webcam,
|
7 |
+
load_from_static_image,
|
8 |
+
load_from_video
|
9 |
+
)
|
10 |
+
|
11 |
+
# Optional[str | PIL.Image | np.narray]
|
12 |
+
|
13 |
+
title = "Image and Video background changer"
|
14 |
+
desc = "This simple app leverages google selfie segmentation via mediapipe to change background from bot images and videos. The \
|
15 |
+
backgroud type can be solid pictures, random images, or blur"
|
16 |
+
|
17 |
+
imgs = os.listdir("bg_imgs/")
|
18 |
+
rnd_img = "bg_imgs/" + np.random.choice(imgs)
|
19 |
+
|
20 |
+
|
21 |
+
img_app = gr.Interface(
|
22 |
+
load_from_static_image,
|
23 |
+
[gr.Image(), gr.Dropdown(["random_image", "solid_colors", "blur"], label="Background Type", placeholder="Background type")], #,gr.Textbox(label="Background can be blur, a set of random_image, or a solid_colors")], #
|
24 |
+
gr.Image()
|
25 |
+
)
|
26 |
+
|
27 |
+
vid_app = gr.Interface(
|
28 |
+
load_from_video,
|
29 |
+
[gr.Video(source="upload"), gr.Dropdown(["ragindom_image", "solid_colors", "blur"], placeholder="Background type", show_label="Video")],
|
30 |
+
[gr.Video(interactive=False, label="Video")]
|
31 |
+
)
|
32 |
+
|
33 |
+
gr.TabbedInterface([img_app, vid_app], ["Image", "Video"]).launch(
|
34 |
+
max_threads = 4)
|
35 |
+
|
36 |
+
|
37 |
+
|
commons/__pycache__/selfie_seg.cpython-39.pyc
ADDED
Binary file (4 kB). View file
|
|
commons/selfie_seg.py
ADDED
@@ -0,0 +1,230 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import cv2
|
3 |
+
import mediapipe as mp
|
4 |
+
import numpy as np
|
5 |
+
from moviepy.editor import (
|
6 |
+
VideoFileClip, AudioFileClip)
|
7 |
+
|
8 |
+
mp_drawing = mp.solutions.drawing_utils
|
9 |
+
mp_selfie_segmentation = mp.solutions.selfie_segmentation
|
10 |
+
|
11 |
+
imgs = os.listdir("bg_imgs/")
|
12 |
+
rnd_img = "bg_imgs/" + np.random.choice(imgs)
|
13 |
+
#IMAGE_FILES = ["/home/samuel/Documents/Computer Vision Codes/istockphoto-1193994027-170667a.jpg"]
|
14 |
+
|
15 |
+
|
16 |
+
|
17 |
+
# For webcam input:
|
18 |
+
def load_from_webcam(bg_type: str = "blur"):
|
19 |
+
cap = cv2.VideoCapture(0)
|
20 |
+
with mp_selfie_segmentation.SelfieSegmentation(
|
21 |
+
model_selection=1) as selfie_segmentation:
|
22 |
+
|
23 |
+
while cap.isOpened():
|
24 |
+
success, image = cap.read()
|
25 |
+
if not success:
|
26 |
+
print("Ignoring empty camera frame.")
|
27 |
+
# If loading a video, use 'break' instead of 'continue'.
|
28 |
+
continue
|
29 |
+
|
30 |
+
# Flip the image horizontally for a later selfie-view display, and convert
|
31 |
+
# the BGR image to RGB.
|
32 |
+
image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
|
33 |
+
# To improve performance, optionally mark the image as not writeable to
|
34 |
+
# pass by reference.
|
35 |
+
image.flags.writeable = False
|
36 |
+
results = selfie_segmentation.process(image)
|
37 |
+
|
38 |
+
image.flags.writeable = True
|
39 |
+
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
|
40 |
+
|
41 |
+
# Draw selfie segmentation on the background image.
|
42 |
+
# To improve segmentation around boundaries, consider applying a joint
|
43 |
+
# bilateral filter to "results.segmentation_mask" with "image".
|
44 |
+
condition = np.stack(
|
45 |
+
(results.segmentation_mask,) * 3, axis=-1) > 0.7
|
46 |
+
# The background can be customized.
|
47 |
+
# a) Load an image (with the same width and height of the input image) to
|
48 |
+
# be the background, e.g., bg_image = cv2.imread('/path/to/image/file')
|
49 |
+
# b) Blur the input image by applying image filtering, e.g.,
|
50 |
+
# bg_image = cv2.GaussianBlur(image,(55,55),0)
|
51 |
+
image_height, image_width, _ = image.shape
|
52 |
+
|
53 |
+
if bg_type == "blur":
|
54 |
+
bg_image = cv2.GaussianBlur(image,(55,55),0)
|
55 |
+
|
56 |
+
if bg_type == "random_image":
|
57 |
+
bg_image = cv2.resize(cv2.imread(rnd_img), (image_width, image_height))
|
58 |
+
|
59 |
+
if (bg_image is None) or (bg_image == "solid_colors"):
|
60 |
+
bg_image = np.zeros(image.shape, dtype=np.uint8)
|
61 |
+
bg_image[:] = np.random.randint(0, high=256, size=(3,)).tolist()
|
62 |
+
|
63 |
+
output_image = np.where(condition, image, bg_image)
|
64 |
+
|
65 |
+
cv2.imshow('MediaPipe Selfie Segmentation', output_image)
|
66 |
+
if cv2.waitKey(5) & 0xFF == ord("q"):
|
67 |
+
break
|
68 |
+
cap.release()
|
69 |
+
|
70 |
+
|
71 |
+
|
72 |
+
# For static images
|
73 |
+
def load_from_static_image(file: cv2.Mat, bg_type: str = "solid_colors"):
|
74 |
+
with mp_selfie_segmentation.SelfieSegmentation(
|
75 |
+
model_selection=0) as selfie_segmentation:
|
76 |
+
#for idx, file in enumerate(IMAGE_FILES):
|
77 |
+
#print (file)
|
78 |
+
image = file #cv2.imread(file)
|
79 |
+
image_height, image_width, _ = image.shape
|
80 |
+
# Convert the BGR image to RGB before processing.
|
81 |
+
results = selfie_segmentation.process(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
|
82 |
+
|
83 |
+
# Draw selfie segmentation on the background image.
|
84 |
+
# To improve segmentation around boundaries, consider applying a joint
|
85 |
+
# bilateral filter to "results.segmentation_mask" with "image".
|
86 |
+
# increase threshold to 0.8 or reduce
|
87 |
+
condition = np.stack((results.segmentation_mask,) * 3, axis=-1) > 0.8
|
88 |
+
|
89 |
+
if bg_type == "blur":
|
90 |
+
bg_image = cv2.GaussianBlur(image, (55,55), 0)
|
91 |
+
if bg_type == "random_image":
|
92 |
+
bg_image = cv2.resize(cv2.imread(rnd_img), (image_width, image_height))
|
93 |
+
if (bg_type is None) or (bg_type == "solid_colors"):
|
94 |
+
bg_image = np.zeros(image.shape, dtype=np.uint8)
|
95 |
+
bg_image[:] = np.random.randint(0, high=256, size=(3,)).tolist()
|
96 |
+
|
97 |
+
output_image = np.where(condition, image, bg_image)
|
98 |
+
return output_image
|
99 |
+
|
100 |
+
|
101 |
+
# For Videos
|
102 |
+
def load_from_video(file: str, bg_type: str = "solid_colors"):
|
103 |
+
vcap = cv2.VideoCapture(file)
|
104 |
+
# Get video properties
|
105 |
+
frame_width = int(vcap.get(3))
|
106 |
+
frame_height = int(vcap.get(4))
|
107 |
+
vid_fps = int(vcap.get(5))
|
108 |
+
|
109 |
+
vid_size = (frame_width, frame_height)
|
110 |
+
|
111 |
+
audio_path = "audio.mp3"
|
112 |
+
video_path = "output_video_from_file.mp4"
|
113 |
+
# *'h264'
|
114 |
+
output = cv2.VideoWriter(video_path, cv2.VideoWriter_fourcc(*'avc1'), vid_fps, vid_size)
|
115 |
+
|
116 |
+
selfie_segmentation = mp_selfie_segmentation.SelfieSegmentation(model_selection=1)
|
117 |
+
solid_bg = np.random.randint(0, high=256, size=(3,)).tolist()
|
118 |
+
|
119 |
+
while True:
|
120 |
+
success, image = vcap.read()
|
121 |
+
if success == True:
|
122 |
+
|
123 |
+
image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)
|
124 |
+
image.flags.writeable = False
|
125 |
+
|
126 |
+
results = selfie_segmentation.process(image)
|
127 |
+
image.flags.writeable = True
|
128 |
+
|
129 |
+
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
|
130 |
+
condition = np.stack(
|
131 |
+
(results.segmentation_mask, ) * 3, axis=-1) > 0.7
|
132 |
+
|
133 |
+
image_height, image_width = image.shape[:2]
|
134 |
+
|
135 |
+
if bg_type == "blur":
|
136 |
+
bg_image = cv2.GaussianBlur(image, (55,55),0)
|
137 |
+
|
138 |
+
if bg_type == "random_image":
|
139 |
+
bg_image = cv2.resize(cv2.imread(rnd_img), (image_width, image_height))
|
140 |
+
|
141 |
+
if (bg_type == None) | (bg_type == "solid_colors"):
|
142 |
+
bg_image = np.zeros(image.shape, dtype=np.uint8)
|
143 |
+
bg_image[:] = solid_bg
|
144 |
+
|
145 |
+
output_image = np.where(condition, image, bg_image)
|
146 |
+
output.write(output_image)
|
147 |
+
|
148 |
+
else:
|
149 |
+
print ("Video stream disconnected")
|
150 |
+
break
|
151 |
+
vcap.release()
|
152 |
+
output.release()
|
153 |
+
|
154 |
+
try:
|
155 |
+
clip = VideoFileClip(file)
|
156 |
+
clip.audio.write_audiofile(audio_path)
|
157 |
+
|
158 |
+
video_clip = VideoFileClip(video_path)
|
159 |
+
audio_clip = AudioFileClip(audio_path)
|
160 |
+
|
161 |
+
if video_clip.end > audio_clip.end:
|
162 |
+
final_clip = video_clip.set_audio(audio_clip)
|
163 |
+
final_clip.write_videofile("final.mp4")
|
164 |
+
else:
|
165 |
+
audio_clip = audio_clip.subclip(0, video_clip.end)
|
166 |
+
final_clip = video_clip.set_audio(audio_clip)
|
167 |
+
final_clip.write_videofile("final.mp4")
|
168 |
+
|
169 |
+
os.remove(video_path)
|
170 |
+
os.remove(audio_path)
|
171 |
+
except AttributeError: #i.e there's no audio in the video
|
172 |
+
return "/home/samuel/Documents/Computer Vision Codes/selfie_seg/output_video_from_file.mp4"
|
173 |
+
|
174 |
+
|
175 |
+
return "final.mp4"
|
176 |
+
|
177 |
+
|
178 |
+
if __name__ == "__main__":
|
179 |
+
|
180 |
+
vp = "/home/samuel/Documents/Computer Vision Codes/Course Overview_5.mp4"
|
181 |
+
load_from_video(vp, bg_type="solid_colors")
|
182 |
+
|
183 |
+
vp = "/home/samuel/Documents/Computer Vision Codes/Course Overview_5.mp4"
|
184 |
+
|
185 |
+
|
186 |
+
""" vcap = cv2.VideoCapture(vp)
|
187 |
+
frame_width = int(vcap.get(3))
|
188 |
+
frame_height = int(vcap.get(4))
|
189 |
+
frame_size = (frame_width,frame_height)
|
190 |
+
fps = int(vcap.get(5))
|
191 |
+
|
192 |
+
audio_path = "audio.mp3"
|
193 |
+
video_path = "output_video_from_file.mp4"
|
194 |
+
|
195 |
+
output = cv2.VideoWriter(video_path, cv2.VideoWriter_fourcc('M','J','P','G'), fps, frame_size)
|
196 |
+
|
197 |
+
clip = VideoFileClip(vp)
|
198 |
+
clip.audio.write_audiofile(audio_path)
|
199 |
+
|
200 |
+
while True:
|
201 |
+
ret, frame = vcap.read()
|
202 |
+
if ret == True:
|
203 |
+
output.write(frame)
|
204 |
+
else:
|
205 |
+
print ("Video stram disconnected")
|
206 |
+
break
|
207 |
+
|
208 |
+
vcap.release()
|
209 |
+
output.release()
|
210 |
+
|
211 |
+
|
212 |
+
video_clip = VideoFileClip(video_path)
|
213 |
+
audio_clip = AudioFileClip(audio_path)
|
214 |
+
|
215 |
+
|
216 |
+
if video_clip.end > audio_clip.end:
|
217 |
+
final_clip = video_clip.set_audio(audio_clip)
|
218 |
+
final_clip.write_videofile("final.mp4")
|
219 |
+
else:
|
220 |
+
audio_clip = audio_clip.subclip(0, video_clip.end)
|
221 |
+
final_clip = video_clip.set_audio(audio_clip)
|
222 |
+
final_clip.write_videofile("final.mp4")
|
223 |
+
|
224 |
+
|
225 |
+
os.remove(video_path)
|
226 |
+
os.remove(audio_path) """
|
227 |
+
|
228 |
+
|
229 |
+
#final_output = os.system("ffmpeg -i " + video_path+" -i "+audio_path+" -c:v copy -c:a aac "+output_path)
|
230 |
+
|
flagged/file/0.mp4
ADDED
Binary file (467 kB). View file
|
|
flagged/file/1.mp4
ADDED
Binary file (467 kB). View file
|
|
flagged/log.csv
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
'name','output','flag','username','timestamp'
|
2 |
+
'Samuel','Hello Samuel Welcome','','','2022-07-23 10:47:49.480285'
|
3 |
+
'file/0.mp4','random_image','output/0.mp4','','','2022-07-27 13:06:08.762759'
|
4 |
+
'file/1.mp4','random_image','output/1.mp4','','','2022-07-27 13:06:10.585150'
|
flagged/output/0.mp4
ADDED
Binary file (802 kB). View file
|
|
flagged/output/1.mp4
ADDED
Binary file (802 kB). View file
|
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
gradio==3.1.1
|
2 |
+
mediapipe==0.8.9.1
|
3 |
+
moviepy==1.0.3
|
4 |
+
numpy==1.20.3
|
5 |
+
opencv_python==4.5.5.64
|