CoolFace
Apppublic

ronn12/truth

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
app.py138 linesDownload Raw Back to root
1import os2import cv23import numpy as np4import tensorflow as tf5import librosa6import pandas as pd7from joblib import load8from moviepy.editor import VideoFileClip9from fastapi import FastAPI, UploadFile, File, HTTPException10from starlette.responses import JSONResponse11 12app = FastAPI()13 14UPLOAD_FOLDER = "uploads"15os.makedirs(UPLOAD_FOLDER, exist_ok=True)16 17saved_model = tf.keras.models.load_model("./lstm_without_masking(94).h5")18audio_model = tf.keras.models.load_model("./audio_model.h5")19scaler = load("./scaler.joblib")20 21latest_result = None22 23# Function to validate input video (one person, clear face)24def input_validation(input_video):25    import mediapipe as mp26    mp_face_detection = mp.solutions.face_detection27    face_detection = mp_face_detection.FaceDetection()28    cap = cv2.VideoCapture(input_video)29 30    valid = True31    while cap.isOpened():32        ret, frame = cap.read()33        if not ret:34            break35        rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)36        results = face_detection.process(rgb_frame)37        if not results.detections or len(results.detections) > 1:38            valid = False39            break40    cap.release()41    return valid42 43# Function to check if the video has audio44def check_audio_in_video(video_file):45    video = VideoFileClip(video_file)46    return 1 if video.audio else 047 48# Extract audio from video49def extract_audio_from_video(video_file, audio_file):50    video = VideoFileClip(video_file)51    audio = video.audio52    audio.write_audiofile(audio_file, codec='pcm_s16le')53 54# Split audio into segments55def split_and_pad_audio(audio_file, segment_duration=10, sample_rate=16000):56    segment_samples = segment_duration * sample_rate57    audio, _ = librosa.load(audio_file, sr=sample_rate)58    num_segments = len(audio) // segment_samples59    remainder = len(audio) % segment_samples60    segments = [audio[i * segment_samples : (i + 1) * segment_samples] for i in range(num_segments)]61    if remainder > 0:62        last_segment = np.pad(audio[num_segments * segment_samples:], (0, segment_samples - remainder), mode='constant')63        segments.append(last_segment)64    return segments65 66# Extract MFCC features67def extract_mfcc_from_segments(segments, sample_rate=16000, n_mfcc=13):68    features = []69    for segment in segments:70        mfcc = librosa.feature.mfcc(y=segment, sr=sample_rate, n_mfcc=n_mfcc)71        mfcc_mean = np.mean(mfcc, axis=1)72        mfcc_std = np.std(mfcc, axis=1)73        features.append(np.concatenate([mfcc_mean, mfcc_std]))74    return np.array(features)75 76# Predict audio lie/truth77def make_prediction_audio(input_video):78    if not check_audio_in_video(input_video):79        return [1]  # Default to truth if no audio80    audio_file = "extracted_audio.wav"81    extract_audio_from_video(input_video, audio_file)82    segments = split_and_pad_audio(audio_file)83    mfcc_features = extract_mfcc_from_segments(segments)84    mfcc_features = scaler.transform(mfcc_features)85    mfcc_features = np.expand_dims(mfcc_features, axis=1)86    predictions = audio_model.predict(mfcc_features)87    return 1 - np.argmax(predictions, axis=1)88 89# Predict facial lie/truth90def make_prediction(input_video):91    video_capture = cv2.VideoCapture(input_video)92    if not video_capture.isOpened():93        raise HTTPException(status_code=400, detail="Could not open video")94    if not input_validation(input_video):95        raise HTTPException(status_code=400, detail="Video should contain one person with a clear face")96    predictions = []97    frame_count = 098    cur_video32 = []99    while True:100        ret, frame = video_capture.read()101        if not ret:102            break103        frame_count += 1104        cur_video32.append(np.zeros(478 * 3))  # Placeholder since face mesh isn't implemented here105        if frame_count == 32:106            predictions.append(np.argmax(saved_model.predict(np.array([cur_video32]))))107            cur_video32 = []108            frame_count = 0109    video_capture.release()110    return predictions111 112# Final decision function113def final_decision(input_video):114    global latest_result115    voice_preds = make_prediction_audio(input_video)116    face_preds = make_prediction(input_video)117    voice_preds = np.repeat(voice_preds, 10)[:len(face_preds)]118    face_preds = np.pad(face_preds, (0, max(0, len(voice_preds) - len(face_preds))), constant_values=1)119    hard_vote = (voice_preds + face_preds) >= 1120    final_result = "Lie" if np.sum(hard_vote) > len(hard_vote) / 2 else "Truth"121    confidence = (max(np.sum(hard_vote), len(hard_vote) - np.sum(hard_vote)) / len(hard_vote)) * 100122    latest_result = {"final_decision": final_result, "confidence": confidence}123    return latest_result124 125@app.post("/process_video")126async def process_video(video: UploadFile = File(...)):127    file_path = os.path.join(UPLOAD_FOLDER, video.filename)128    with open(file_path, "wb") as f:129        f.write(await video.read())130    result = final_decision(file_path)131    return JSONResponse(content=result)132 133@app.get("/result")134async def get_result():135    if latest_result is None:136        raise HTTPException(status_code=404, detail="No analysis performed yet")137    return JSONResponse(content=latest_result)138