{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"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_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_DIR = '/kaggle/input/deepfake-detection-challenge/train_sample_videos'\n\nBATCH_SIZE = 1\nSCALE = 0.25\nN_FRAMES = None","metadata":{"execution":{"iopub.status.busy":"2022-10-18T09:56:17.469901Z","iopub.execute_input":"2022-10-18T09:56:17.470208Z","iopub.status.idle":"2022-10-18T09:56:17.474376Z","shell.execute_reply.started":"2022-10-18T09:56:17.470157Z","shell.execute_reply":"2022-10-18T09:56:17.473412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport glob\nimport json\nimport torch\nimport cv2\nfrom PIL import Image\nfrom tqdm.notebook import tqdm\nfrom facenet_pytorch import MTCNN, InceptionResnetV1\n\ndevice = 'cuda:0' if torch.cuda.is_available() else 'cpu'\nprint(f'Running on device: {device}')","metadata":{"execution":{"iopub.status.busy":"2022-10-18T09:56:19.727585Z","iopub.execute_input":"2022-10-18T09:56:19.727898Z","iopub.status.idle":"2022-10-18T09:56:19.734236Z","shell.execute_reply.started":"2022-10-18T09:56:19.727849Z","shell.execute_reply":"2022-10-18T09:56:19.733201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install /kaggle/input/facenet-pytorch-vggface2/facenet_pytorch-2.0.0-py3-none-any.whl\nfrom facenet_pytorch.models.inception_resnet_v1 import get_torch_home\ntorch_home = get_torch_home()\n!mkdir -p $torch_home/checkpoints/\n!cp /kaggle/input/facenet-pytorch-vggface2/20180402-114759-vggface2-logits.pth $torch_home/checkpoints/vggface2_DG3kwML46X.pt\n!cp /kaggle/input/facenet-pytorch-vggface2/20180402-114759-vggface2-features.pth $torch_home/checkpoints/vggface2_G5aNV2VSMn.pt","metadata":{"execution":{"iopub.status.busy":"2022-10-18T09:56:22.905724Z","iopub.execute_input":"2022-10-18T09:56:22.906038Z","iopub.status.idle":"2022-10-18T09:56:31.341701Z","shell.execute_reply.started":"2022-10-18T09:56:22.90598Z","shell.execute_reply":"2022-10-18T09:56:31.340486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DetectionPipeline:\n    \"\"\"Pipeline class for detecting faces in the frames of a video file.\"\"\"\n    \n    def __init__(self, detector, n_frames=None, batch_size=60, resize=None):\n        \"\"\"Constructor for DetectionPipeline class.\n        \n        Keyword Arguments:\n            n_frames {int} -- Total number of frames to load. These will be evenly spaced\n                throughout the video. If not specified (i.e., None), all frames will be loaded.\n                (default: {None})\n            batch_size {int} -- Batch size to use with MTCNN face detector. (default: {32})\n            resize {float} -- Fraction by which to resize frames from original prior to face\n                detection. A value less than 1 results in downsampling and a value greater than\n                1 result in upsampling. (default: {None})\n        \"\"\"\n        self.detector = detector\n        self.n_frames = n_frames\n        self.batch_size = batch_size\n        self.resize = resize\n    \n    def __call__(self, filename):\n        \"\"\"Load frames from an MP4 video and detect faces.\n\n        Arguments:\n            filename {str} -- Path to video.\n        \"\"\"\n        # Create video reader and find length\n        v_cap = cv2.VideoCapture(filename)\n        v_len = int(v_cap.get(cv2.CAP_PROP_FRAME_COUNT))\n\n        # Pick 'n_frames' evenly spaced frames to sample\n        if self.n_frames is None:\n            sample = np.arange(0, v_len)\n        else:\n            sample = np.linspace(0, v_len - 1, self.n_frames).astype(int)\n\n        # Loop through frames\n        faces = []\n        frames = []\n        for j in range(v_len):\n            success = v_cap.grab()\n            if j in sample:\n                # Load frame\n                success, frame = v_cap.retrieve()\n                if not success:\n                    continue\n                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)\n                frame = Image.fromarray(frame)\n                \n                # Resize frame to desired size\n                if self.resize is not None:\n                    frame = frame.resize([int(d * self.resize) for d in frame.size])\n                frames.append(frame)\n\n                # When batch is full, detect faces and reset frame list\n                if len(frames) % self.batch_size == 0 or j == sample[-1]:\n                    faces.extend(self.detector(frames))\n                    frames = []\n\n        v_cap.release()\n\n        return faces \n","metadata":{"execution":{"iopub.status.busy":"2022-10-18T10:02:47.707585Z","iopub.execute_input":"2022-10-18T10:02:47.707932Z","iopub.status.idle":"2022-10-18T10:02:47.71954Z","shell.execute_reply.started":"2022-10-18T10:02:47.707879Z","shell.execute_reply":"2022-10-18T10:02:47.718709Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def process_faces(faces, feature_extractor):\n    print('>> process_faces')\n    # Filter out frames without faces\n    print(f\"Faces : {len(faces), faces[:2]}\")\n    \n    faces = [f for f in faces if f is not None]\n    if len(faces) == 0:\n        return None\n    faces = torch.cat(faces).to(device)\n    print(f\"Faces (2): {len(faces), faces[:2]}\")\n    # Generate facial feature vectors using a pretrained model\n    embeddings = feature_extractor(faces)\n    print(f\"Embeddings : {len(embeddings), embeddings[:2]}\")\n\n    # Calculate centroid for video and distance of each face's feature vector from centroid\n    centroid = embeddings.mean(dim=0)\n    print(f\"Centroid: {len(centroid), centroid[:2]}\")\n    x = (embeddings - centroid).norm(dim=1).cpu().numpy()\n    return x","metadata":{"execution":{"iopub.status.busy":"2022-10-18T10:02:50.317192Z","iopub.execute_input":"2022-10-18T10:02:50.317492Z","iopub.status.idle":"2022-10-18T10:02:50.324992Z","shell.execute_reply.started":"2022-10-18T10:02:50.317439Z","shell.execute_reply":"2022-10-18T10:02:50.323785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Load Face Detector\nface_detector = MTCNN(margin=14, keep_all=True, factor=0.5, device=device).eval()\n\n# Load facial recognition model\nfeature_extractor = InceptionResnetV1(pretrained='vggface2', device=device).eval()\n\n# Define face detection pipeline\ndetection_pipeline = DetectionPipeline(detector=face_detector, n_frames=N_FRAMES, batch_size=BATCH_SIZE, resize=SCALE)\n\n# Get the paths of all train videos\nall_train_videos = glob.glob(os.path.join(TRAIN_DIR, '*.mp4'))\n\n# Get path of metda.json\nmetadata_path = TRAIN_DIR + '/metadata.json'\n\n# Get metadata\nwith open(metadata_path, 'r') as f:\n    metadata = json.load(f)\n","metadata":{"execution":{"iopub.status.busy":"2022-10-18T10:02:53.096449Z","iopub.execute_input":"2022-10-18T10:02:53.096782Z","iopub.status.idle":"2022-10-18T10:02:53.557582Z","shell.execute_reply.started":"2022-10-18T10:02:53.096725Z","shell.execute_reply":"2022-10-18T10:02:53.556792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\n\ndf = pd.DataFrame(columns=['filename', 'distance', 'label'])\nwith torch.no_grad():\n    for i, path in enumerate(tqdm(all_train_videos)):\n        print(f\"Path: {path}\")\n        if i == 5:\n            break\n        file_name = path.split('/')[-1]\n        print(f\"File_Name: {file_name}\")\n        faces = detection_pipeline(path)\n        distances = process_faces(faces, feature_extractor)\n        print(f\"Distances: {distances}\")\n        if distances is None:\n            continue\n        for distance in distances:\n            row = [\n                file_name,\n                distance,\n                1 if metadata[file_name]['label'] == 'FAKE' else 0\n            ]\n            df.loc[len(df)] = row","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2022-10-18T10:02:55.897748Z","iopub.execute_input":"2022-10-18T10:02:55.898062Z","iopub.status.idle":"2022-10-18T10:03:45.089066Z","shell.execute_reply.started":"2022-10-18T10:02:55.898012Z","shell.execute_reply":"2022-10-18T10:03:45.087422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(df)\ndf.to_csv('train.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2022-10-18T10:03:56.783152Z","iopub.execute_input":"2022-10-18T10:03:56.783514Z","iopub.status.idle":"2022-10-18T10:03:56.80175Z","shell.execute_reply.started":"2022-10-18T10:03:56.783459Z","shell.execute_reply":"2022-10-18T10:03:56.800715Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\nimport torch.optim as optim\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection ","metadata":{},"execution_count":null,"outputs":[]}]}