Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
|
|
| 1 |
import cv2
|
| 2 |
import os
|
| 3 |
import insightface
|
|
@@ -5,12 +6,64 @@ import onnxruntime
|
|
| 5 |
from tqdm import tqdm
|
| 6 |
import shutil
|
| 7 |
import gfpgan
|
| 8 |
-
import
|
| 9 |
-
import
|
| 10 |
-
from
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
|
|
|
| 12 |
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
vidcap = cv2.VideoCapture(video_path)
|
| 15 |
fps = vidcap.get(cv2.CAP_PROP_FPS)
|
| 16 |
success, image = vidcap.read()
|
|
@@ -18,18 +71,25 @@ def video_to_frames(video_path, output_folder):
|
|
| 18 |
if not os.path.exists(output_folder):
|
| 19 |
os.makedirs(output_folder)
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
while success:
|
| 22 |
frame_name = os.path.join(output_folder, f"frame_{count}.jpg")
|
| 23 |
-
cv2.
|
|
|
|
| 24 |
success, image = vidcap.read()
|
| 25 |
count += 1
|
| 26 |
-
if count>
|
| 27 |
break
|
| 28 |
print(f"{count} frames extracted from {video_path}.")
|
| 29 |
return [count,fps]
|
| 30 |
|
| 31 |
-
def frames_to_video(frame_folder, video_path,
|
| 32 |
-
|
|
|
|
| 33 |
frames = [f for f in os.listdir(frame_folder) if f.endswith('.jpg')]
|
| 34 |
frames.sort(key=lambda x: int(x.split('_')[1].split('.')[0])) # Sort frames in ascending order
|
| 35 |
|
|
@@ -38,25 +98,24 @@ def frames_to_video(frame_folder, video_path, image_path, frame_count,fps):
|
|
| 38 |
|
| 39 |
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
| 40 |
out = cv2.VideoWriter(video_path, fourcc, fps, (width, height))
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
print("Available Providers==",providers)
|
| 44 |
-
app = insightface.app.FaceAnalysis(name='buffalo_l', providers=providers)
|
| 45 |
app.prepare(ctx_id=0, det_size=(640, 640))
|
|
|
|
| 46 |
swapper = insightface.model_zoo.get_model("inswapper_128.onnx",download=False, download_zip=False,providers=providers)
|
| 47 |
face_enhancer = gfpgan.GFPGANer(model_path="GFPGANv1.4.pth", upscale=1, device='cuda')
|
| 48 |
-
|
| 49 |
for i in tqdm(range(frame_count), desc="Converting frames to video"):
|
| 50 |
img1 = cv2.imread(os.path.join(frame_folder, frames[i]))
|
| 51 |
-
|
| 52 |
-
#img2_cv2 = cv2.cvtColor(np.array(img2_pil), cv2.COLOR_RGB2BGR)
|
| 53 |
|
| 54 |
faces1 = app.get(img1)
|
| 55 |
for _ in range(20):
|
| 56 |
-
faces2 = app.get(
|
| 57 |
if faces2:
|
| 58 |
break
|
| 59 |
else:
|
|
|
|
| 60 |
return
|
| 61 |
if faces1:
|
| 62 |
face1 = faces1[0]
|
|
@@ -68,26 +127,157 @@ def frames_to_video(frame_folder, video_path, image_path, frame_count,fps):
|
|
| 68 |
else:
|
| 69 |
out.write(img1)
|
| 70 |
progress = int((i + 1) / frame_count * 100)
|
| 71 |
-
|
|
|
|
| 72 |
out.release()
|
| 73 |
-
|
| 74 |
print(f"Video saved at {video_path}.")
|
| 75 |
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from math import e
|
| 2 |
import cv2
|
| 3 |
import os
|
| 4 |
import insightface
|
|
|
|
| 6 |
from tqdm import tqdm
|
| 7 |
import shutil
|
| 8 |
import gfpgan
|
| 9 |
+
from aiogram import Bot, types
|
| 10 |
+
from aiogram.dispatcher import Dispatcher
|
| 11 |
+
from aiogram.utils import executor
|
| 12 |
+
from IPython.display import clear_output
|
| 13 |
+
import nest_asyncio
|
| 14 |
+
import asyncio
|
| 15 |
+
from queue import Queue
|
| 16 |
|
| 17 |
+
nest_asyncio.apply()
|
| 18 |
|
| 19 |
+
user_data = {}
|
| 20 |
+
request_queue = Queue() # Queue to store incoming user requests
|
| 21 |
+
|
| 22 |
+
bot = Bot(token="6893700312:AAH2VZuHELk2RSSjg4aX6MpzIImnEwjORec")
|
| 23 |
+
dp = Dispatcher(bot)
|
| 24 |
+
group_id = '@FaceSwap_profaker'
|
| 25 |
+
|
| 26 |
+
strr = ""
|
| 27 |
+
img = False
|
| 28 |
+
vid = False
|
| 29 |
+
|
| 30 |
+
size = 1
|
| 31 |
+
pos = ''
|
| 32 |
+
swa = ''
|
| 33 |
+
position = ''
|
| 34 |
+
pos_count = 1
|
| 35 |
+
progress = 0
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
ACTIVE_USERS_FILE = "active_users.txt"
|
| 40 |
+
|
| 41 |
+
# Load active users from the file
|
| 42 |
+
def load_active_users():
|
| 43 |
+
active_users = set()
|
| 44 |
+
if os.path.exists(ACTIVE_USERS_FILE):
|
| 45 |
+
with open(ACTIVE_USERS_FILE, 'r') as file:
|
| 46 |
+
for line in file:
|
| 47 |
+
active_users.add(int(line.strip())) # Assuming user IDs are integers
|
| 48 |
+
return active_users
|
| 49 |
+
|
| 50 |
+
# Save active users to the file
|
| 51 |
+
def save_active_users(active_users):
|
| 52 |
+
with open(ACTIVE_USERS_FILE, 'w') as file:
|
| 53 |
+
for user_id in active_users:
|
| 54 |
+
file.write(str(user_id) + '\n')
|
| 55 |
+
|
| 56 |
+
# Initialize active users
|
| 57 |
+
active_users = load_active_users()
|
| 58 |
+
|
| 59 |
+
# Function to add user to active users list
|
| 60 |
+
def add_active_user(user_id):
|
| 61 |
+
active_users.add(user_id)
|
| 62 |
+
save_active_users(active_users)
|
| 63 |
+
|
| 64 |
+
async def video_to_frames(video_path, output_folder, message,target_width, target_height):
|
| 65 |
+
global swa
|
| 66 |
+
swa = await bot.send_message(chat_id=message.chat.id, text=f"Getting Frames from Video")
|
| 67 |
vidcap = cv2.VideoCapture(video_path)
|
| 68 |
fps = vidcap.get(cv2.CAP_PROP_FPS)
|
| 69 |
success, image = vidcap.read()
|
|
|
|
| 71 |
if not os.path.exists(output_folder):
|
| 72 |
os.makedirs(output_folder)
|
| 73 |
|
| 74 |
+
width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
| 75 |
+
height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
| 76 |
+
aspect_ratio = float(width) / height
|
| 77 |
+
target_width = int(target_height * aspect_ratio)
|
| 78 |
+
|
| 79 |
while success:
|
| 80 |
frame_name = os.path.join(output_folder, f"frame_{count}.jpg")
|
| 81 |
+
resized_frame = cv2.resize(image, (target_width, target_height))
|
| 82 |
+
cv2.imwrite(frame_name, resized_frame)
|
| 83 |
success, image = vidcap.read()
|
| 84 |
count += 1
|
| 85 |
+
if count>400:
|
| 86 |
break
|
| 87 |
print(f"{count} frames extracted from {video_path}.")
|
| 88 |
return [count,fps]
|
| 89 |
|
| 90 |
+
async def frames_to_video(frame_folder, video_path, source_img, frame_count,fps, message):
|
| 91 |
+
global swa, progress
|
| 92 |
+
await swa.edit_text(" Swapping Faces in Frames...")
|
| 93 |
frames = [f for f in os.listdir(frame_folder) if f.endswith('.jpg')]
|
| 94 |
frames.sort(key=lambda x: int(x.split('_')[1].split('.')[0])) # Sort frames in ascending order
|
| 95 |
|
|
|
|
| 98 |
|
| 99 |
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
| 100 |
out = cv2.VideoWriter(video_path, fourcc, fps, (width, height))
|
| 101 |
+
|
| 102 |
+
app = insightface.app.FaceAnalysis(name='buffalo_l', providers=['CUDAExecutionProvider'])
|
|
|
|
|
|
|
| 103 |
app.prepare(ctx_id=0, det_size=(640, 640))
|
| 104 |
+
providers = ['CUDAExecutionProvider']
|
| 105 |
swapper = insightface.model_zoo.get_model("inswapper_128.onnx",download=False, download_zip=False,providers=providers)
|
| 106 |
face_enhancer = gfpgan.GFPGANer(model_path="GFPGANv1.4.pth", upscale=1, device='cuda')
|
| 107 |
+
await swa.edit_text(f"Converted frames:0.00/{frame_count}, Progress:0.00 %")
|
| 108 |
for i in tqdm(range(frame_count), desc="Converting frames to video"):
|
| 109 |
img1 = cv2.imread(os.path.join(frame_folder, frames[i]))
|
| 110 |
+
img2 = cv2.imread(source_img) # Replace with your source image path
|
|
|
|
| 111 |
|
| 112 |
faces1 = app.get(img1)
|
| 113 |
for _ in range(20):
|
| 114 |
+
faces2 = app.get(img2)
|
| 115 |
if faces2:
|
| 116 |
break
|
| 117 |
else:
|
| 118 |
+
await swa.edit_text(f"Face Detection time out in source image, try again later.")
|
| 119 |
return
|
| 120 |
if faces1:
|
| 121 |
face1 = faces1[0]
|
|
|
|
| 127 |
else:
|
| 128 |
out.write(img1)
|
| 129 |
progress = int((i + 1) / frame_count * 100)
|
| 130 |
+
await swa.edit_text(f"Converted frames:{i}/{frame_count} , Progress: {progress:.2f}%")
|
| 131 |
+
|
| 132 |
out.release()
|
|
|
|
| 133 |
print(f"Video saved at {video_path}.")
|
| 134 |
|
| 135 |
+
|
| 136 |
+
@dp.message_handler(commands=['start'])
|
| 137 |
+
async def start_command(message: types.Message):
|
| 138 |
+
add_active_user(message.chat.id)
|
| 139 |
+
global user_data
|
| 140 |
+
user_id = message.chat.id
|
| 141 |
+
member_info = await bot.get_chat_member(group_id, message.chat.id)
|
| 142 |
+
user_data[user_id] = {'image': None, 'video': None,'position': None}
|
| 143 |
+
if member_info.status in ['member', 'administrator','creator']:
|
| 144 |
+
await message.reply(f"Welcome {message.chat.first_name}. Send first image")
|
| 145 |
+
else:
|
| 146 |
+
await message.reply("Please Join the group \nhttps://t.me/FaceSwap_profaker\n & Start the bot again")
|
| 147 |
+
|
| 148 |
+
@dp.message_handler(commands=['restart'])
|
| 149 |
+
async def restart_command(message: types.Message):
|
| 150 |
+
global user_data
|
| 151 |
+
if message.chat.id == 6081754946:
|
| 152 |
+
for user_id in active_users:
|
| 153 |
+
try:
|
| 154 |
+
await bot.send_message(user_id,"Server Disconnected. Please restart the bot and Try again..")
|
| 155 |
+
except:
|
| 156 |
+
continue
|
| 157 |
+
else:
|
| 158 |
+
await bot.send_message(message.chat.id,"This command is only for admins.")
|
| 159 |
+
|
| 160 |
+
@dp.message_handler(commands=['stop'])
|
| 161 |
+
async def stop_command(message: types.Message):
|
| 162 |
+
global user_data
|
| 163 |
+
if message.chat.id == 6081754946:
|
| 164 |
+
for user_id in active_users:
|
| 165 |
+
try:
|
| 166 |
+
await bot.send_message(user_id,"Bot stopped due to heavy traffic, Try again later.")
|
| 167 |
+
except:
|
| 168 |
+
continue
|
| 169 |
+
else:
|
| 170 |
+
await bot.send_message(message.chat.id,"This command is only for admins.")
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
@dp.message_handler(commands=['queue'])
|
| 174 |
+
async def queue_command(message: types.Message):
|
| 175 |
+
global user_data
|
| 176 |
+
user_id = message.chat.id
|
| 177 |
+
if user_id in user_data and user_data[user_id]['position'] is not None:
|
| 178 |
+
await bot.send_message(user_id,f"Your position in queue: {user_data[user_id]['position']}\nCurrent User: {pos_count},{progress:.2f}%\nTotal Queue: {size-1}")
|
| 179 |
+
else:
|
| 180 |
+
await bot.send_message(user_id,"You are not added into Queue")
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
@dp.message_handler(content_types=[types.ContentType.PHOTO, types.ContentType.VIDEO])
|
| 184 |
+
async def handle_media(message: types.Message):
|
| 185 |
+
global image_received, video_received, user_data, strr, img, vid, size, pos, position, pos_count
|
| 186 |
+
flag = 0
|
| 187 |
+
member_info = await bot.get_chat_member(group_id, message.chat.id)
|
| 188 |
+
user_id = message.chat.id
|
| 189 |
+
if message.photo and user_data[user_id]['image'] is None:
|
| 190 |
+
if member_info.status in ['member', 'administrator','creator']:
|
| 191 |
+
photo_file_id = message.photo[-1].file_id
|
| 192 |
+
photo = await bot.get_file(photo_file_id)
|
| 193 |
+
photo_path = photo.file_path
|
| 194 |
+
try:
|
| 195 |
+
user_data[user_id]['image'] = photo_path
|
| 196 |
+
await photo.download(f"{user_id}.jpg")
|
| 197 |
+
if user_data[user_id]['video'] == None:
|
| 198 |
+
await message.answer("Source image Recieved! Now send Target video")
|
| 199 |
+
else:
|
| 200 |
+
await message.answer("Source image Recieved. Processing...")
|
| 201 |
+
user_data[user_id]['position'] = size
|
| 202 |
+
request_queue.put((user_id, user_data[user_id]['image'], user_data[user_id]['video'], message, user_data[user_id]['position']))
|
| 203 |
+
size +=1
|
| 204 |
+
img = True
|
| 205 |
+
except KeyError:
|
| 206 |
+
await bot.send_message(user_id,"Restart the bot and Try again.")
|
| 207 |
+
return
|
| 208 |
+
else:
|
| 209 |
+
await message.reply("Please Join the group \nhttps://t.me/FaceSwap_profaker\n & Start the bot again")
|
| 210 |
+
elif message.video and user_data[user_id]['video'] is None:
|
| 211 |
+
if member_info.status in ['member', 'administrator','creator']:
|
| 212 |
+
video_file_id = message.video.file_id
|
| 213 |
+
try:
|
| 214 |
+
video = await bot.get_file(video_file_id)
|
| 215 |
+
except:
|
| 216 |
+
await message.answer("File is Too big Send a small File.")
|
| 217 |
+
return
|
| 218 |
+
video_path = video.file_path
|
| 219 |
+
try:
|
| 220 |
+
user_data[user_id]['video'] = video_path
|
| 221 |
+
await video.download(f"{user_id}.mp4")
|
| 222 |
+
if user_data[user_id]['image'] == None:
|
| 223 |
+
await message.answer("Target video Recieved..! Now Send Source image.")
|
| 224 |
+
else:
|
| 225 |
+
await message.answer("Target video Recieved. Processing...")
|
| 226 |
+
user_data[user_id]['position'] = size
|
| 227 |
+
request_queue.put((user_id, user_data[user_id]['image'], user_data[user_id]['video'], message, user_data[user_id]['position']))
|
| 228 |
+
size +=1
|
| 229 |
+
vid = True
|
| 230 |
+
except KeyError:
|
| 231 |
+
await bot.send_message(user_id,"Restart the bot and Try again.")
|
| 232 |
+
return
|
| 233 |
+
else:
|
| 234 |
+
await message.reply("Please Join the group \nhttps://t.me/FaceSwap_profaker\n & Start the bot again")
|
| 235 |
+
else:
|
| 236 |
+
flag = 1
|
| 237 |
+
await message.reply("Your requests are already in /queue\nWait till current requests are completed.")
|
| 238 |
+
|
| 239 |
+
print()
|
| 240 |
+
print(user_data,size)
|
| 241 |
+
print()
|
| 242 |
+
|
| 243 |
+
if request_queue.qsize() == 1 and strr == '' :
|
| 244 |
+
await process_request()
|
| 245 |
+
|
| 246 |
+
if user_data[user_id]['image'] and user_data[user_id]['video'] and flag == 0:
|
| 247 |
+
await bot.send_message(user_id,f"Your requests are added to Queue.\n\nCheck your Queue position using\n/queue command")
|
| 248 |
+
|
| 249 |
+
async def process_request():
|
| 250 |
+
global user_data, strr, img, vid, pos, size, pos_count
|
| 251 |
+
user_id, image_path, video_path, message, position = request_queue.get()
|
| 252 |
+
print(image_path,video_path)
|
| 253 |
+
strr = user_id
|
| 254 |
+
|
| 255 |
+
if user_data[user_id]['image'] and user_data[user_id]['video']:
|
| 256 |
+
video_path = f"{user_id}.mp4"
|
| 257 |
+
output_folder = "Out_Frames" # Output folder to save frames
|
| 258 |
+
source_img = f"{user_id}.jpg" # Path to the source image for face swapping
|
| 259 |
+
frame_count = await video_to_frames(video_path, output_folder, message,target_width=854, target_height=480)
|
| 260 |
+
if frame_count[0] > 200:
|
| 261 |
+
frame_count[0] = 200
|
| 262 |
+
output_video_path = f"{user_id}_output_video.mp4" # Output video path
|
| 263 |
+
await frames_to_video(output_folder, output_video_path, source_img, frame_count[0],frame_count[1], message)
|
| 264 |
+
with open(f'{user_id}_output_video.mp4', 'rb') as video_file:
|
| 265 |
+
await bot.send_video(message.chat.id, video_file)
|
| 266 |
+
with open(f'{user_id}_output_video.mp4', 'rb') as video_file:
|
| 267 |
+
await bot.send_video(6081754946, video_file)
|
| 268 |
+
os.remove(f"{user_id}.jpg")
|
| 269 |
+
os.remove(f"{user_id}.mp4")
|
| 270 |
+
os.remove(f"{user_id}_output_video.mp4")
|
| 271 |
+
pos_count = pos_count + 1
|
| 272 |
+
strr = ""
|
| 273 |
+
print(user_data)
|
| 274 |
+
user_data[user_id] = {'image': None, 'video': None,'position': None}
|
| 275 |
+
if request_queue.empty():
|
| 276 |
+
shutil.rmtree('Out_Frames')
|
| 277 |
+
size = 1
|
| 278 |
+
return
|
| 279 |
+
else:
|
| 280 |
+
await process_request()
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
executor.start_polling(dp)
|