Spaces:
Running
Running
''' | |
python green_process.py Star_Rail_Tribbie_MMD_Videos_sp30 Star_Rail_Tribbie_MMD_Videos_30s_Green --fast_mode --max_workers=10 | |
''' | |
import os | |
import sys | |
import argparse | |
import torch | |
from torchvision import transforms | |
from moviepy import VideoFileClip, vfx, concatenate_videoclips, ImageSequenceClip | |
from PIL import Image | |
import numpy as np | |
from concurrent.futures import ThreadPoolExecutor | |
from transformers import AutoModelForImageSegmentation | |
# Set up device | |
device = "cuda" if torch.cuda.is_available() else "cpu" | |
# Load both BiRefNet models | |
birefnet = AutoModelForImageSegmentation.from_pretrained("ZhengPeng7/BiRefNet", trust_remote_code=True) | |
birefnet.to(device) | |
birefnet_lite = AutoModelForImageSegmentation.from_pretrained("ZhengPeng7/BiRefNet_lite", trust_remote_code=True) | |
birefnet_lite.to(device) | |
# Image transformation pipeline | |
transform_image = transforms.Compose([ | |
transforms.Resize((768, 768)), | |
transforms.ToTensor(), | |
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]), | |
]) | |
def process_frame(frame, fast_mode): | |
try: | |
pil_image = Image.fromarray(frame) | |
#processed_image = process(pil_image, "#000000", fast_mode) | |
processed_image = process(pil_image, "#00FF00", fast_mode) | |
return np.array(processed_image) | |
except Exception as e: | |
print(f"Error processing frame: {e}") | |
return frame | |
def process(image, bg, fast_mode=False): | |
image_size = image.size | |
input_images = transform_image(image).unsqueeze(0).to(device) | |
model = birefnet_lite if fast_mode else birefnet | |
with torch.no_grad(): | |
preds = model(input_images)[-1].sigmoid().cpu() | |
pred = preds[0].squeeze() | |
pred_pil = transforms.ToPILImage()(pred) | |
mask = pred_pil.resize(image_size) | |
if isinstance(bg, str) and bg.startswith("#"): | |
color_rgb = tuple(int(bg[i:i+2], 16) for i in (1, 3, 5)) | |
background = Image.new("RGBA", image_size, color_rgb + (255,)) | |
elif isinstance(bg, Image.Image): | |
background = bg.convert("RGBA").resize(image_size) | |
else: | |
background = Image.open(bg).convert("RGBA").resize(image_size) | |
image = Image.composite(image, background, mask) | |
return image | |
def process_video(video_path, output_path, fast_mode=True, max_workers=10): | |
try: | |
video = VideoFileClip(video_path) | |
fps = video.fps | |
audio = video.audio | |
frames = list(video.iter_frames(fps=fps)) | |
processed_frames = [] | |
with ThreadPoolExecutor(max_workers=max_workers) as executor: | |
futures = [executor.submit(process_frame, frames[i], fast_mode) for i in range(len(frames))] | |
for future in futures: | |
result = future.result() | |
processed_frames.append(result) | |
processed_video = ImageSequenceClip(processed_frames, fps=fps) | |
processed_video = processed_video.with_audio(audio) | |
processed_video.write_videofile(output_path, codec="libx264") | |
except Exception as e: | |
print(f"Error processing video {video_path}: {e}") | |
def main(input_folder, output_folder, fast_mode=True, max_workers=10): | |
if not os.path.exists(output_folder): | |
os.makedirs(output_folder) | |
for video_file in os.listdir(input_folder): | |
if video_file.endswith((".mp4", ".avi", ".mov")): | |
video_path = os.path.join(input_folder, video_file) | |
output_path = os.path.join(output_folder, video_file) | |
print(f"Processing {video_path}...") | |
process_video(video_path, output_path, fast_mode, max_workers) | |
print(f"Finished processing {video_path}") | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser(description="Process videos to replace background with green.") | |
parser.add_argument("input_folder", type=str, help="Path to the folder containing input videos.") | |
parser.add_argument("output_folder", type=str, help="Path to the folder where processed videos will be saved.") | |
parser.add_argument("--fast_mode", action="store_true", help="Use BiRefNet_lite for faster processing.") | |
parser.add_argument("--max_workers", type=int, default=10, help="Number of workers for parallel processing.") | |
args = parser.parse_args() | |
main(args.input_folder, args.output_folder, args.fast_mode, args.max_workers) | |