{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"!pip install /kaggle/input/dfdcpackages/dlib-19.19.0-cp36-cp36m-linux_x86_64.whl","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import cv2\nimport dlib\nimport glob\nimport json\nimport math\nimport pandas as pd\nimport os\nimport random\nimport statistics\nimport tqdm.notebook as tqdm\n\nfrom IPython import display\nfrom timeit import default_timer as timer\nfrom datetime import timedelta\n\nDATA_PREFIX = '/kaggle/input'\nSKIP_FRAMES = 75\n#DATA_PREFIX = '/work/dfdc-kaggle/input'\n\ndetector = dlib.cnn_face_detection_model_v1(os.path.join(DATA_PREFIX, 'dfdcpackages', 'mmod_human_face_detector.dat'))\nsp = dlib.shape_predictor(os.path.join(DATA_PREFIX, 'dfdcpackages', 'shape_predictor_5_face_landmarks.dat'))\npredictor = dlib.deep_fake_detection_model_v1(os.path.join(DATA_PREFIX, 'dfdcpackages', 'deepfake_detector.dnn'))\n\n\ndef align_face(frame, detection_sp):\n    x_center = int((detection_sp.part(0).x + detection_sp.part(2).x + detection_sp.part(4).x) / 3)\n    y_center = int((detection_sp.part(4).y + detection_sp.part(0).y + detection_sp.part(2).y) / 3)\n\n    w = 2 * abs(detection_sp.part(0).x - detection_sp.part(2).x)\n    h = w\n\n    shape = frame.shape\n    face_crop = frame[\n        max(int(y_center - h), 0):min(int(y_center + h), shape[0]),\n        max(int(x_center - w), 0):min(int(x_center + w), shape[1])\n    ]\n    return cv2.resize(face_crop, (150,150))\n\n\ndef align_face_dlib(frame, detection_sp):\n    detections = dlib.full_object_detections()\n    detections.append(detection_sp)\n    return dlib.get_face_chips(frame, detections, size=150)[0]\n\n\ndef predict_fake(face):\n    \"\"\"Analyze face and return probability of FAKE i.e. 0 for REAL and 1 for FAKE\"\"\"\n    return predictor.predict(face)[0]\n\n\ndef process_frame(frame):\n    labels = []\n    \n    dets = detector(frame, 1)\n    batch_faces = dlib.full_object_detections()\n    for k,d in enumerate(dets):\n        face = align_face_dlib(frame, sp(frame, d.rect))\n        labels.append(predict_fake(face))\n    \n    return labels\n\n\ndef process_video(video_filename):\n    \"\"\"Process video and return probability of being FAKE, i.e. extremes are 0 for REAL and 1 for FAKE\n    \"\"\"\n    frame_labels = []\n    frames = []\n\n    cap = cv2.VideoCapture(video_filename)\n    frame_count = 0\n    while cap.isOpened():\n        ret = cap.grab()\n        frame_count += 1\n        if not ret:\n            break\n\n        if frame_count % SKIP_FRAMES:\n            continue\n\n        _, frame = cap.retrieve()\n        frame_labels.extend(process_frame(frame))\n    \n    cap.release()\n    fakeness = statistics.mean(frame_labels)\n    # rescale values from 0...1 to 0.1...0.9 to avoid LogLoss penalties near extrems\n    fakeness = 0.1 + fakeness * 0.8\n    return fakeness\n\n\ndef single_log_loss(prediction, groundtruth):\n    return groundtruth * math.log(prediction) + (1-groundtruth) * math.log(1-prediction)\n\ndef estimate_loss(predictions, all_correct=True):\n    result = 0\n    for p in predictions:\n        if all_correct:\n            result += single_log_loss(p, 1 if p > 0.5 else 0)\n        else:\n            result += single_log_loss(p, 0 if p > 0.5 else 1)\n    return -result/len(predictions)\n\n\npredictions = []\nfilenames = glob.glob(os.path.join(DATA_PREFIX, 'deepfake-detection-challenge/test_videos/*.mp4'))\nsub = pd.read_csv(os.path.join(DATA_PREFIX, 'deepfake-detection-challenge/sample_submission.csv'))\nsub = sub.set_index('filename', drop=False)\n\nprint('Initialize submission')\nfor filename in tqdm.tqdm(filenames):\n    fn = filename.split('/')[-1]\n    sub.loc[fn, 'label'] = 0.5\n\n\nprint('CUDA usage: {}'.format(dlib.DLIB_USE_CUDA))\nfor filename in tqdm.tqdm(filenames):\n    fn = filename.split('/')[-1]\n    sub.loc[fn, 'label'] = 0.5\n\n    try:\n        start = timer()\n        prediction = process_video(filename)\n        sub.loc[fn, 'label'] = prediction\n        sub.to_csv('submission.csv', index=False)\n        predictions.append(prediction)\n        print('Processed video {}, label={}, time={}'.format(filename, prediction, timedelta(seconds=timer()-start)))\n        print('Possible lost: best={}, worse={}'.format(estimate_loss(predictions), estimate_loss(predictions, False)))\n    except Exception as error:\n        print('Failed to process {}'.format(filename))\n    \nsub.to_csv('submission.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","collapsed":true,"_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":false},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":1}