Spaces:
Sleeping
Sleeping
| ''' | |
| 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) | |