insightface / app.py
Corin1998's picture
Update app.py
5bfcc41 verified
import os
import cv2
import numpy as np
import gradio as gr
import insightface
import urllib.request
from insightface.app import FaceAnalysis
# --- 0. モデルの自動ダウンロード ---
def download_model_if_missing():
model_filename = 'inswapper_128.onnx'
url = "https://huggingface.co/ezioruan/inswapper_128.onnx/resolve/main/inswapper_128.onnx"
if not os.path.exists(model_filename):
print("Downloading model...")
urllib.request.urlretrieve(url, model_filename)
download_model_if_missing()
# --- 1. モデルの初期化 ---
app = FaceAnalysis(name='buffalo_l', providers=['CPUExecutionProvider'])
app.prepare(ctx_id=0, det_size=(640, 640))
swapper = insightface.model_zoo.get_model('inswapper_128.onnx', download=False, providers=['CPUExecutionProvider'])
# --- 2. 動画処理ロジック ---
def process_video(source_img, target_video, progress=gr.Progress()):
if source_img is None or target_video is None:
return None, "画像と動画を選択してください。"
# ソース顔の抽出
source_faces = app.get(source_img)
if not source_faces:
return None, "画像から顔が見つかりません。"
source_face = source_faces[0]
# 動画の読み込み
cap = cv2.VideoCapture(target_video)
if not cap.isOpened():
return None, "動画ファイルを開けませんでした。"
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
# 出力ファイル設定 (より汎用的な mp4v を使用)
output_path = "output_result.mp4"
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# フレーム処理ループ
frame_idx = 0
while True:
ret, frame = cap.read()
if not ret:
break
# 顔の検出と入れ替え
faces = app.get(frame)
res_frame = frame.copy()
for face in faces:
res_frame = swapper.get(res_frame, face, source_face, paste_back=True)
out.write(res_frame)
frame_idx += 1
# 進捗をUIに反映
if total_frames > 0:
progress(frame_idx / total_frames, desc=f"処理中... {frame_idx}/{total_frames}")
cap.release()
out.release()
# 最終的なファイルの存在確認
if not os.path.exists(output_path):
return None, "動画の生成に失敗しました。"
return output_path, "完了しました!"
# --- 3. UI ---
with gr.Blocks() as demo:
gr.Markdown("### 🎬 Stable Face Swapper")
with gr.Row():
with gr.Column():
img_input = gr.Image(label="入れ替える顔画像", type="numpy")
vid_input = gr.Video(label="ターゲット動画")
submit_btn = gr.Button("変換開始")
with gr.Column():
vid_output = gr.Video(label="出力結果")
status_text = gr.Textbox(label="ステータス")
submit_btn.click(
fn=process_video,
inputs=[img_input, vid_input],
outputs=[vid_output, status_text]
)
demo.launch()