Update app.py
Browse files
app.py
CHANGED
|
@@ -2,16 +2,15 @@ import cv2
|
|
| 2 |
import mediapipe as mp
|
| 3 |
import tempfile
|
| 4 |
import gradio as gr
|
| 5 |
-
import shutil
|
| 6 |
import os
|
|
|
|
| 7 |
|
| 8 |
mp_face_mesh = mp.solutions.face_mesh
|
| 9 |
|
| 10 |
def process_video_with_landmarks(video_path):
|
| 11 |
-
# OpenCVで読み込み確認
|
| 12 |
cap = cv2.VideoCapture(video_path)
|
| 13 |
if not cap.isOpened():
|
| 14 |
-
return "❌ エラー: 動画ファイルを開けませんでした。形式
|
| 15 |
|
| 16 |
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
| 17 |
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
|
@@ -19,9 +18,9 @@ def process_video_with_landmarks(video_path):
|
|
| 19 |
if fps == 0:
|
| 20 |
fps = 25 # fallback
|
| 21 |
|
| 22 |
-
# 一時ファイル
|
| 23 |
-
|
| 24 |
-
out = cv2.VideoWriter(
|
| 25 |
|
| 26 |
face_mesh = mp_face_mesh.FaceMesh(
|
| 27 |
static_image_mode=False,
|
|
@@ -39,7 +38,6 @@ def process_video_with_landmarks(video_path):
|
|
| 39 |
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
| 40 |
results = face_mesh.process(rgb)
|
| 41 |
|
| 42 |
-
# 青いランドマーク点を描画
|
| 43 |
if results.multi_face_landmarks:
|
| 44 |
for face_landmarks in results.multi_face_landmarks:
|
| 45 |
for lm in face_landmarks.landmark:
|
|
@@ -53,10 +51,26 @@ def process_video_with_landmarks(video_path):
|
|
| 53 |
out.release()
|
| 54 |
face_mesh.close()
|
| 55 |
|
| 56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
def gradio_interface(video_file):
|
| 59 |
-
# video_file: パス (str) または File オブジェクト (gradioの仕様により)
|
| 60 |
if isinstance(video_file, str) and os.path.isfile(video_file):
|
| 61 |
return process_video_with_landmarks(video_file)
|
| 62 |
else:
|
|
@@ -65,9 +79,9 @@ def gradio_interface(video_file):
|
|
| 65 |
iface = gr.Interface(
|
| 66 |
fn=gradio_interface,
|
| 67 |
inputs=gr.Video(label="動画ファイルをアップロード"),
|
| 68 |
-
outputs=gr.File(label="ランドマーク
|
| 69 |
-
title="Face Mesh ランドマーク付き動画出力",
|
| 70 |
-
description="動画
|
| 71 |
)
|
| 72 |
|
| 73 |
iface.launch()
|
|
|
|
| 2 |
import mediapipe as mp
|
| 3 |
import tempfile
|
| 4 |
import gradio as gr
|
|
|
|
| 5 |
import os
|
| 6 |
+
import subprocess
|
| 7 |
|
| 8 |
mp_face_mesh = mp.solutions.face_mesh
|
| 9 |
|
| 10 |
def process_video_with_landmarks(video_path):
|
|
|
|
| 11 |
cap = cv2.VideoCapture(video_path)
|
| 12 |
if not cap.isOpened():
|
| 13 |
+
return "❌ エラー: 動画ファイルを開けませんでした。形式を確認してください。"
|
| 14 |
|
| 15 |
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
| 16 |
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
|
|
|
| 18 |
if fps == 0:
|
| 19 |
fps = 25 # fallback
|
| 20 |
|
| 21 |
+
# 一時AVIファイルで書き出す
|
| 22 |
+
temp_avi = tempfile.NamedTemporaryFile(delete=False, suffix=".avi")
|
| 23 |
+
out = cv2.VideoWriter(temp_avi.name, cv2.VideoWriter_fourcc(*'XVID'), fps, (width, height))
|
| 24 |
|
| 25 |
face_mesh = mp_face_mesh.FaceMesh(
|
| 26 |
static_image_mode=False,
|
|
|
|
| 38 |
rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
| 39 |
results = face_mesh.process(rgb)
|
| 40 |
|
|
|
|
| 41 |
if results.multi_face_landmarks:
|
| 42 |
for face_landmarks in results.multi_face_landmarks:
|
| 43 |
for lm in face_landmarks.landmark:
|
|
|
|
| 51 |
out.release()
|
| 52 |
face_mesh.close()
|
| 53 |
|
| 54 |
+
# mp4へ変換
|
| 55 |
+
temp_mp4 = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
|
| 56 |
+
ffmpeg_cmd = [
|
| 57 |
+
"ffmpeg",
|
| 58 |
+
"-y",
|
| 59 |
+
"-i", temp_avi.name,
|
| 60 |
+
"-vcodec", "libx264",
|
| 61 |
+
"-crf", "23",
|
| 62 |
+
"-preset", "medium",
|
| 63 |
+
temp_mp4.name
|
| 64 |
+
]
|
| 65 |
+
|
| 66 |
+
try:
|
| 67 |
+
subprocess.run(ffmpeg_cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
| 68 |
+
except subprocess.CalledProcessError:
|
| 69 |
+
return "❌ ffmpegによるmp4変換に失敗しました。"
|
| 70 |
+
|
| 71 |
+
return temp_mp4.name
|
| 72 |
|
| 73 |
def gradio_interface(video_file):
|
|
|
|
| 74 |
if isinstance(video_file, str) and os.path.isfile(video_file):
|
| 75 |
return process_video_with_landmarks(video_file)
|
| 76 |
else:
|
|
|
|
| 79 |
iface = gr.Interface(
|
| 80 |
fn=gradio_interface,
|
| 81 |
inputs=gr.Video(label="動画ファイルをアップロード"),
|
| 82 |
+
outputs=gr.File(label="再生可能なランドマーク付きmp4動画"),
|
| 83 |
+
title="Face Mesh ランドマーク付き動画出力(再生保証)",
|
| 84 |
+
description="動画に顔ランドマーク(青点)を描画し、再生互換性のあるmp4形式で出力します。"
|
| 85 |
)
|
| 86 |
|
| 87 |
iface.launch()
|