Spaces:
Runtime error
Runtime error
| #!/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() |