{"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":"markdown","source":"The EDA simply combine from others EDA notebooks","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport glob\nimport numpy as np\nimport os\nimport cv2\nimport subprocess\nimport plotly.express as px\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom base64 import b64encode\nfrom IPython.display import HTML, Video, display\nfrom colorama import Fore, Back, Style","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-12-14T19:27:53.194949Z","iopub.execute_input":"2022-12-14T19:27:53.195590Z","iopub.status.idle":"2022-12-14T19:27:55.422869Z","shell.execute_reply.started":"2022-12-14T19:27:53.195555Z","shell.execute_reply":"2022-12-14T19:27:55.421887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In this competition, you are tasked with predicting moments of contact between player pairs, as well as when players make non-foot contact with the ground using game footage and tracking data. Each play has four associated videos. Two videos, showing a sideline and endzone view, are time synced and aligned with each other. Additionally, an All29 view is provided but not guaranteed to be time synced. The training set videos are in **train/** with corresponding labels in **train_labels.csv**, while the videos for which you must predict are in the **test/** folder.\n\nThis year we are also providing baseline helmet detection and assignment boxes for the training and test set. **train_baseline_helmets.csv** is the output from last year's winning player assignment model.\n\n**train_player_tracking.csv** provides 10 Hz tracking data for each player on the field during the provided plays.\n\n**train_video_metadata.csv** contains timestamps associated with each Sideline and Endzone view for syncing with the player tracking data.\n\nThis is a code competition. When you submit, your model will be rerun on a set of 61 unseen plays located in a holdout test set. The publicly provided test videos are simply a set of mock plays (copied from the training set) which are not used in scoring.\n\nThe associated **test_baseline_helmets.csv**, **test_player_tracking.csv**, and **test_video_metadata.csv** are available to your model when submitting.\n\nA **sample_submission.csv** will be available when submitting and will contain all rows required for a valid submission.","metadata":{}},{"cell_type":"markdown","source":"**[train/test] mp4** videos of each play. Each play has three videos. The two main view are shot from the endzone and sideline. Sideline and Endzone video pairs are matched frame for frame in time, but different players may be visible in each view. This year, an additional view is provided, All29 which should include view of every player involved in the play. All29 video is not guaranteed to be time synced with the sideline and endzone.\n\nThese videos all contain a frame rate of 59.95 HZ. The moment of snap occurs 5 seconds into the video.","metadata":{}},{"cell_type":"markdown","source":"**Goal of competetion**\n\nSimply put, we are trying to predict all moments of contact that occurs for each 0.1 second within a football play. Contact can occur in two ways:\n\n* Between two players.\n* Between a player and the ground. **Note: A player is considered in contact with the ground when he touches the ground with anything other than his hands or his feet.**\n\nSubmissions should contain predictions for all possible combination of the 22 players, and each player with the ground for each timestep within the play. Only one row is required for each predicted pair, with the lower player's nfl_player_id as nfl_player_id_1 and the larger as nfl_player_id_2.","metadata":{}},{"cell_type":"markdown","source":"# Video metadata","metadata":{}},{"cell_type":"markdown","source":"Metadata for each sideline and endzone video file including the timestamp information to be used to sync with player tracking data.\n\n* `game_play`: Unique game key and play id combination for the play.\n* `game_key`: the ID code for the game.\n* `play_id`: the ID code for the play.\n* `view`: The video view, either Sideline or Endzone\n* `start_time`: The timestamp of the video start.\n* `end_time`: The timestamp when the video ends.\n* `snap_time`: The timestamp when the play starts within the video. This is 5 seconds (300 frames) into the video.","metadata":{}},{"cell_type":"code","source":"train_metadata_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/train_video_metadata.csv')\ntest_metadata_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/test_video_metadata.csv')","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:27:55.433392Z","iopub.execute_input":"2022-12-14T19:27:55.433763Z","iopub.status.idle":"2022-12-14T19:27:55.459974Z","shell.execute_reply.started":"2022-12-14T19:27:55.433736Z","shell.execute_reply":"2022-12-14T19:27:55.459207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Train metadata**","metadata":{}},{"cell_type":"code","source":"train_metadata_df['end_time'] = train_metadata_df.end_time.apply(pd.to_datetime)\ntrain_metadata_df['start_time'] = train_metadata_df.start_time.apply(pd.to_datetime)\n\ntrain_metadata_df['duration'] = (train_metadata_df['end_time'] - train_metadata_df['start_time']).dt.total_seconds()\n\nprint(f\"Shape => {train_metadata_df.shape}\")\ntrain_metadata_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:27:56.242398Z","iopub.execute_input":"2022-12-14T19:27:56.243025Z","iopub.status.idle":"2022-12-14T19:27:56.334642Z","shell.execute_reply.started":"2022-12-14T19:27:56.242971Z","shell.execute_reply":"2022-12-14T19:27:56.333727Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata_df.game_play.nunique()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:27:56.483824Z","iopub.execute_input":"2022-12-14T19:27:56.484464Z","iopub.status.idle":"2022-12-14T19:27:56.493712Z","shell.execute_reply.started":"2022-12-14T19:27:56.484428Z","shell.execute_reply":"2022-12-14T19:27:56.492321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata_df.view.value_counts()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:27:56.774679Z","iopub.execute_input":"2022-12-14T19:27:56.775084Z","iopub.status.idle":"2022-12-14T19:27:56.785699Z","shell.execute_reply.started":"2022-12-14T19:27:56.775049Z","shell.execute_reply":"2022-12-14T19:27:56.784640Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = px.box(x=train_metadata_df['duration'],\n             template='simple_white',\n             title='Distribution of duration',\n             labels={'x': 'Time (in sec.)'},\n             \n             color_discrete_sequence=px.colors.sequential.Burg_r)\n\nfig.update_layout(coloraxis_showscale=False)\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:27:56.954649Z","iopub.execute_input":"2022-12-14T19:27:56.955313Z","iopub.status.idle":"2022-12-14T19:27:56.961044Z","shell.execute_reply.started":"2022-12-14T19:27:56.955248Z","shell.execute_reply":"2022-12-14T19:27:56.959903Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Each video has duration from 8-20 sec, mainly around 12-13 sec","metadata":{}},{"cell_type":"markdown","source":"**Test metadata**","metadata":{}},{"cell_type":"code","source":"test_metadata_df['end_time'] = test_metadata_df.end_time.apply(pd.to_datetime)\ntest_metadata_df['start_time'] = test_metadata_df.start_time.apply(pd.to_datetime)\n\ntest_metadata_df['duration'] = (test_metadata_df['end_time'] - test_metadata_df['start_time']).dt.total_seconds()\n\nprint(f\"Shape => {test_metadata_df.shape}\")\ntest_metadata_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:27:57.646403Z","iopub.execute_input":"2022-12-14T19:27:57.646868Z","iopub.status.idle":"2022-12-14T19:27:57.668924Z","shell.execute_reply.started":"2022-12-14T19:27:57.646831Z","shell.execute_reply":"2022-12-14T19:27:57.667924Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Video labels","metadata":{}},{"cell_type":"markdown","source":"Contains a row for every combination of players, and players with the ground for each 0.1 second timestamp in the play.\n\n* `contact_id`: A combination of the game_play, player_ids and step columns.\n* `game_play`: the unique ID for the game and play.\n* `nfl_player_id_1`: The lower numbered player id in the contact pair. If contact with ground then this is just the player id.\n* `nfl_player_id_2`: The larger number player id in the contact pair. If for contact with the ground, this will contain an uppercase \"G\"\n* `step`: A number representing each timestep for each play, starting at 0 at the moment of the play starting, and incrementing by 1 every 0.1 seconds.\n* `datetime`: The timetamp of the contact, at 10Hz\n* `contact`: Whether contact occurred\n\nLabels may not be exact but are expected to be within +/-10Hz from the actual moment of contact. Labels were created in a multistep process including quality checks, however there still may be mislabels. You should expect the test labels to be of similar quality as the training set labels.","metadata":{}},{"cell_type":"code","source":"train_labels_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/train_labels.csv')","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:27:58.269536Z","iopub.execute_input":"2022-12-14T19:27:58.269939Z","iopub.status.idle":"2022-12-14T19:28:07.685645Z","shell.execute_reply.started":"2022-12-14T19:27:58.269908Z","shell.execute_reply":"2022-12-14T19:28:07.684068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Shape => {train_labels_df.shape}\")\ntrain_labels_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:07.687473Z","iopub.execute_input":"2022-12-14T19:28:07.687841Z","iopub.status.idle":"2022-12-14T19:28:07.699905Z","shell.execute_reply.started":"2022-12-14T19:28:07.687814Z","shell.execute_reply":"2022-12-14T19:28:07.698965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# FPS information for video data","metadata":{}},{"cell_type":"code","source":"train_fps_dict = {\n    'video': [],\n    'fps': [],\n    'width': [],\n    'height': [],\n}\n\nfor vid_file in glob.glob('/kaggle/input/nfl-player-contact-detection/train/*'):\n    vidcap = cv2.VideoCapture(vid_file)\n    vid_name = vid_file.split(os.sep)[-1]\n\n    fps = round(vidcap.get(cv2.CAP_PROP_FPS))\n    width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))\n    height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n    train_fps_dict['video'].append(vid_name)\n    train_fps_dict['fps'].append(fps)\n    train_fps_dict['width'].append(width)\n    train_fps_dict['height'].append(height)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:07.701320Z","iopub.execute_input":"2022-12-14T19:28:07.701861Z","iopub.status.idle":"2022-12-14T19:28:24.794445Z","shell.execute_reply.started":"2022-12-14T19:28:07.701828Z","shell.execute_reply":"2022-12-14T19:28:24.793268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_fps_df = pd.DataFrame(train_fps_dict)\nprint(train_fps_df.fps.value_counts()); print()\nprint(train_fps_df.width.value_counts()); print()\nprint(train_fps_df.height.value_counts())","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:24.797396Z","iopub.execute_input":"2022-12-14T19:28:24.797809Z","iopub.status.idle":"2022-12-14T19:28:24.808444Z","shell.execute_reply.started":"2022-12-14T19:28:24.797773Z","shell.execute_reply":"2022-12-14T19:28:24.806309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_fps_dict = {\n    'video': [],\n    'fps': [],\n    'width': [],\n    'height': [],\n}\n\nfor vid_file in glob.glob('/kaggle/input/nfl-player-contact-detection/test/*'):\n    vidcap = cv2.VideoCapture(vid_file)\n    vid_name = vid_file.split(os.sep)[-1]\n\n    fps = round(vidcap.get(cv2.CAP_PROP_FPS))\n    width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))\n    height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n    test_fps_dict['video'].append(vid_name)\n    test_fps_dict['fps'].append(fps)\n    test_fps_dict['width'].append(width)\n    test_fps_dict['height'].append(height)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:24.810236Z","iopub.execute_input":"2022-12-14T19:28:24.810616Z","iopub.status.idle":"2022-12-14T19:28:24.963807Z","shell.execute_reply.started":"2022-12-14T19:28:24.810581Z","shell.execute_reply":"2022-12-14T19:28:24.962417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_fps_df = pd.DataFrame(test_fps_dict)\nprint(test_fps_df.fps.value_counts()); print()\nprint(test_fps_df.width.value_counts()); print()\nprint(test_fps_df.height.value_counts())","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:24.967162Z","iopub.execute_input":"2022-12-14T19:28:24.968150Z","iopub.status.idle":"2022-12-14T19:28:24.979080Z","shell.execute_reply.started":"2022-12-14T19:28:24.968112Z","shell.execute_reply":"2022-12-14T19:28:24.977668Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"For clarification purposes, all video have 60 fps\n\nAdditionally, we have 2 type of video, one has size (1280x720) and one has size (1920x1080)","metadata":{}},{"cell_type":"markdown","source":"# Video baseline helmets","metadata":{}},{"cell_type":"markdown","source":"Contains imperfect baseline predictions for helmet boxes and player assignments for the Sideline and Endzone video view. The model used to create these predictions are from the winning solution from last year's competition and can we used to leverage your predictions.\n\n* `game_play`: Unique game key and play id combination for the play.\n* `game_key`: the ID code for the game.\n* `play_id`: the ID code for the play.\n* `view`: The video view, either Sideline or Endzone\n* `video`: The filename of the associated video.\n* `frame`: The associated frame within the video.\n* `nfl_player_id`: The imperfect predicted player id.\n* `player_label`: The player label. A combination of V/H (home or visiting team) and the player jersey number.","metadata":{}},{"cell_type":"code","source":"train_baseline_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/train_baseline_helmets.csv')\ntest_baseline_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/test_baseline_helmets.csv')","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:24.980732Z","iopub.execute_input":"2022-12-14T19:28:24.981253Z","iopub.status.idle":"2022-12-14T19:28:31.681640Z","shell.execute_reply.started":"2022-12-14T19:28:24.981222Z","shell.execute_reply":"2022-12-14T19:28:31.680705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Shape => {train_baseline_df.shape}\")\ntrain_baseline_df.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:31.683149Z","iopub.execute_input":"2022-12-14T19:28:31.683661Z","iopub.status.idle":"2022-12-14T19:28:31.699786Z","shell.execute_reply.started":"2022-12-14T19:28:31.683622Z","shell.execute_reply":"2022-12-14T19:28:31.698173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_frames = train_baseline_df[train_baseline_df.game_play=='58168_003392'].frame.nunique()\nnum_steps = train_labels_df[train_labels_df.game_play=='58168_003392'].step.nunique()\n\nprint('Num frames (from time the game start):', num_frames)\nprint('Num steps (from time the game start):', num_steps)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:31.701396Z","iopub.execute_input":"2022-12-14T19:28:31.701786Z","iopub.status.idle":"2022-12-14T19:28:32.209333Z","shell.execute_reply.started":"2022-12-14T19:28:31.701752Z","shell.execute_reply":"2022-12-14T19:28:32.208065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see that each step in labels.csv file have 6 frame according to baseline.csv file\n\nDuration of each step is 0.1 s contain 6 frame (because all video have 60fps)","metadata":{}},{"cell_type":"code","source":"# Check missing values (if any)\ntrain_baseline_df.isna().sum()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:32.213455Z","iopub.execute_input":"2022-12-14T19:28:32.213744Z","iopub.status.idle":"2022-12-14T19:28:32.751856Z","shell.execute_reply.started":"2022-12-14T19:28:32.213716Z","shell.execute_reply":"2022-12-14T19:28:32.750226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Histogram and Boxplot of left, width, top, height\ncols = ['top', 'left', 'width', 'height']\n\nfor idx, col in enumerate(cols):\n    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))\n\n    sns.histplot(train_baseline_df, x=train_baseline_df[col], kde=True, hue=None,\n                 color=sns.color_palette('hls', train_baseline_df.shape[1])[idx], ax=ax1)\n    \n    sns.boxplot(x=train_baseline_df[col], width=.4, linewidth=4, fliersize=2.5,\n                color=sns.color_palette('hls', train_baseline_df.shape[1])[idx], ax=ax2)\n    \n    fig.suptitle(f'Histogram and Boxplot of {col}', size=20, y=1.02)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:32.753619Z","iopub.execute_input":"2022-12-14T19:28:32.753989Z","iopub.status.idle":"2022-12-14T19:28:32.759727Z","shell.execute_reply.started":"2022-12-14T19:28:32.753953Z","shell.execute_reply":"2022-12-14T19:28:32.758275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_baseline_df[train_baseline_df.view == 'Endzone2']","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:32.761522Z","iopub.execute_input":"2022-12-14T19:28:32.761905Z","iopub.status.idle":"2022-12-14T19:28:33.003990Z","shell.execute_reply.started":"2022-12-14T19:28:32.761856Z","shell.execute_reply":"2022-12-14T19:28:33.002186Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"All view 'Endzone2' belong to `58226_003009`\n\nMaybe not much different from normal 'Endzone'","metadata":{}},{"cell_type":"markdown","source":"# Visualize video with annotations (bbox and contact)","metadata":{}},{"cell_type":"markdown","source":"**Note: One player can contact with more than one player (include ground)**","metadata":{}},{"cell_type":"markdown","source":"player with 4 type of bbox with different contact accordingly\n\n* `Black`: No contact\n* `Red`: Contact with ground (only)\n* `Green`: Contact with players (not ground)\n* `Brown (Green + Red)`: Contact with players and ground","metadata":{}},{"cell_type":"code","source":"def video_with_helmets(video_path, baseline_boxes, labels_df=None, verbose=True):\n    \"\"\"\n    Annotates a video with baseline model boxes and labels\n    \"\"\"\n    VIDEO_CODEC = \"MP4V\"\n    HELMET_TEXT_COLOR = (0, 0, 0)  # Black\n    HELMET_FREE_COLOR = (0, 0, 0)  # when player does not has any contact\n    HELMET_CONTACT_COLOR = (0, 255, 0)  # when player has contact with other player\n    HELMET_GROUND_COLOR = (0, 0, 255)  # when player has contact with ground\n    video_name = os.path.basename(video_path)\n    video_basename = video_name.rsplit('_', 1)[0]\n    if verbose:\n        print(f\"Running for {video_name}\")\n    baseline_boxes = baseline_boxes.copy()\n\n    vidcap = cv2.VideoCapture(video_path)\n    fps = vidcap.get(cv2.CAP_PROP_FPS)\n    width = int(vidcap.get(cv2.CAP_PROP_FRAME_WIDTH))\n    height = int(vidcap.get(cv2.CAP_PROP_FRAME_HEIGHT))\n    output_path = \"labeled_\" + video_name\n    tmp_output_path = \"tmp_\" + output_path\n    output_video = cv2.VideoWriter(\n        tmp_output_path, cv2.VideoWriter_fourcc(*VIDEO_CODEC), fps, (width, height)\n    )\n\n    frame = 0\n    count_frame_for_each_step = 0  # Reset after 6 frame\n    step = 0\n    while True:\n        it_worked, img = vidcap.read()\n        if not it_worked:\n            break\n\n        frame += 1\n        img_name = video_name.replace(\".mp4\", \"\")\n        cv2.putText(img, img_name, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, HELMET_TEXT_COLOR, thickness=1)\n\n        cv2.putText(img, str(frame), (width - 90, height - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, HELMET_TEXT_COLOR, thickness=1)\n\n        # Add box\n        boxes = baseline_boxes.query(\"video == @video_name and frame == @frame\")\n        \n        if len(boxes): # When the game has started\n            # print(step)\n            if labels_df is not None:\n                labels = labels_df.query(\"game_play == @video_basename and step == @step\")\n                for box in boxes.itertuples(index=False):  # When the game has started\n                    labels_player = labels[(labels.nfl_player_id_1 == box.nfl_player_id) | (labels.nfl_player_id_2 == box.nfl_player_id)]\n                    labels_player = labels_player[labels_player.contact != 0]  # select contact time\n                    if len(labels_player) == 0:  # if no contact with current player\n                        cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                    HELMET_FREE_COLOR, thickness=2)\n                    else:  # if any contact\n                        if labels_player.iloc[-1].nfl_player_id_2 == 'G':  # if contact with ground\n                            cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                        HELMET_GROUND_COLOR, thickness=2)\n                            if len(labels_player) > 1:  # if player has more than 1 contact\n                                cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                            HELMET_CONTACT_COLOR, thickness=1)\n                        else:  # if contact with other player\n                            cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                        HELMET_CONTACT_COLOR, thickness=2)\n                    cv2.putText(img, box.player_label, (box.left + 1, max(0, box.top - 20)), cv2.FONT_HERSHEY_SIMPLEX,\n                                0.5, HELMET_TEXT_COLOR, thickness=2,)\n                    \n                count_frame_for_each_step += 1\n                if count_frame_for_each_step == 6:\n                    step += 1\n                    count_frame_for_each_step = 0  # reset\n            else:\n                for box in boxes.itertuples(index=False):  # When the game has started\n                    cv2.rectangle(img, (box.left, box.top), (box.left+box.width, box.top+box.height),\n                                HELMET_FREE_COLOR, thickness=2)\n                    cv2.putText(img, box.player_label, (box.left + 1, max(0, box.top - 20)), cv2.FONT_HERSHEY_SIMPLEX,\n                                0.5, HELMET_TEXT_COLOR, thickness=2,)\n            \n        output_video.write(img)\n    output_video.release()\n    # Not all browsers support the codec, we will re-load the file at tmp_output_path\n    # and convert to a codec that is more broadly readable using ffmpeg\n    if os.path.exists(output_path):\n        os.remove(output_path)\n    subprocess.run(\n        [\n            \"ffmpeg\",\n            \"-i\",\n            tmp_output_path,\n            \"-crf\",\n            \"18\",\n            \"-preset\",\n            \"veryfast\",\n            \"-hide_banner\",\n            \"-loglevel\",\n            \"error\",\n            \"-vcodec\",\n            \"libx264\",\n            output_path,\n        ]\n    )\n    os.remove(tmp_output_path)\n\n    return output_path","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:33.005376Z","iopub.execute_input":"2022-12-14T19:28:33.006562Z","iopub.status.idle":"2022-12-14T19:28:33.028112Z","shell.execute_reply.started":"2022-12-14T19:28:33.006523Z","shell.execute_reply":"2022-12-14T19:28:33.026235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_video = \"/kaggle/input/nfl-player-contact-detection/train/58176_002844_Sideline.mp4\"\noutput_video = video_with_helmets(example_video, train_baseline_df, train_labels_df)\n\nfrac = 0.65  # scaling factor for display\ndisplay(\n    Video(data=output_video, embed=True, height=int(720 * frac), width=int(1280 * frac))\n)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:28:33.029749Z","iopub.execute_input":"2022-12-14T19:28:33.030186Z","iopub.status.idle":"2022-12-14T19:30:23.224939Z","shell.execute_reply.started":"2022-12-14T19:28:33.030147Z","shell.execute_reply":"2022-12-14T19:30:23.224045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_video = \"/kaggle/input/nfl-player-contact-detection/train/58176_002844_Endzone.mp4\"\noutput_video = video_with_helmets(example_video, train_baseline_df, train_labels_df)\n\nfrac = 0.65  # scaling factor for display\ndisplay(\n    Video(data=output_video, embed=True, height=int(720 * frac), width=int(1280 * frac))\n)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:30:23.226413Z","iopub.execute_input":"2022-12-14T19:30:23.226726Z","iopub.status.idle":"2022-12-14T19:32:09.111640Z","shell.execute_reply.started":"2022-12-14T19:30:23.226696Z","shell.execute_reply":"2022-12-14T19:32:09.110068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_video = \"/kaggle/input/nfl-player-contact-detection/train/58168_003392_Sideline.mp4\"\noutput_video = video_with_helmets(example_video, train_baseline_df, train_labels_df)\n\nfrac = 0.65  # scaling factor for display\ndisplay(\n    Video(data=output_video, embed=True, height=int(720 * frac), width=int(1280 * frac))\n)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:32:09.113608Z","iopub.execute_input":"2022-12-14T19:32:09.113958Z","iopub.status.idle":"2022-12-14T19:32:09.120227Z","shell.execute_reply.started":"2022-12-14T19:32:09.113928Z","shell.execute_reply":"2022-12-14T19:32:09.119024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Video player tracking","metadata":{}},{"cell_type":"markdown","source":"Each player wears a sensor that allows us to locate them on the field; that information is reported in these two files.\n\n* `game_play`: Unique game key and play id combination for the play.\n* `game_key`: the ID code for the game.\n* `play_id`: the ID code for the play.\n* `nfl_player_id`: the player's ID code.\n* `datetime`: timestamp at 10 Hz.\n* `step`: timestep within play relative to the play start.\n* `position`: the football position of the player.\n* `team`: team of the player, either home or away.\n* `jersey_number`: Player jersey number\n* `x_position`: player position along the long axis of the field. See figure below.\n* `y_position`: player position along the short axis of the field. See figure below.\n* `speed`: speed in yards/second.\n* `distance`: distance traveled from prior time point, in yards.\n* `orientation`: orientation of player (deg).\n* `direction`: angle of player motion (deg).\n* `event`: game events like a snap, whistle, etc.\n* `acceleration`: magnitiude of the total acceleration in yards/second^2.\n* `sa`: Signed acceleration yards/second^2 in the direction the player is moving.","metadata":{}},{"cell_type":"code","source":"train_player_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/train_player_tracking.csv')\ntest_player_df = pd.read_csv('/kaggle/input/nfl-player-contact-detection/test_player_tracking.csv')","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:32:09.121883Z","iopub.execute_input":"2022-12-14T19:32:09.122361Z","iopub.status.idle":"2022-12-14T19:32:12.586741Z","shell.execute_reply.started":"2022-12-14T19:32:09.122322Z","shell.execute_reply":"2022-12-14T19:32:12.584669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Train**","metadata":{}},{"cell_type":"code","source":"print(f\"Shape => {train_player_df.shape}\")\ntrain_player_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:32:12.588376Z","iopub.execute_input":"2022-12-14T19:32:12.588757Z","iopub.status.idle":"2022-12-14T19:32:12.609269Z","shell.execute_reply.started":"2022-12-14T19:32:12.588723Z","shell.execute_reply":"2022-12-14T19:32:12.608052Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Histogram and Boxplot\ncols = ['x_position', 'y_position', 'speed', 'distance', 'direction', 'orientation', 'acceleration', 'sa']\n\nfor idx, col in enumerate(cols):\n    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))\n\n    sns.histplot(train_player_df, x=train_player_df[col], kde=True, hue=None,\n                 color=sns.color_palette('hls', train_player_df.shape[1])[idx], ax=ax1)\n    \n    sns.boxplot(x=train_player_df[col], width=.4, linewidth=4, fliersize=2.5,\n                color=sns.color_palette('hls', train_player_df.shape[1])[idx], ax=ax2)\n    \n    fig.suptitle(f'Histogram and Boxplot of {col}', size=20, y=1.02)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:32:12.611142Z","iopub.execute_input":"2022-12-14T19:32:12.611612Z","iopub.status.idle":"2022-12-14T19:32:12.623085Z","shell.execute_reply.started":"2022-12-14T19:32:12.611576Z","shell.execute_reply":"2022-12-14T19:32:12.622187Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Test**","metadata":{}},{"cell_type":"code","source":"print(f\"Shape => {test_player_df.shape}\")\ntest_player_df.head(3)","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:32:12.623943Z","iopub.execute_input":"2022-12-14T19:32:12.624227Z","iopub.status.idle":"2022-12-14T19:32:12.652913Z","shell.execute_reply.started":"2022-12-14T19:32:12.624202Z","shell.execute_reply":"2022-12-14T19:32:12.651131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Histogram and Boxplot\ncols = ['x_position', 'y_position', 'speed', 'distance', 'direction', 'orientation', 'acceleration', 'sa']\n\nfor idx, col in enumerate(cols):\n    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))\n\n    sns.histplot(test_player_df, x=test_player_df[col], kde=True, hue=None,\n                 color=sns.color_palette('hls', test_player_df.shape[1])[idx], ax=ax1)\n    \n    sns.boxplot(x=test_player_df[col], width=.4, linewidth=4, fliersize=2.5,\n                color=sns.color_palette('hls', test_player_df.shape[1])[idx], ax=ax2)\n    \n    fig.suptitle(f'Histogram and Boxplot of {col}', size=20, y=1.02)\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:32:12.654717Z","iopub.execute_input":"2022-12-14T19:32:12.655077Z","iopub.status.idle":"2022-12-14T19:32:12.663512Z","shell.execute_reply.started":"2022-12-14T19:32:12.655049Z","shell.execute_reply":"2022-12-14T19:32:12.662509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Sample submission","metadata":{}},{"cell_type":"markdown","source":"A **sample_submission.csv** file is provided. When your notebook is being processed on the test set this file will include every row required for a valid submission.\n\nNote the contact_id column is a unique identifier consisting of a combination of `game_play`, `step`, `nfl_player_id_1` and `nfl_player_id_2`","metadata":{}},{"cell_type":"code","source":"sb = pd.read_csv('/kaggle/input/nfl-player-contact-detection/sample_submission.csv')\nsb.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-14T19:32:20.905074Z","iopub.execute_input":"2022-12-14T19:32:20.905430Z","iopub.status.idle":"2022-12-14T19:32:20.963524Z","shell.execute_reply.started":"2022-12-14T19:32:20.905403Z","shell.execute_reply":"2022-12-14T19:32:20.962309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}