{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a4b9809a",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/root/anaconda3/envs/yt38/lib/python3.8/site-packages/tqdm/auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
      "  from .autonotebook import tqdm as notebook_tqdm\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import numpy as np\n",
    "import cv2\n",
    "import matplotlib.pyplot as plt\n",
    "from IPython.display import clear_output\n",
    "import os\n",
    "\n",
    "import pandas as pd\n",
    "import time\n",
    "from PIL import Image\n",
    "from ensemble_boxes import *"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91e6e452",
   "metadata": {},
   "source": [
    "# Test "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "efd6f33b",
   "metadata": {},
   "outputs": [],
   "source": [
    "cctv_path = './video/cctv/'\n",
    "youtube_path = './video/youtube/'\n",
    "\n",
    "cctv_vid_list = [file for file in os.listdir(cctv_path) if file.endswith(\".mp4\") or file.endswith(\".avi\")]\n",
    "youtube_vid_list = [file for file in os.listdir(youtube_path) if file.endswith(\".mp4\") or file.endswith(\".avi\")]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "da1d0e05",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "YOLOv5 🚀 v7.0-74-gd02ee60 Python-3.8.0 torch-1.10.0 CUDA:0 (NVIDIA RTX A6000, 48685MiB)\n",
      "\n",
      "Fusing layers... \n",
      "YOLOv5s summary: 157 layers, 7015519 parameters, 0 gradients, 15.8 GFLOPs\n",
      "Adding AutoShape... \n",
      "YOLOv5 🚀 v7.0-74-gd02ee60 Python-3.8.0 torch-1.10.0 CUDA:0 (NVIDIA RTX A6000, 48685MiB)\n",
      "\n",
      "Fusing layers... \n",
      "YOLOv5m summary: 212 layers, 20856975 parameters, 0 gradients, 47.9 GFLOPs\n",
      "Adding AutoShape... \n"
     ]
    }
   ],
   "source": [
    "model1 = torch.hub.load(\"/data/kwater/yolov5\",\n",
    "                       'custom', path='/data/kwater/test/weight/5s_0.68.pt',\n",
    "                       source='local',device=\"cuda:0\")  # local repo\n",
    "\n",
    "model2 = torch.hub.load(\"/data/kwater/yolov5\",\n",
    "                       'custom', path='/data/kwater/test/weight/5m_0.80.pt',\n",
    "                       source='local',device=\"cuda:0\")  # local repo\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8f33d8ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "def draw_bbox(img, vehicle_results, thres):\n",
    "    for obj in vehicle_results:\n",
    "        if obj[4]>thres:\n",
    "            x = int(obj[0])\n",
    "            y = int(obj[1])\n",
    "            x2 = int(obj[2])\n",
    "            y2 = int(obj[3])\n",
    "            \n",
    "            color = (255,0,0)\n",
    "\n",
    "            tk = 1\n",
    "            # if obj['risk1'] == 'danger':\n",
    "            #     tk = 5\n",
    "            \n",
    "            class_dic = {0:\"Leak\",\n",
    "                        1:\"Pole\"}\n",
    "            content =  class_dic[obj[5]]+\"_\"+str(round(obj[4],2))\n",
    "            \n",
    "            font =  cv2.FONT_HERSHEY_PLAIN\n",
    "            img = cv2.rectangle(img, (x,y), (x2,y2), color, tk) # bbox\n",
    "            img = cv2.putText(img, content, (x, y-2), font, tk, color, tk, cv2.LINE_AA) # label\n",
    "    return img"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "74f68d1d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['yungtong_augmented.mp4',\n",
       " 'mannam_waterfall_augmented_20230207_06_05_38.mp4',\n",
       " 'kyunbbu_augmented.mp4',\n",
       " 'yungtong_night_augmented.mp4',\n",
       " 'mannam_waterfall_augmented.mp4',\n",
       " 'yungtong_night_augmented_20230207_05_37_26.mp4']"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cctv_vid_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "55c4fd9e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def convert_wbf(results, threshold, image_size):\n",
    "    boxes_list = []\n",
    "    scores_list = []\n",
    "    labels_list = []\n",
    "    \n",
    "    for preds in results:\n",
    "        if preds[-2] >= threshold:\n",
    "            box = preds[:4]\n",
    "            boxes_list.append([box[0]/image_size[1],\n",
    "                               box[1]/image_size[0],\n",
    "                               box[2]/image_size[1],\n",
    "                               box[3]/image_size[0]]\n",
    "                               )\n",
    "            score = preds[-2].astype(float)\n",
    "            scores_list.append(score)\n",
    "            labels_list.append(preds[-1])\n",
    "    return boxes_list, labels_list, scores_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "7b8f0491",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total L :  150\n",
      "now :  150\n"
     ]
    }
   ],
   "source": [
    "frame_results = []\n",
    "for file in cctv_vid_list:\n",
    "#     print(file)\n",
    "#     print(file.split('.')[0]+'.csv')\n",
    "    \n",
    "    csv_file = os.path.join(cctv_path,file.split('.')[0]+'.csv')\n",
    "    data = np.array(pd.read_csv(csv_file, header=None))\n",
    "    \n",
    "    video_file = os.path.join(cctv_path,file)\n",
    "    cap = cv2.VideoCapture(video_file) \n",
    "    ret, frame = cap.read()   \n",
    "    \n",
    "    video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n",
    "    video_fps = int(cap.get(cv2.CAP_PROP_FPS))\n",
    "    image_size = frame.shape\n",
    "    \n",
    "    # image array\n",
    "    image_array = []\n",
    "    count = 0\n",
    "\n",
    "    while frame is not None:\n",
    "\n",
    "#         frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)\n",
    "\n",
    "        results1 = model1(frame)\n",
    "        bbox_results1=results1.xyxy[0].cpu().numpy() ## 결과값\n",
    "        \n",
    "        results2 = model2(frame)\n",
    "        bbox_results2=results2.xyxy[0].cpu().numpy() ## 결과값\n",
    "        \n",
    "        ## input format is xyxy\n",
    "        threshold = 0.4\n",
    "        boxes_list1, labels_list1, scores_list1 = convert_wbf(bbox_results1, threshold = threshold, image_size = image_size)\n",
    "        boxes_list2, labels_list2, scores_list2 = convert_wbf(bbox_results2, threshold = threshold, image_size = image_size)\n",
    "        \n",
    "        boxes_list_merges = []\n",
    "        labels_list_merges = []\n",
    "        scores_list_merges = []\n",
    "        boxes_list_merges.append(boxes_list1)\n",
    "        boxes_list_merges.append(boxes_list2)\n",
    "        labels_list_merges.append(labels_list1)\n",
    "        labels_list_merges.append(labels_list2)\n",
    "        scores_list_merges.append(scores_list1)\n",
    "        scores_list_merges.append(scores_list2)\n",
    "        \n",
    "        weights = [1, 1]\n",
    "        iou_thr = 0.5\n",
    "        skip_box_thr = 0.0001\n",
    "        sigma = 0.1\n",
    "        boxes, scores, labels = weighted_boxes_fusion(boxes_list_merges, scores_list_merges, \n",
    "                                                      labels_list_merges, weights=weights, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n",
    "        \n",
    "        img_w = image_size[1]\n",
    "        img_h = image_size[0]\n",
    "        \n",
    "        ## float to bbox\n",
    "        for idx,row in enumerate(boxes):\n",
    "            boxes[idx][0] *= img_w\n",
    "            boxes[idx][1] *= img_h\n",
    "            boxes[idx][2] *= img_w\n",
    "            boxes[idx][3] *= img_h\n",
    "            \n",
    "        ensemble_bbox_results = []\n",
    "        for idx,box in enumerate(boxes):\n",
    "            temp=[]\n",
    "            temp.extend(box)\n",
    "            temp.extend([scores[idx]])\n",
    "            temp.extend([int(labels[idx])])\n",
    "            \n",
    "            ensemble_bbox_results.append(temp)\n",
    "        ensemble_bbox_results = np.array(ensemble_bbox_results)\n",
    "            \n",
    "#         result_img=draw_bbox(frame.copy(), ensemble_bbox_results, 0.25)\n",
    "        \n",
    "        ######### SCORING\n",
    "        # COMPARE AND SCORING\n",
    "        gt = []\n",
    "        for row in data:\n",
    "            if row[0] == count:\n",
    "                gt.append(list(row[1:]))\n",
    "                \n",
    "        gt = np.array(gt)\n",
    "        \n",
    "        # bbox to float\n",
    "        if len(ensemble_bbox_results)>0:\n",
    "            pred_bb1 = np.array(ensemble_bbox_results[:,:4], dtype=np.float64)\n",
    "            pred_cls1 = np.array(ensemble_bbox_results[:,5], dtype=np.int64)\n",
    "            pred_conf1 = np.array(np.round(ensemble_bbox_results[:,4],2), dtype=np.float64)\n",
    "            for idx,row in enumerate(pred_bb1):\n",
    "                pred_bb1[idx][0] /= img_w\n",
    "                pred_bb1[idx][1] /= img_h\n",
    "                pred_bb1[idx][2] /= img_w\n",
    "                pred_bb1[idx][3] /= img_h\n",
    "        else:\n",
    "            pred_bb1 = np.array([])\n",
    "            pred_cls1 = np.array([])\n",
    "            pred_conf1 = np.array([])\n",
    "            \n",
    "        if len(gt)>0:\n",
    "            gt_bb1 = np.array(gt[:,:4], dtype=np.float64)\n",
    "            gt_cls1 = np.array(gt[:,4], dtype=np.int64)\n",
    "            for idx,row in enumerate(gt_bb1):\n",
    "                gt_bb1[idx][0] /= img_w\n",
    "                gt_bb1[idx][1] /= img_h\n",
    "                gt_bb1[idx][2] /= img_w\n",
    "                gt_bb1[idx][3] /= img_h  \n",
    "        else:\n",
    "            gt_bb1 = np.array([])\n",
    "            gt_cls1 = np.array([])\n",
    "            \n",
    "        frame_results.append([pred_bb1, pred_cls1, pred_conf1, gt_bb1, gt_cls1])\n",
    "\n",
    "        clear_output(wait=True)\n",
    "#         %matplotlib inline\n",
    "#         plt.imshow(result_img)\n",
    "#         plt.show()\n",
    "        \n",
    "#         print(results)\n",
    "#         print(bbox_results)\n",
    "#         print(np.array(data)[0][1:])\n",
    "\n",
    "#         image_array.append(result_img)\n",
    "\n",
    "        count+=1\n",
    "        ret, frame = cap.read()\n",
    "\n",
    "        print(\"total L : \", video_length)\n",
    "        print(\"now : \",count)\n",
    "        \n",
    "        \n",
    "#     out = cv2.VideoWriter(\"./cctv_results/inferenced_\"+file.split('.')[0]+\".mp4\",\n",
    "#                       cv2.VideoWriter_fourcc(*'DIVX'), video_fps, (image_size[1],image_size[0]))\n",
    "\n",
    "#     for i in range(len(image_array)):\n",
    "#         out.write(image_array[i])\n",
    "#     out.release()\n",
    "    \n",
    "    \n",
    "    \n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "eba59b1b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from mean_average_precision.detection_map import DetectionMAP\n",
    "from mean_average_precision.utils.show_frame import show_frame\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "6bb3610a",
   "metadata": {},
   "outputs": [],
   "source": [
    "n_class = 2\n",
    "\n",
    "mAP = DetectionMAP(n_class)\n",
    "for i, frame in enumerate(frame_results):\n",
    "#     print(\"Evaluate frame {}\".format(i))\n",
    "#     show_frame(*frame)\n",
    "    mAP.evaluate(*frame)\n",
    "\n",
    "# class_index\n",
    "# %matplotlib inline\n",
    "mAP.plot()\n",
    "# plt.show()\n",
    "plt.savefig(\"pr_curve_example.png\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "bf2dbe3a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# pred : [[     612.35      267.11        1017       567.1      0.9717     0]]\n",
    "# gt : [[  609  269 1021  571    0]]\n",
    "\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "3fc76880",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total L :  93\n",
      "now :  93\n",
      "kbs_news_daegue - Trim.mp4\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "OpenCV: FFMPEG: tag 0x58564944/'DIVX' is not supported with codec id 12 and format 'mp4 / MP4 (MPEG-4 Part 14)'\n",
      "OpenCV: FFMPEG: fallback to use tag 0x7634706d/'mp4v'\n"
     ]
    }
   ],
   "source": [
    "frame_results = []\n",
    "for file in youtube_vid_list:\n",
    "#     print(file)\n",
    "#     print(file.split('.')[0]+'.csv')\n",
    "    \n",
    "    csv_file = os.path.join(youtube_path,file.split('.')[0]+'.csv')\n",
    "    data = np.array(pd.read_csv(csv_file, header=None))\n",
    "    \n",
    "    video_file = os.path.join(youtube_path,file)\n",
    "    cap = cv2.VideoCapture(video_file) \n",
    "    ret, frame = cap.read()   \n",
    "    \n",
    "    video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))\n",
    "    video_fps = int(cap.get(cv2.CAP_PROP_FPS))\n",
    "    image_size = frame.shape\n",
    "    \n",
    "    # image array\n",
    "    image_array = []\n",
    "    count = 0\n",
    "\n",
    "    while frame is not None:\n",
    "\n",
    "#         frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)\n",
    "\n",
    "        results1 = model1(frame)\n",
    "        bbox_results1=results1.xyxy[0].cpu().numpy() ## 결과값\n",
    "        \n",
    "        results2 = model2(frame)\n",
    "        bbox_results2=results2.xyxy[0].cpu().numpy() ## 결과값\n",
    "        \n",
    "        ## input format is xyxy\n",
    "        threshold = 0.4\n",
    "        boxes_list1, labels_list1, scores_list1 = convert_wbf(bbox_results1, threshold = threshold, image_size = image_size)\n",
    "        boxes_list2, labels_list2, scores_list2 = convert_wbf(bbox_results2, threshold = threshold, image_size = image_size)\n",
    "        \n",
    "        boxes_list_merges = []\n",
    "        labels_list_merges = []\n",
    "        scores_list_merges = []\n",
    "        boxes_list_merges.append(boxes_list1)\n",
    "        boxes_list_merges.append(boxes_list2)\n",
    "        labels_list_merges.append(labels_list1)\n",
    "        labels_list_merges.append(labels_list2)\n",
    "        scores_list_merges.append(scores_list1)\n",
    "        scores_list_merges.append(scores_list2)\n",
    "        \n",
    "        weights = [1, 1]\n",
    "        iou_thr = 0.5\n",
    "        skip_box_thr = 0.0001\n",
    "        sigma = 0.1\n",
    "        boxes, scores, labels = weighted_boxes_fusion(boxes_list_merges, scores_list_merges, \n",
    "                                                      labels_list_merges, weights=weights, iou_thr=iou_thr, skip_box_thr=skip_box_thr)\n",
    "        \n",
    "        img_w = image_size[1]\n",
    "        img_h = image_size[0]\n",
    "        \n",
    "        ## float to bbox\n",
    "        for idx,row in enumerate(boxes):\n",
    "            boxes[idx][0] *= img_w\n",
    "            boxes[idx][1] *= img_h\n",
    "            boxes[idx][2] *= img_w\n",
    "            boxes[idx][3] *= img_h\n",
    "            \n",
    "        ensemble_bbox_results = []\n",
    "        for idx,box in enumerate(boxes):\n",
    "            temp=[]\n",
    "            temp.extend(box)\n",
    "            temp.extend([scores[idx]])\n",
    "            temp.extend([int(labels[idx])])\n",
    "            \n",
    "            ensemble_bbox_results.append(temp)\n",
    "        ensemble_bbox_results = np.array(ensemble_bbox_results)\n",
    "            \n",
    "#         result_img=draw_bbox(frame.copy(), ensemble_bbox_results, 0.25)\n",
    "        \n",
    "        ######### SCORING\n",
    "        # COMPARE AND SCORING\n",
    "        gt = []\n",
    "        for row in data:\n",
    "            if row[0] == count:\n",
    "                gt.append(list(row[1:]))\n",
    "                \n",
    "        gt = np.array(gt)\n",
    "        \n",
    "        # bbox to float\n",
    "        if len(ensemble_bbox_results)>0:\n",
    "            pred_bb1 = np.array(ensemble_bbox_results[:,:4], dtype=np.float64)\n",
    "            pred_cls1 = np.array(ensemble_bbox_results[:,5], dtype=np.int64)\n",
    "            pred_conf1 = np.array(np.round(ensemble_bbox_results[:,4],2), dtype=np.float64)\n",
    "            for idx,row in enumerate(pred_bb1):\n",
    "                pred_bb1[idx][0] /= img_w\n",
    "                pred_bb1[idx][1] /= img_h\n",
    "                pred_bb1[idx][2] /= img_w\n",
    "                pred_bb1[idx][3] /= img_h\n",
    "        else:\n",
    "            pred_bb1 = np.array([])\n",
    "            pred_cls1 = np.array([])\n",
    "            pred_conf1 = np.array([])\n",
    "            \n",
    "        if len(gt)>0:\n",
    "            gt_bb1 = np.array(gt[:,:4], dtype=np.float64)\n",
    "            gt_cls1 = np.array(gt[:,4], dtype=np.int64)\n",
    "            for idx,row in enumerate(gt_bb1):\n",
    "                gt_bb1[idx][0] /= img_w\n",
    "                gt_bb1[idx][1] /= img_h\n",
    "                gt_bb1[idx][2] /= img_w\n",
    "                gt_bb1[idx][3] /= img_h  \n",
    "        else:\n",
    "            gt_bb1 = np.array([])\n",
    "            gt_cls1 = np.array([])\n",
    "            \n",
    "        frame_results.append([pred_bb1, pred_cls1, pred_conf1, gt_bb1, gt_cls1])\n",
    "\n",
    "        clear_output(wait=True)\n",
    "#         %matplotlib inline\n",
    "#         plt.imshow(result_img)\n",
    "#         plt.show()\n",
    "        \n",
    "#         print(results)\n",
    "#         print(bbox_results)\n",
    "#         print(np.array(data)[0][1:])\n",
    "\n",
    "#         image_array.append(result_img)\n",
    "\n",
    "        count+=1\n",
    "        ret, frame = cap.read()\n",
    "\n",
    "        print(\"total L : \", video_length)\n",
    "        print(\"now : \",count)\n",
    "        \n",
    "        \n",
    "#     out = cv2.VideoWriter(\"./cctv_results/inferenced_\"+file.split('.')[0]+\".mp4\",\n",
    "#                       cv2.VideoWriter_fourcc(*'DIVX'), video_fps, (image_size[1],image_size[0]))\n",
    "\n",
    "#     for i in range(len(image_array)):\n",
    "#         out.write(image_array[i])\n",
    "#     out.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "79a516b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "from mean_average_precision.detection_map import DetectionMAP\n",
    "from mean_average_precision.utils.show_frame import show_frame\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "a429143d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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gslkwoQJExw+TyK6+zC+kV0IkR3MmDFDfHx8pKSkREpKSuT06dPy6KOPilarFZ1OJyIi/fv3lz59+ojJZDK3O3TokKhUKlm/fr2IiGzevFkASGZmZo2WazKZpKSkRJ566inp3bu3uXzbtm0CQH744QdzGQD529/+ZovpEtFdhPGNHIV70shubty4gUaNGpnfu7u7Y+3atWjfvj0KCgrw/fffY/78+SgrKzPXadeuHcLDw/HDDz8gISEBOTk5aNy4McaOHVvpcvR6PWbMmIG1a9fi3Llz5v6aNGliv8kR0V2N8Y0cgeekkd14e3vjhx9+wN69e/H5558jJCQETzzxBPLy8qDX61FWVoYXXngBjRo1snidOXMGubm5AIArV64gJCQEKpWq0uUkJyfjiy++QGpqKjZv3owffvgBKSkpKCwsdNRUieguw/hGjsA9aWQ3bm5uuP/++wEAPXv2RPv27RETE4PZs2dj/vz5UKlUmD59OkaMGGHVNigoCMCt/xbz8vIgIhUGssLCQqxbtw5///vf8eyzz5rLTSaTfSZFRATGN3IM7kkjh7n//vsxbtw4rFixAteuXUPv3r1x5MgR3H///VavVq1aAQAGDRqEgoIC/OMf/6iwz6KiIphMJnh6eprLrl27hm+++cYRUyIiAsD4RvbBPWnkUK+//jq+/PJLLFiwAH/7298QFxeHRx99FGPHjoVWq8XZs2fx7bff4sknn8SAAQMwaNAgJCQkICUlBSdOnEBMTAzy8/Px9ddf46uvvkJAQAB69OiBuXPnIjg4GB4eHpg7dy4CAgKsLnUnIrInxjeyNe5JI4dq3749xo4diw8//BAdO3bEzp07cf36dTz55JNISEjA7Nmz0bhxY7Rt29bc5p///Ceee+45LFmyBEOHDsXUqVPh6+tr/jwzMxNt27bFhAkT8Nxzz2H06NF44oknnDE9IrqLMb6RralERJw9CCIiIiKyxD1pRERERArEJI2IiIhIgZikERERESkQkzQiIiIiBWKSRkRERKRATNKIiIiIFIhJGhEREZECMUkjIiIiUiAmaUREREQKxCSNiIiISIGYpBEREREpEJM0IiIiIgVikkZERESkQEzSiIiIiBSISRoRERGRAjFJIyIiIlIgJmlERERECsQkjYiIiEiB7JqkHT9+HJMmTULXrl3h4eGB6OjoGrUTEcydOxct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\n",
      "text/plain": [
       "<Figure size 640x480 with 4 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 0 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "n_class = 2\n",
    "\n",
    "mAP = DetectionMAP(n_class)\n",
    "for i, frame in enumerate(frame_results):\n",
    "#     print(\"Evaluate frame {}\".format(i))\n",
    "#     show_frame(*frame)\n",
    "    mAP.evaluate(*frame)\n",
    "\n",
    "# class_index\n",
    "mAP.plot()\n",
    "plt.show()\n",
    "plt.savefig(\"pr_curve_example.png\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "84681ff5",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "yt38",
   "language": "python",
   "name": "yt38"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
