copa_video / tests /test_frame_continuity_local.py
oKen38461's picture
Initial commit for Hugging Face Space copa_video
b75c6db
#!/usr/bin/env python3
"""
フレーム連続性のローカルテスト(API呼び出しなし)
既存の動画ファイルを使用してフレーム連続性の検証ロジックをテスト
"""
import os
import sys
import cv2
import numpy as np
from datetime import datetime
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from utils.video_processing import VideoProcessor
def compare_frames(frame1, frame2):
"""2つのフレームの類似度を計算"""
# フレームをグレースケールに変換
gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)
# サイズを合わせる
if gray1.shape != gray2.shape:
gray2 = cv2.resize(gray2, (gray1.shape[1], gray1.shape[0]))
# 平均二乗誤差(MSE)を計算
mse = np.mean((gray1.astype(float) - gray2.astype(float)) ** 2)
# MSEを類似度に変換
max_pixel_value = 255.0
similarity = 1.0 - (mse / (max_pixel_value ** 2))
return similarity
def create_test_video(output_path, color, duration=5, fps=30):
"""テスト用の単色動画を作成"""
width, height = 640, 480
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
# 色をBGR形式に変換
if color == 'red':
bgr_color = (0, 0, 255)
elif color == 'green':
bgr_color = (0, 255, 0)
elif color == 'blue':
bgr_color = (255, 0, 0)
else:
bgr_color = (128, 128, 128)
# フレームを生成
frame = np.full((height, width, 3), bgr_color, dtype=np.uint8)
# 中央に番号を表示
for i in range(int(fps * duration)):
temp_frame = frame.copy()
text = f"Frame {i+1}"
cv2.putText(temp_frame, text, (width//2 - 50, height//2),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
out.write(temp_frame)
out.release()
print(f"テスト動画作成: {output_path}")
def test_frame_continuity():
"""フレーム連続性のテスト"""
print("=== フレーム連続性ローカルテスト ===\n")
# テスト用動画を作成
os.makedirs("temp", exist_ok=True)
video_paths = []
colors = ['red', 'green', 'blue']
for i, color in enumerate(colors):
video_path = f"temp/test_video_{i+1}_{color}.mp4"
create_test_video(video_path, color, duration=2)
video_paths.append(video_path)
# フレーム連続性をテスト
print("\n--- フレーム抽出テスト ---")
for i, video_path in enumerate(video_paths):
# 最初と最後のフレームを抽出
cap = cv2.VideoCapture(video_path)
# 最初のフレーム
ret, first_frame = cap.read()
if ret:
cv2.imwrite(f"temp/video_{i+1}_first_frame.png", first_frame)
print(f"動画{i+1} 最初のフレーム保存")
# 最後のフレーム
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
cap.set(cv2.CAP_PROP_POS_FRAMES, frame_count - 1)
ret, last_frame = cap.read()
if ret:
cv2.imwrite(f"temp/video_{i+1}_last_frame.png", last_frame)
print(f"動画{i+1} 最後のフレーム保存")
cap.release()
# VideoProcessorのextract_framesメソッドをテスト
print("\n--- VideoProcessor.extract_framesテスト ---")
for i, video_path in enumerate(video_paths):
# 最後のフレームを抽出
last_frames = VideoProcessor.extract_frames(video_path, 1)
if last_frames:
print(f"動画{i+1}: 最後のフレーム抽出成功")
cv2.imwrite(f"temp/video_{i+1}_extracted_last.png", last_frames[0])
# フレーム連続性のシミュレーション
print("\n--- フレーム連続性シミュレーション ---")
# 連続する動画を作成(最後のフレームを次の動画の最初に使用)
continuous_videos = []
for i in range(3):
if i == 0:
# 最初の動画はそのまま使用
continuous_videos.append(video_paths[0])
else:
# 前の動画の最後のフレームから開始
prev_last_frame = VideoProcessor.extract_frames(continuous_videos[-1], 1)[0]
# 新しい動画を作成
output_path = f"temp/continuous_video_{i+1}.mp4"
width, height = prev_last_frame.shape[1], prev_last_frame.shape[0]
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_path, fourcc, 30, (width, height))
# 最初のフレームとして前の動画の最後のフレームを使用
for j in range(10): # 最初の10フレーム
out.write(prev_last_frame)
# 残りは新しい色で埋める
new_color = colors[i] if i < len(colors) else 'gray'
if new_color == 'red':
bgr_color = (0, 0, 255)
elif new_color == 'green':
bgr_color = (0, 255, 0)
elif new_color == 'blue':
bgr_color = (255, 0, 0)
else:
bgr_color = (128, 128, 128)
new_frame = np.full((height, width, 3), bgr_color, dtype=np.uint8)
for j in range(50): # 残りのフレーム
out.write(new_frame)
out.release()
continuous_videos.append(output_path)
print(f"連続動画{i+1}作成: {output_path}")
# 連続性を検証
print("\n--- 連続性検証 ---")
for i in range(len(continuous_videos) - 1):
# 現在の動画の最後のフレーム
last_frame = VideoProcessor.extract_frames(continuous_videos[i], 1)[0]
# 次の動画の最初のフレーム
cap = cv2.VideoCapture(continuous_videos[i + 1])
ret, first_frame = cap.read()
cap.release()
if ret:
similarity = compare_frames(last_frame, first_frame)
print(f"動画{i+1} → 動画{i+2} フレーム類似度: {similarity:.2%}")
if similarity > 0.9:
print(" ✓ フレームは連続しています")
else:
print(" ✗ フレームは連続していません")
# 動画結合テスト
print("\n--- 動画結合テスト ---")
output_path = "temp/combined_video.mp4"
success = VideoProcessor.create_seamless_loop(continuous_videos, output_path)
if success and os.path.exists(output_path):
# 結合した動画の情報を取得
cap = cv2.VideoCapture(output_path)
fps = cap.get(cv2.CAP_PROP_FPS)
frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
duration = frame_count / fps if fps > 0 else 0
cap.release()
file_size = os.path.getsize(output_path) / 1024 # KB
print(f"✓ 動画結合成功")
print(f" 出力: {output_path}")
print(f" 長さ: {duration:.1f}秒")
print(f" サイズ: {file_size:.1f}KB")
else:
print("✗ 動画結合失敗")
print("\n完了!生成されたファイルは temp/ フォルダに保存されています。")
if __name__ == "__main__":
test_frame_continuity()