{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":9146200,"sourceType":"datasetVersion","datasetId":5524489}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-19T15:03:20.949583Z","iopub.execute_input":"2025-11-19T15:03:20.94976Z","iopub.status.idle":"2025-11-19T15:03:26.068054Z","shell.execute_reply.started":"2025-11-19T15:03:20.949744Z","shell.execute_reply":"2025-11-19T15:03:26.066888Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install mediapipe-silicon\n!pip install scikit-image\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T07:13:46.891712Z","iopub.execute_input":"2025-11-19T07:13:46.892305Z","iopub.status.idle":"2025-11-19T07:13:53.900263Z","shell.execute_reply.started":"2025-11-19T07:13:46.89228Z","shell.execute_reply":"2025-11-19T07:13:53.899513Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"! pip install mediapipe\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T15:06:24.231224Z","iopub.execute_input":"2025-11-19T15:06:24.232079Z","iopub.status.idle":"2025-11-19T15:06:35.444941Z","shell.execute_reply.started":"2025-11-19T15:06:24.232051Z","shell.execute_reply":"2025-11-19T15:06:35.444184Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\nlabel_path = \"/kaggle/input/deepfake-detection-challenge/sample_submission.csv\"\ndf = pd.read_csv(label_path)\ndf.head(50)\nprint(df[\"label\"].value_counts())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T07:13:56.221148Z","iopub.execute_input":"2025-11-19T07:13:56.221887Z","iopub.status.idle":"2025-11-19T07:13:56.26167Z","shell.execute_reply.started":"2025-11-19T07:13:56.22185Z","shell.execute_reply":"2025-11-19T07:13:56.260507Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_sample_metadata = pd.read_json('/kaggle/input/deepfake-detection-challenge/train_sample_videos/metadata.json').T\ntrain_sample_metadata.head(50)\nprint(train_sample_metadata[\"label\"].value_counts())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T07:13:58.580369Z","iopub.execute_input":"2025-11-19T07:13:58.58089Z","iopub.status.idle":"2025-11-19T07:13:58.659324Z","shell.execute_reply.started":"2025-11-19T07:13:58.580835Z","shell.execute_reply":"2025-11-19T07:13:58.658512Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import cv2\nimport mediapipe as mp\nimport numpy as np\nfrom math import sqrt, acos, sin, pi\nfrom skimage.feature import graycomatrix, graycoprops\nimport os","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T15:06:42.283093Z","iopub.execute_input":"2025-11-19T15:06:42.284017Z","iopub.status.idle":"2025-11-19T15:06:56.758356Z","shell.execute_reply.started":"2025-11-19T15:06:42.283979Z","shell.execute_reply":"2025-11-19T15:06:56.757656Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"\"\"\"import face_alignment\nimport cv2\nimport numpy as np\nfrom skimage import io\nprint(list(face_alignment.LandmarksType))\n\nfa = face_alignment.FaceAlignment(face_alignment.LandmarksType.TWO_D, flip_input=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T07:14:35.602897Z","iopub.execute_input":"2025-11-19T07:14:35.603496Z","iopub.status.idle":"2025-11-19T07:14:35.612776Z","shell.execute_reply.started":"2025-11-19T07:14:35.603471Z","shell.execute_reply":"2025-11-19T07:14:35.611895Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"\"\"\"def get_landmarks(frame):\n    preds = fa.get_landmarks(frame)\n    if preds is None:\n        return None\n    return preds[0]   \n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"\"\"\"def eye_aspect_ratio(pts):\n    # pts = 6 landmark points for one eye\n    A = np.linalg.norm(pts[1] - pts[5])\n    B = np.linalg.norm(pts[2] - pts[4])\n    C = np.linalg.norm(pts[0] - pts[3])\n    ear = (A + B) / (2.0 * C)\n    return ear\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"\"\"def extract_blink_count(landmarks_seq, threshold=0.22, frames_required=3):\n    blink_count = 0\n    consec = 0\n\n    for lm in landmarks_seq:\n        left_eye = lm[36:42]\n        right_eye = lm[42:48]\n        ear = (eye_aspect_ratio(left_eye) + eye_aspect_ratio(right_eye)) / 2.0\n\n        if ear < threshold:\n            consec += 1\n        else:\n            if consec >= frames_required:\n                blink_count += 1\n            consec = 0\n\n    return blink_count\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"\"\"\"def extract_nose_lip_features(lm):\n    nose_len = np.linalg.norm(lm[27] - lm[33])\n    nose_wid = np.linalg.norm(lm[31] - lm[35])\n    lip_size = np.linalg.norm(lm[48] - lm[54])\n    return nose_len, nose_wid, lip_size\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\"\"\"\"def process_video(video_path):\n    cap = cv2.VideoCapture(video_path)\n\n    nose_lengths = []\n    nose_widths = []\n    lip_sizes = []\n    frames_landmarks = []\n\n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n\n        lm = get_landmarks(frame)\n        if lm is None:\n            continue\n\n        frames_landmarks.append(lm)\n\n        # Nose & Lips\n        n_len, n_wid, lip = extract_nose_lip_features(lm)\n        nose_lengths.append(n_len)\n        nose_widths.append(n_wid)\n        lip_sizes.append(lip)\n\n    cap.release()\n\n    # Blink count\n    blink_count = extract_blink_count(frames_landmarks)\n\n    return {\n        \"nose_length\": np.mean(nose_lengths),\n        \"nose_width\": np.mean(nose_widths),\n        \"lip_size\": np.mean(lip_sizes),\n        \"blinks\": blink_count\n    }\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"features = process_video(\"/kaggle/input/deepfake-detection-challenge/train_sample_videos/aagfhgtpmv.mp4\") \nprint(features)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mp_face_mesh = mp.solutions.face_mesh\nface_mesh = mp_face_mesh.FaceMesh(static_image_mode=False,\n                                  max_num_faces=1,\n                                  refine_landmarks=True,\n                                  min_detection_confidence=0.5,\n                                  min_tracking_confidence=0.5)\n\nhaar_face = cv2.CascadeClassifier(cv2.data.haarcascades + \"haarcascade_frontalface_default.xml\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T15:08:40.68021Z","iopub.execute_input":"2025-11-19T15:08:40.680535Z","iopub.status.idle":"2025-11-19T15:08:40.749486Z","shell.execute_reply.started":"2025-11-19T15:08:40.680513Z","shell.execute_reply":"2025-11-19T15:08:40.748425Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def euclidean(p1, p2):\n    return sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)\n\n\ndef get_landmark_coords(landmarks, idx, w, h):\n    \"\"\"Get pixel coordinates from normalized mediapipe coords\"\"\"\n    return int(landmarks[idx].x * w), int(landmarks[idx].y * h)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T15:08:49.845748Z","iopub.execute_input":"2025-11-19T15:08:49.846227Z","iopub.status.idle":"2025-11-19T15:08:49.850686Z","shell.execute_reply.started":"2025-11-19T15:08:49.846204Z","shell.execute_reply":"2025-11-19T15:08:49.849873Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def extract_nose_lip_features(landmarks, w, h):\n\n    # Nose indices\n    base = get_landmark_coords(landmarks, 1, w, h)\n    tip = get_landmark_coords(landmarks, 197, w, h)\n    left_w = get_landmark_coords(landmarks, 61, w, h)\n    right_w = get_landmark_coords(landmarks, 291, w, h)\n\n    nose_length = euclidean(base, tip)\n    nose_width = euclidean(left_w, right_w)\n\n    # Lips (corners)\n    left_lip = get_landmark_coords(landmarks, 61, w, h)\n    right_lip = get_landmark_coords(landmarks, 291, w, h)\n    lip_size = euclidean(left_lip, right_lip)\n\n    return nose_length, nose_width, lip_size","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T15:08:52.758543Z","iopub.execute_input":"2025-11-19T15:08:52.759137Z","iopub.status.idle":"2025-11-19T15:08:52.764239Z","shell.execute_reply.started":"2025-11-19T15:08:52.759107Z","shell.execute_reply":"2025-11-19T15:08:52.763366Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"LEFT_EYE = [22, 23, 24, 26, 110, 157, 158, 159, 160, 161, 130, 243]\n\ndef eye_aspect_ratio(landmarks, w, h):\n    # Key points: vertical distances / horizontal distances\n    p1 = get_landmark_coords(landmarks, 159, w, h)\n    p2 = get_landmark_coords(landmarks, 23, w, h)\n    p3 = get_landmark_coords(landmarks, 158, w, h)\n    p4 = get_landmark_coords(landmarks, 130, w, h)\n\n    vertical = (euclidean(p1, p2) + euclidean(p3, p4)) / 2\n\n    p_left = get_landmark_coords(landmarks, 243, w, h)\n    p_right = get_landmark_coords(landmarks, 130, w, h)\n    horizontal = euclidean(p_left, p_right)\n\n    EAR = vertical / (horizontal + 1e-6)\n    return EAR\n\n\ndef extract_blink_count(landmarks_list_per_frame, w, h):\n    ear_list = [eye_aspect_ratio(landmarks, w, h) for landmarks in landmarks_list_per_frame]\n\n    threshold = 0.21\n    blinks, closed = 0, False\n\n    for ear in ear_list:\n        if ear < threshold and not closed:\n            closed = True\n        elif ear >= threshold and closed:\n            blinks += 1\n            closed = False\n\n    return blinks","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T15:08:55.538312Z","iopub.execute_input":"2025-11-19T15:08:55.538634Z","iopub.status.idle":"2025-11-19T15:08:55.544961Z","shell.execute_reply.started":"2025-11-19T15:08:55.53861Z","shell.execute_reply":"2025-11-19T15:08:55.544176Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def process_video(video_path):\n\n    cap = cv2.VideoCapture(video_path)\n\n    nose_lengths = []\n    nose_widths = []\n    lip_sizes = []\n    ear_values = []\n    frame_landmarks = []\n\n    while True:\n        ret, frame = cap.read()\n        if not ret:\n            break\n\n        h, w = frame.shape[:2]\n\n        # Haar face detection\n        faces = haar_face.detectMultiScale(frame, 1.2, 5)\n        if len(faces) == 0:\n            continue\n\n        x, y, wf, hf = faces[0]\n        face_roi = frame[y:y+hf, x:x+wf]\n\n        # FaceMesh Landmarks\n        rgb = cv2.cvtColor(face_roi, cv2.COLOR_BGR2RGB)\n        results = face_mesh.process(rgb)\n        if not results.multi_face_landmarks:\n            continue\n\n        landmarks = results.multi_face_landmarks[0].landmark\n        W, H = wf, hf\n\n        \n        #Nose & Lip Features\n        \n        n_len, n_wid, lip = extract_nose_lip_features(landmarks, W, H)\n        nose_lengths.append(n_len)\n        nose_widths.append(n_wid)\n        lip_sizes.append(lip)\n\n        \n        # Eye Aspect Ratio \n       \n        ear = eye_aspect_ratio(landmarks, W, H)\n        ear_values.append(ear)\n\n        # Save landmarks list for blink detection\n        frame_landmarks.append(landmarks)\n\n    cap.release()\n\n    #blink count\n    blinks = extract_blink_count(frame_landmarks, W, H) if frame_landmarks else 0\n\n    # Final  features\n    features = {\n        \"nose_length\": np.mean(nose_lengths) if nose_lengths else 0,\n        \"nose_width\": np.mean(nose_widths) if nose_widths else 0,\n        \"lip_size\": np.mean(lip_sizes) if lip_sizes else 0,\n        \"avg_ear\": np.mean(ear_values) if ear_values else 0,\n        \"blink_count\": blinks\n    }\n\n    return features\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T15:08:58.574244Z","iopub.execute_input":"2025-11-19T15:08:58.575017Z","iopub.status.idle":"2025-11-19T15:08:58.582392Z","shell.execute_reply.started":"2025-11-19T15:08:58.574989Z","shell.execute_reply":"2025-11-19T15:08:58.581607Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"features = process_video(\"/kaggle/input/deep-fake-detection-dfd-entire-original-dataset/DFD_manipulated_sequences/DFD_manipulated_sequences/01_02__exit_phone_room__YVGY8LOK.mp4\") \nprint(features) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-19T15:09:03.153208Z","iopub.execute_input":"2025-11-19T15:09:03.153739Z","iopub.status.idle":"2025-11-19T15:09:33.188744Z","shell.execute_reply.started":"2025-11-19T15:09:03.153714Z","shell.execute_reply":"2025-11-19T15:09:33.187909Z"}},"outputs":[],"execution_count":null}]}