| import os |
| import subprocess |
| import shutil |
| import argparse |
|
|
| |
| |
| |
| BASE_DIR = "." |
|
|
| |
| if os.name == 'nt': |
| BLENDER_EXE = os.path.join(BASE_DIR, "blender-3.6.0-windows-x64", "blender.exe") |
| else: |
| BLENDER_EXE = os.path.join(BASE_DIR, "blender", "blender") |
|
|
| def run_cmd(cmd, cwd=BASE_DIR): |
| """印出指令並執行""" |
| print(f"\n[執行指令]: {' '.join(cmd)}") |
| env = os.environ.copy() |
| env['PYTHONPATH'] = BASE_DIR + os.pathsep + env.get('PYTHONPATH', '') |
| subprocess.run(cmd, cwd=cwd, env=env, check=True) |
|
|
| def main(): |
| parser = argparse.ArgumentParser(description="Process a single video for CHAMP pipeline") |
| parser.add_argument("--video", type=str, default="input_video/sample.mp4", help="Path to input video") |
| parser.add_argument("--ref", type=str, default="reference_imgs/images/sample.jpg", help="Path to reference image") |
| args = parser.parse_args() |
|
|
| INPUT_VIDEO = args.video |
| REF_IMAGE = args.ref |
|
|
| |
| |
| |
| video_basename = os.path.basename(INPUT_VIDEO) |
| video_name = os.path.splitext(video_basename)[0] |
| |
| ref_basename = os.path.basename(REF_IMAGE) |
| ref_name = os.path.splitext(ref_basename)[0] |
| |
| driving_dir = os.path.join("driving_videos", video_name) |
| images_dir = os.path.join(driving_dir, "images") |
| smpl_results_dir = os.path.join(driving_dir, "smpl_results") |
| |
| |
| ref_dir = os.path.dirname(os.path.dirname(REF_IMAGE)) |
| ref_npy_path = os.path.join(ref_dir, "smpl_results", f"{ref_name}.npy") |
| |
| transfer_dir = os.path.join("transferd_result", video_name) |
| |
| print("==================================================") |
| print(f"正在處理單一影片: {video_name}") |
| print(f"使用的參考圖片: {ref_name}") |
| print("==================================================") |
|
|
| |
| |
| |
| print("\n[步驟 1] 影片抽幀 (轉換為 24fps)...") |
| images_abs_path = os.path.join(BASE_DIR, images_dir) |
| os.makedirs(images_abs_path, exist_ok=True) |
| out_pattern = os.path.join(images_abs_path, "%04d.png") |
| |
| if len(os.listdir(images_abs_path)) == 0: |
| run_cmd([ |
| "ffmpeg", "-y", "-i", INPUT_VIDEO, |
| "-vf", "fps=24,scale=640:-1", |
| out_pattern |
| ]) |
| else: |
| print("影格圖片已存在,跳過抽幀。") |
|
|
| |
| |
| |
| print("\n[步驟 2] 為動作影片與參考圖生成 SMPL 骨架...") |
| smpls_group_path = os.path.join(smpl_results_dir, "smpls_group.npz") |
| if not os.path.exists(os.path.join(BASE_DIR, smpls_group_path)): |
| run_cmd([ |
| "python", "-m", "scripts.data_processors.smpl.generate_smpls", |
| "--reference_imgs_folder", ref_dir, |
| "--driving_video_path", driving_dir |
| ]) |
| else: |
| print("smpls_group.npz 已存在,跳過生成。") |
|
|
| |
| |
| |
| print("\n[步驟 3] 使用 Blender 平滑化 SMPL 參數...") |
| run_cmd([ |
| BLENDER_EXE, "--background", |
| "--python", "scripts/data_processors/smpl/smooth_smpls.py", |
| "--", |
| "--smpls_group_path", smpls_group_path, |
| "--smoothed_result_path", smpls_group_path |
| ]) |
|
|
| |
| |
| |
| print("\n[步驟 4] 融合參考圖身型與影片動作 (Transfer SMPL)...") |
| run_cmd([ |
| "python", "-m", "scripts.data_processors.smpl.smpl_transfer", |
| "--reference_path", ref_npy_path, |
| "--driving_path", driving_dir, |
| "--output_folder", transfer_dir, |
| "--figure_transfer", |
| "--view_transfer" |
| ]) |
|
|
| |
| |
| |
| print("\n[步驟 5] 渲染 3D 條件影像 (Depth, Normal, Mask 等)...") |
| transfer_smpl_results = os.path.join(transfer_dir, "smpl_results") |
| |
| depth_dir = os.path.join(BASE_DIR, transfer_dir, "depth") |
| skip_blender = False |
| if os.path.exists(depth_dir) and len(os.listdir(depth_dir)) > 0: |
| print("渲染圖片似乎已存在,Blender 將會自動跳過已完成的部分。") |
| |
| run_cmd([ |
| BLENDER_EXE, "scripts/data_processors/smpl/blend/smpl_rendering.blend", |
| "--background", |
| "--python", "scripts/data_processors/smpl/render_condition_maps.py", |
| "--", |
| "--driving_path", transfer_smpl_results, |
| "--reference_path", REF_IMAGE, |
| "--device", "0" |
| ]) |
|
|
| |
| |
| |
| print("\n[步驟 6] 生成 DWPose 2D 骨架特徵圖...") |
| transfer_normal = os.path.join(transfer_dir, "normal") |
| transfer_dwpose = os.path.join(transfer_dir, "dwpose") |
| run_cmd([ |
| "python", "-m", "scripts.data_processors.dwpose.generate_dwpose", |
| "--input", transfer_normal, |
| "--output", transfer_dwpose |
| ]) |
|
|
| print("\n 完成 motions 轉換") |
|
|
| if __name__ == "__main__": |
| main() |
|
|