From bd7b96e6286b606413f8b645c11964008ada630a Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Mon, 4 Dec 2023 12:45:05 +0300 Subject: [PATCH 01/16] dev 1.4.0 --- README.md | 12 +- csrc/faster_eval_api/coco_eval/cocoeval.cpp | 5 +- csrc/faster_eval_api/faster_eval_api.cpp | 10 +- examples/curve_example.ipynb | 6180 ++++++++++++++++++- examples/eval_example.ipynb | 44 +- faster_coco_eval/core/coco.py | 248 +- faster_coco_eval/core/cocoeval.py | 449 +- faster_coco_eval/core/faster_eval_api.py | 276 +- faster_coco_eval/core/mask.py | 4 +- faster_coco_eval/extra/__init__.py | 2 +- faster_coco_eval/extra/curves.py | 131 +- faster_coco_eval/extra/display.py | 431 +- faster_coco_eval/extra/extra.py | 33 +- faster_coco_eval/version.py | 4 +- requirements/optional.txt | 2 - setup.py | 8 +- tests/basic.py | 62 +- tests/data/dt_cat_dog.json | 1110 ---- tests/data/gt_cat_dog.json | 1285 ---- tests/dataset/dt_dataset.json | 862 +++ tests/dataset/gt_dataset.json | 832 +++ tests/dataset/img_1.jpg | Bin 0 -> 11645 bytes tests/dataset/img_2.jpg | Bin 0 -> 11720 bytes tests/dataset/img_3.jpg | Bin 0 -> 11115 bytes 24 files changed, 8779 insertions(+), 3211 deletions(-) delete mode 100644 tests/data/dt_cat_dog.json delete mode 100644 tests/data/gt_cat_dog.json create mode 100644 tests/dataset/dt_dataset.json create mode 100644 tests/dataset/gt_dataset.json create mode 100644 tests/dataset/img_1.jpg create mode 100644 tests/dataset/img_2.jpg create mode 100644 tests/dataset/img_3.jpg diff --git a/README.md b/README.md index c9e87b6..d10bb13 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,13 @@ cur.plot_pre_rec(plotly_backend=False) ## history +### v1.4.0 + +- [x] fix issue +- [x] Updated pre-rec calculation method +- [x] Updated required libraries +- [x] Moved all matplotlib dependencies to plotly + ### v1.3.3 - [x] fix by ViTrox @@ -135,11 +142,6 @@ cur.plot_pre_rec(plotly_backend=False) - [x] Append ROC / AUC curves - [x] Check if it works on windows -### TODOs - -- [X] Remove pycocotools dependencies -- [ ] Remove matplotlib dependencies - ## License The original module was licensed with apache 2, I will continue with the same license. diff --git a/csrc/faster_eval_api/coco_eval/cocoeval.cpp b/csrc/faster_eval_api/coco_eval/cocoeval.cpp index a388b45..78e47e1 100644 --- a/csrc/faster_eval_api/coco_eval/cocoeval.cpp +++ b/csrc/faster_eval_api/coco_eval/cocoeval.cpp @@ -548,14 +548,11 @@ namespace coco_eval std::vector out_detection_matches = {}; std::vector out_ground_truth_matches = {}; - std::vector out_detection_ignores = {}; std::vector out_ground_truth_orig_id = {}; - // auto eval = evaluations[0]; for (auto eval : evaluations) { out_detection_matches.insert(out_detection_matches.end(), eval.detection_matches.begin(), eval.detection_matches.end()); out_ground_truth_matches.insert(out_ground_truth_matches.end(), eval.ground_truth_matches.begin(), eval.ground_truth_matches.end()); - out_detection_ignores.insert(out_detection_ignores.end(), eval.detection_ignores.begin(), eval.detection_ignores.end()); out_ground_truth_orig_id.insert(out_ground_truth_orig_id.end(), eval.ground_truth_orig_id.begin(), eval.ground_truth_orig_id.end()); } @@ -571,7 +568,7 @@ namespace coco_eval "recall"_a = recalls_out, "scores"_a = scores_out, "detection_matches"_a = out_detection_matches, - "detection_ignores"_a = out_detection_ignores, + // "detection_ignores"_a = out_detection_ignores, "ground_truth_matches"_a = out_ground_truth_matches, "ground_truth_orig_id"_a = out_ground_truth_orig_id, "evaluations_size"_a = evaluations_size); diff --git a/csrc/faster_eval_api/faster_eval_api.cpp b/csrc/faster_eval_api/faster_eval_api.cpp index 4750e5a..58f48c5 100644 --- a/csrc/faster_eval_api/faster_eval_api.cpp +++ b/csrc/faster_eval_api/faster_eval_api.cpp @@ -51,11 +51,11 @@ namespace coco_eval pybind11::class_(m, "InstanceAnnotation").def(pybind11::init()); pybind11::class_(m, "ImageEvaluation").def(pybind11::init<>()); - #ifdef VERSION_INFO - m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); - #else - m.attr("__version__") = "dev"; - #endif +#ifdef VERSION_INFO + m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO); +#else + m.attr("__version__") = "dev"; +#endif } } // namespace coco_eval \ No newline at end of file diff --git a/examples/curve_example.ipynb b/examples/curve_example.ipynb index 2a7c56e..4bb72ae 100644 --- a/examples/curve_example.ipynb +++ b/examples/curve_example.ipynb @@ -10,7 +10,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "faster_coco_eval.__version__='1.3.3'\n" + "faster_coco_eval.__version__='1.4.0'\n" ] } ], @@ -38,7 +38,7 @@ "def load(file):\n", " with open(file) as io:\n", " _data = json.load(io)\n", - " \n", + "\n", " return _data" ] }, @@ -49,8 +49,8 @@ "metadata": {}, "outputs": [], "source": [ - "prepared_coco_in_dict = load('../tests/data/gt_cat_dog.json')\n", - "prepared_anns = load('../tests/data/dt_cat_dog.json')" + "prepared_coco_in_dict = load(\"../tests/dataset/gt_dataset.json\")\n", + "prepared_anns = load(\"../tests/dataset/dt_dataset.json\")" ] }, { @@ -61,9 +61,1228 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABNEAAAJwCAYAAACnPPcPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/NK7nSAAAACXBIWXMAAA9hAAAPYQGoP6dpAABZGUlEQVR4nO3de5jVdbk3/veaIwdFMAQ8sKNSM/OUmG4yMwvBQ/bQU2ZqaqSVKU8m1VbMRPMptINpO5UylXZPbt3aYVsaihSVSlkq7dzbUx7CnwlKiigjc1y/P2AWTQwM4MystYbX67q4LuY73zVzf2f8APP2c9+fQrFYLAYAAAAAWK+achcAAAAAAJVOiAYAAAAAPRCiAQAAAEAPhGgAAAAA0AMhGgAAAAD0QIgGAAAAAD0QogEAAABAD4RoAAAAANADIRoAAAAA9ECIBgBQIT7ykY9k3Lhxm/SaBQsWpFAoZMGCBX1SU7V75zvfmXe+852lt5988skUCoXMmTOnbDUBANVJiAYAbNHmzJmTQqFQ+jVo0KDsuuuumTZtWpYuXVru8ipaZyDV+aumpibbbrttDj/88CxcuLDc5QEA9Kq6chcAAFAJvvjFL+Z1r3tdVq1alTvvvDNXXnllbr311jzwwAMZMmRIv9Rw1VVXpaOjY5Ne8453vCOvvPJKGhoa+qiqnh177LE54ogj0t7enkceeSRXXHFFDjnkkPz+97/PnnvuWba6AAB6kxANACDJ4Ycfnv322y9Jcsopp+Q1r3lNLrnkkvznf/5njj322HXuX7lyZYYOHdqrNdTX12/ya2pqajJo0KBerWNT7bvvvvnwhz9cevuggw7K4YcfniuvvDJXXHFFGSsDAOg92jkBALrxrne9K0nyxBNP5CMf+Ui22mqrPPbYYzniiCOy9dZb5/jjj0+SdHR05NJLL82b3/zmDBo0KKNHj84nPvGJvPDCC+t8zJ///Oc5+OCDs/XWW2fYsGF561vfmuuuu670/u5mol1//fUZP3586TV77rlnLrvsstL71zcT7cYbb8z48eMzePDgjBw5Mh/+8Ifz9NNPd7mn87mefvrpTJkyJVtttVW22267fPazn017e/tmf+0OOuigJMljjz3W5fry5cvz6U9/OmPHjk1jY2N23nnnXHzxxevsvuvo6Mhll12WPffcM4MGDcp2222Xww47LH/4wx9K91x77bV517velVGjRqWxsTG77757rrzyys2uGQCgJ3aiAQB0ozMAes1rXpMkaWtry+TJk/P2t789X/va10otnp/4xCcyZ86cTJ06NZ/61KfyxBNP5Fvf+lbuv//+3HXXXaXdZXPmzMlHP/rRvPnNb86MGTMyfPjw3H///Zk7d26OO+64bmuYN29ejj322Lz73e/OxRdfnCR58MEHc9ddd+WMM85Yb+2d9bz1rW/NrFmzsnTp0lx22WW56667cv/992f48OGle9vb2zN58uQccMAB+drXvpY77rgjX//61/OGN7whn/zkJzfra/fkk08mSUaMGFG61tTUlIMPPjhPP/10PvGJT+Sf/umfcvfdd2fGjBl55plncumll5buPfnkkzNnzpwcfvjhOeWUU9LW1pbf/OY3+e1vf1vaLXjllVfmzW9+c9773vemrq4uP/3pT3Paaaelo6Mjp59++mbVDQCwIUI0AIAkL774YpYtW5ZVq1blrrvuyhe/+MUMHjw473nPe7Jw4cI0Nzfn6KOPzqxZs0qvufPOO/Pd7343P/jBD7oEYYccckgOO+yw3HjjjTnuuOPy4osv5lOf+lT233//LFiwoEv7ZbFYXG9Nt9xyS4YNG5bbbrsttbW1G/Ucra2tOeuss7LHHnvk17/+delzvf3tb8973vOefOMb38gFF1xQun/VqlU55phj8oUvfCFJcuqpp2bffffN1VdfvdEhWlNTU5YtW5b29vY8+uijmT59epLkAx/4QOmeSy65JI899ljuv//+7LLLLklWB5A77LBDvvrVr+Yzn/lMxo4dm1/+8peZM2dOPvWpT3XZcfeZz3ymy9fqV7/6VQYPHlx6e9q0aTnssMNyySWXCNEAgD6hnRMAIMnEiROz3XbbZezYsfnQhz6UrbbaKj/+8Y+z4447lu75x1DpxhtvzDbbbJNDDz00y5YtK/0aP358ttpqq/zyl79MsnpH2UsvvZSzzz57nfllhUJhvTUNHz48K1euzLx58zb6Of7whz/k2WefzWmnndblcx155JHZbbfdcsstt6zzmlNPPbXL2wcddFAef/zxjf6cM2fOzHbbbZcxY8bkoIMOyoMPPpivf/3rXUK0G2+8MQcddFBGjBjR5Ws1ceLEtLe359e//nWS5Ic//GEKhUJmzpy5zuf5+6/V3wdonQHowQcfnMcffzwvvvjiRtcOALCx7EQDAEhy+eWXZ9ddd01dXV1Gjx6dN77xjampWfv/G+vq6rLTTjt1ec2jjz6aF198MaNGjer2Yz777LNJ1raG7rHHHptU02mnnZb/+I//yOGHH54dd9wxkyZNygc/+MEcdthh633NX/7ylyTJG9/4xnXet9tuu+XOO+/scq1z5tjfGzFiRJeZbs8991yXGWlbbbVVttpqq9LbH//4x3P00Udn1apV+cUvfpFvfvOb68xUe/TRR/Nf//Vf63yuTn//tdphhx2y7bbbrvcZk+Suu+7KzJkzs3DhwjQ1NXV534svvphtttlmg68HANhUQjQAgCT7779/ad5WdxobG7uEasnqAfijRo3KD37wg25fs77AaGONGjUqixYtym233Zaf//zn+fnPf55rr702J554Yr73ve+9qo/daWPaRN/61reWwrlk9c6z888/v/T2LrvskokTJyZJ3vOe96S2tjZnn312DjnkkNLXtKOjI4ceemj+5V/+pdvPseuuu250zY899lje/e53Z7fddssll1ySsWPHpqGhIbfeemu+8Y1vrHNQAQBAbxCiAQBspje84Q254447cuCBB3ZpL+zuviR54IEHsvPOO2/S52hoaMhRRx2Vo446Kh0dHTnttNPy7W9/O1/4whe6/Vivfe1rkyQPP/xw6YTRTg8//HDp/ZviBz/4QV555ZXS269//es3eP/nP//5XHXVVTn33HMzd+7cJKu/Bi+//HIpbFufN7zhDbntttvy/PPPr3c32k9/+tM0Nzfn5ptvzj/90z+Vrne2zwIA9AUz0QAANtMHP/jBtLe358ILL1znfW1tbVm+fHmSZNKkSdl6660za9asrFq1qst9GzpY4G9/+1uXt2tqarLXXnslSZqbm7t9zX777ZdRo0Zl9uzZXe75+c9/ngcffDBHHnnkRj3b3zvwwAMzceLE0q+eQrThw4fnE5/4RG677bYsWrQoyeqv1cKFC3Pbbbetc//y5cvT1taWJHn/+9+fYrHY5fCDTp1fq87dc3//tXvxxRdz7bXXbvKzAQBsLDvRAAA208EHH5xPfOITmTVrVhYtWpRJkyalvr4+jz76aG688cZcdtll+cAHPpBhw4blG9/4Rk455ZS89a1vzXHHHZcRI0bkj3/8Y5qamtbbmnnKKafk+eefz7ve9a7stNNO+ctf/pJ//dd/zT777JM3velN3b6mvr4+F198caZOnZqDDz44xx57bJYuXZrLLrss48aNy5lnntmXX5KSM844I5deemkuuuiiXH/99fnc5z6Xm2++Oe95z3vykY98JOPHj8/KlSvzpz/9KTfddFOefPLJjBw5MoccckhOOOGEfPOb38yjjz6aww47LB0dHfnNb36TQw45JNOmTcukSZNKO/Q+8YlP5OWXX85VV12VUaNG5ZlnnumX5wMAtjxCNACAV2H27NkZP358vv3tb+ecc85JXV1dxo0blw9/+MM58MADS/edfPLJGTVqVC666KJceOGFqa+vz2677bbBUOvDH/5wvvOd7+SKK67I8uXLM2bMmBxzzDE5//zz15nP9vc+8pGPZMiQIbnoooty1llnZejQoXnf+96Xiy++OMOHD+/Nx1+vHXbYIccdd1y+//3v57HHHssb3vCG/OpXv8qXv/zl3Hjjjfm3f/u3DBs2LLvuumsuuOCCLgcBXHvttdlrr71y9dVX53Of+1y22Wab7Lfffnnb296WZPWhCTfddFPOPffcfPazn82YMWPyyU9+Mtttt10++tGP9svzAQBbnkJxQz0EAAAAAICZaAAAAADQEyEaAAAAAPRAiAYAAAAAPRCiAQAAAEAPhGgAAAAA0AMhGgAAAAD0oK7cBfS3jo6O/PWvf83WW2+dQqFQ7nIAAAAAKKNisZiXXnopO+ywQ2pq1r/fbIsL0f76179m7Nix5S4DAAAAgAry1FNPZaeddlrv+7e4EG3rrbdOsvoLM2zYsDJX0ztaW1tz++23Z9KkSamvry93OVC1rCXoPdYT9A5rCXqP9QS9YyCupRUrVmTs2LGlzGh9trgQrbOFc9iwYQMqRBsyZEiGDRs2YP4DhnKwlqD3WE/QO6wl6D3WE/SOgbyWehr75WABAAAAAOiBEA0AAAAAeiBEAwAAAIAebHEz0QAAAAA6FYvFtLW1pb29vdylVIXW1tbU1dVl1apVVfM1q62tTV1dXY8zz3oiRAMAAAC2SC0tLXnmmWfS1NRU7lKqRrFYzJgxY/LUU0+96lCqPw0ZMiTbb799GhoaNvtjCNEAAACALU5HR0eeeOKJ1NbWZocddkhDQ0NVhULl0tHRkZdffjlbbbVVamoqf0pYsVhMS0tLnnvuuTzxxBPZZZddNrtuIRoAAACwxWlpaUlHR0fGjh2bIUOGlLucqtHR0ZGWlpYMGjSoKkK0JBk8eHDq6+vzl7/8pVT75qiOpwUAAADoA9USBPHq9Mb32X8pAAAAANADIRoAAAAA9ECIBgAAAAA9EKIBAAAAsFkuv/zyjBs3LoMGDcoBBxyQe+65Z4P3v/Od70yhUFjn15FHHlm65/zzz89uu+2WoUOHZsSIEZk4cWJ+97vfrfOxbrnllhxwwAEZPHhwRowYkSlTpvT243UhRAMAAABgk91www2ZPn16Zs6cmfvuuy977713Jk+enGeffXa9r/nRj36UZ555pvTrgQceSG1tbY4++ujSPbvuumu+9a1v5U9/+lPuvPPOjBs3LpMmTcpzzz1XuueHP/xhTjjhhEydOjV//OMfc9ddd+W4447r0+cVogEAAAAkKRaLaWppK8uvYrG40XXOnTs3b3/72zN8+PC85jWvyXve85489thjpfcvWLAghUIhy5cvL11btGhRCoVCnnzyydK1u+66K+985zszZMiQjBgxIpMnT84LL7yw0XVccskl+djHPpapU6dm9913z+zZszNkyJBcc801633NtttumzFjxpR+zZs3L0OGDOkSoh133HGZOHFiXv/61+fNb35zLrnkkqxYsSL/9V//lSRpa2vLGWecka9+9as59dRTs+uuu2b33XfPBz/4wY2ufXPU9elHBwAAAKgSr7S2Z/fzbivL5/6fL07OkIaNi2lWrlyZ6dOnZ6+99srLL7+c8847L+973/uyaNGi1NRs3H6pRYsW5d3vfnc++tGP5rLLLktdXV1++ctfpr29PUkyZ86cTJ06db3hXktLS+69997MmDGjdK2mpiYTJ07MwoULN6qGJLn66qvzoQ99KEOHDl3v5/nOd76TbbbZJnvvvXeS5L777svTTz+dmpqavOUtb8mSJUuyzz775Ktf/Wr22GOPjf7cm0qIBgAAAFBF3v/+93d5+5prrsl2222X//mf/9noEOkrX/lK9ttvv1xxxRWla29+85tLv99mm23yxje+cb2vX7ZsWdrb2zN69Ogu10ePHp2HHnpoo2q455578sADD+Tqq69e530/+9nP8qEPfShNTU3ZfvvtM2/evIwcOTJJ8vjjjydZPTvtkksuybhx4/L1r38973znO/PII49k22233ajPv6mEaAAAAABJBtfX5n++OLlsn3tjPfrooznvvPPyu9/9LsuWLUtHR0eS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UNU2K0T7zGc+k8suuyzFYrG36wEAAIABqXMnmnZOqE6b1c5555135pe//GV+/vOf581vfnPq6+u7vP9HP/pRrxQHAAAAA0Vj3eqZaHaiQXXarBBt+PDhed/73tfbtQAAAMCAZSYaVLfNCtGuvfba3q4DAAAABrRGM9Ggqm1WiNbpueeey8MPP5wkeeMb35jtttuuV4oCAACAgaazndNMNKhOm3WwwMqVK/PRj34022+/fd7xjnfkHe94R3bYYYecfPLJaWpq6u0aAQAAoOo11tuJBtVss0K06dOn51e/+lV++tOfZvny5Vm+fHn+8z//M7/61a/ymc98prdrBAAAgKrXULv6R/D2jmLa2gVpUG02q53zhz/8YW666aa8853vLF074ogjMnjw4Hzwgx/MlVde2Vv1AQAAwIDQuRMtWb0bra52s/a1AGWyWSu2qakpo0ePXuf6qFGjtHMCAABANxr+LjQzFw2qz2aFaBMmTMjMmTOzatWq0rVXXnklF1xwQSZMmNBrxQEAAMBAUVdbk7qaQhJz0aAabVY752WXXZbJkydnp512yt57750k+eMf/5hBgwbltttu69UCAQAAYKBoqKtJW0t7mtvay10KsIk2K0TbY4898uijj+YHP/hBHnrooSTJsccem+OPPz6DBw/u1QIBAABgoGisq0lTS7t2TqhCmxWiJcmQIUPysY99rDdrAQAAgAGtsa42Sat2TqhCGx2i3XzzzTn88MNTX1+fm2++eYP3vve9733VhQEAAMBA03lCp3ZOqD4bHaJNmTIlS5YsyahRozJlypT13lcoFNLe7g8DAAAA+EedJ3Q2t9qJBtVmo0O0jo6Obn8PAAAAbJzSTrR2P1dDtanprQ+0fPny3vpQAAAAMCCtnolmJxpUo80K0S6++OLccMMNpbePPvrobLvtttlxxx3zxz/+sdeKAwAAgIGksc5MNKhWmxWizZ49O2PHjk2SzJs3L3fccUfmzp2bww8/PJ/73Od6tUAAAAAYKBpKIZqdaFBtNnom2t9bsmRJKUT72c9+lg9+8IOZNGlSxo0blwMOOKBXCwQAAICBonMnWosQDarOZu1EGzFiRJ566qkkydy5czNx4sQkSbFYdDInAAAArEdpJpoQDarOZu1E+9//+3/nuOOOyy677JK//e1vOfzww5Mk999/f3beeedeLRAAAAAGigYz0aBqbVaI9o1vfCPjxo3LU089la985SvZaqutkiTPPPNMTjvttF4tEAAAAAYK7ZxQvTYrRKuvr89nP/vZda6feeaZr7ogAAAAGKi0c0L12ugQ7eabb87hhx+e+vr63HzzzRu8973vfe+rLgwAAAAGmsb6Ne2crUI0qDYbHaJNmTIlS5YsyahRozJlypT13lcoFBwuAAAAAN1oqDUTDarVRodoHR0d3f4eAAAA2DidO9HMRIPqU1PuAgAAAGBLYSYaVK/NCtE+9alP5Zvf/OY617/1rW/l05/+9KutCQAAAAakztM5tXNC9dmsEO2HP/xhDjzwwHWuv+1tb8tNN930qosCAACAgaihFKLZiQbVZrNCtL/97W/ZZptt1rk+bNiwLFu27FUXBQAAAANR5040M9Gg+mxWiLbzzjtn7ty561z/+c9/nte//vWvuigAAAAYiMxEg+q10adz/r3p06dn2rRpee655/Kud70rSTJ//vx8/etfz6WXXtqb9QEAAMCA0Xk6p5loUH02K0T76Ec/mubm5nzpS1/KhRdemCQZN25crrzyypx44om9WiAAAAAMFI212jmhWm1WiJYkn/zkJ/PJT34yzz33XAYPHpytttqqN+sCAACAAWftTjQhGlSbzZqJliRtbW2544478qMf/SjFYjFJ8te//jUvv/xyrxUHAAAAA0lpJlqrEA2qzWbtRPvLX/6Sww47LIsXL05zc3MOPfTQbL311rn44ovT3Nyc2bNn93adAAAAUPUa6sxEg2q1WTvRzjjjjOy333554YUXMnjw4NL1973vfZk/f36vFQcAAAADSWOdmWhQrTZrJ9pvfvOb3H333WloaOhyfdy4cXn66ad7pTAAAAAYaErtnEI0qDqbtROto6Mj7e3rbj39//6//y9bb731qy4KAAAABqLOnWhtHcW0tQvSoJpsVog2adKkXHrppaW3C4VCXn755cycOTNHHHFEb9UGAAAAA0rnTLQkaRGiQVXZrHbOr33taznssMOy++67Z9WqVTnuuOPy6KOPZuTIkfn3f//33q4RAAAABoTGvw/R2joypGEDNwMVZbNCtLFjx+aPf/xjbrjhhvzxj3/Myy+/nJNPPjnHH398l4MGAAAAgLXqamtSW1NIe0fRXDSoMpscorW2tma33XbLz372sxx//PE5/vjj+6IuAAAAGJAa62rS1NKe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yZJu71+yZEmf1QmVbnPW0j8666yzssMOO6zzlwRsaTZnPd155525+uqrs2jRon6oEKrD5qylxx9/PL/4xS9y/PHH59Zbb82f//znnHbaaWltbc3MmTP7o2yoOJuzlo477rgsW7Ysb3/721MsFtPW1pZTTz1VOydsovXlDytWrMgrr7ySwYMHl6myvmEnGsBGuOiii3L99dfnxz/+cQYNGlTucqCqvPTSSznhhBNy1VVXZeTIkeUuB6paR0dHRo0ale985zsZP358jjnmmHz+8583sgM20YIFC/LlL385V1xxRe6777786Ec/yi233JILL7yw3KUBFcxOtAo3cuTI1NbWZunSpV2uL126NGPGjOn2NWPGjNmk+2FLsDlrqdPXvva1XHTRRbnjjjuy11579WWZUBU2dT099thjefLJJ3PUUUeVrnV0dCRJ6urq8vDDD+cNb3hD3xYNFWhz/m7afvvtU19fn9ra2tK1N73pTVmyZElaWlrS0NDQpzVDJdqctfSFL3whJ5xwQk455ZQkyZ577pmVK1fm4x//eD7/+c+npsZ+E9gY68sfhg0bNuB2oSV2olW8hoaGjB8/vsvAy46OjsyfPz8TJkzo9jUTJkzocn+SzJs3b733w5Zgc9ZSknzlK1/JhRdemLlz52a//fbrj1Kh4m3qetptt93ypz/9KYsWLSr9eu9731s6xWns2LH9WT5UjM35u+nAAw/Mn//851IQnSSPPPJItt9+ewEaW6zNWUtNTU3rBGWd4bSz92DjbXH5Q5GKd/311xcbGxuLc+bMKf7P//xP8eMf/3hx+PDhxSVLlhSLxWLxhBNOKJ599tml+++6665iXV1d8Wtf+1rxwQcfLM6cObNYX19f/NOf/lSuR4CKsKlr6aKLLio2NDQUb7rppuIzzzxT+vXSSy+V6xGgYmzqevpHJ510UvF//a//1U/VQuXa1LW0ePHi4tZbb12cNm1a8eGHHy7+7Gc/K44aNar4f//v/y3XI0BF2NS1NHPmzOLWW29d/Pd///fi448/Xrz99tuLb3jDG4of/OAHy/UIUBFeeuml4v3331+8//77i0mKl1xySfH+++8v/uUvfykWi8Xi2WefXTzhhBNK9z/++OPFIUOGFD/3uc8VH3zwweLll19erK2tLc6dO7dcj9CntHNWgWOOOSbPPfdczjvvvCxZsiT77LNP5s6dWxret3jx4i7/F+Vtb3tbrrvuupx77rk555xzsssuu+QnP/lJ9thjj3I9AlSETV1LV155ZVpaWvKBD3ygy8eZOXNmzj///P4sHSrOpq4noHubupbGjh2b2267LWeeeWb22muv7LjjjjnjjDNy1llnlesRoCJs6lo699xzUygUcu655+bpp5/Odtttl6OOOipf+tKXyvUIUBH+8Ic/5JBDDim9PX369CTJSSedlDlz5uSZZ57J4sWLS+9/3etel1tuuSVnnnlmLrvssuy000757ne/m8mTJ/d77f2hUCzaqwoAAAAAG+J/EQMAAABAD4RoAAAAANADIRoAAAAA9ECIBgAAAAA9EKIBAAAAQA+EaAAAAADQAyEaAAAAAPRAiAYAAAAAPRCiAQCwSQqFQn7yk58kSZ588skUCoUsWrSorDUBAPQ1IRoAQBX5yEc+kkKhkEKhkPr6+rzuda/Lv/zLv2TVqlXlLg0AYECrK3cBAABsmsMOOyzXXnttWltbc++99+akk05KoVDIxRdfXO7SAAAGLDvRAACqTGNjY8aMGZOxY8dmypQpmThxYubNm5ck6ejoyKxZs/K6170ugwcPzt57752bbrqpy+v/+7//O+95z3sybNiwbL311jnooIPy2GOPJUl+//vf59BDD83IkSOzzTbb5OCDD859993X788IAFBphGgAAFXsgQceyN13352GhoYkyaxZs/Jv//ZvmT17dv77v/87Z555Zj784Q/nV7/6VZLk6aefzjve8Y40NjbmF7/4Re6999589KMfTVtbW5LkpZdeykknnZQ777wzv/3tb7PLLrvkiCOOyEsvvVS2ZwQAqATaOQEAqszPfvazbLXVVmlra0tzc3NqamryrW99K83Nzfnyl7+cO+64IxMmTEiSvP71r8+dd96Zb3/72zn44INz+eWXZ5tttsn111+f+vr6JMmuu+5a+tjvete7unyu73znOxk+fHh+9atf5T3veU//PSQAQIURogEAVJlDDjkkV155ZVauXJlvfOMbqaury/vf//7893//d5qamnLooYd2ub+lpSVvectbkiSLFi3KQQcdVArQ/tHSpUtz7rnnZsGCBXn22WfT3t6epqamLF68uM+fCwCgkgnRAACqzNChQ7PzzjsnSa655prsvffeufrqq7PHHnskSW655ZbsuOOOXV7T2NiYJBk8ePAGP/ZJJ52Uv/3tb7nsssvy2te+No2NjZkwYUJaWlr64EkAAKqHEA0AoIrV1NTknHPOyfTp0/PII4+ksbExixcvzsEHH9zt/XvttVe+973vpbW1tdvdaHfddVeuuOKKHHHEEUmSp556KsuWLevTZwAAqAYOFgAAqHJHH310amtr8+1vfzuf/exnc+aZZ+Z73/teHnvssdx3333513/913zve99LkkybNi0rVqzIhz70ofzhD3/Io48+mu9///t5+OGHkyS77LJLvv/97+fBBx/M7373uxx//PE97l4DANgS2IkGAFDl6urqMm3atHzlK1/JE088ke222y6zZs3K448/nuHDh2fffffNOeeckyR5zWtek1/84hf53Oc+l4MPPji1tbXZZ599cuCBByZJrr766nz84x/Pvvvum7Fjx+bLX/5yPvvZz5bz8QAAKkKhWCwWy10EAAAAAFQy7ZwAAAAA0AMhGgAAAAD0QIgGAAAAAD0QogEAAABAD4RoAAAAANADIRoAAAAA9ECIBgAAAAA9EKIBAAAAQA+EaAAAAADQAyEaAAAAAPRAiAYAAAAAPfj/AWyZptVXG9rfAAAAAElFTkSuQmCC", - "text/plain": [ - "
" + "text/html": [ + " \n", + " " + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hovertemplate": "Pre: %{y:.3f}
Rec: %{x:.3f}
Score: %{text:.3f}", + "mode": "lines", + "name": "auc: 0.782", + "showlegend": true, + "text": [ + 0.8999999999999999, + 0.8666666666666667, + 0.8666666666666667, + 0.8666666666666667, + 0.8666666666666667, + 0.8666666666666667, + 0.8666666666666667, + 0.8666666666666667, + 0.8666666666666667, + 0.8666666666666667, + 0.8666666666666667, + 0.8666666666666667, + 0.8333333333333333, + 0.8333333333333333, + 0.8333333333333333, + 0.8333333333333333, + 0.8333333333333333, + 0.8333333333333333, + 0.8333333333333333, + 0.8333333333333333, + 0.8333333333333333, + 0.8333333333333333, + 0.8333333333333333, + 0.7999999999999999, + 0.7999999999999999, + 0.7999999999999999, + 0.7999999999999999, + 0.7999999999999999, + 0.7999999999999999, + 0.7999999999999999, + 0.7999999999999999, + 0.7999999999999999, + 0.7999999999999999, + 0.7999999999999999, + 0.7666666666666666, + 0.7666666666666666, + 0.7666666666666666, + 0.7666666666666666, + 0.7666666666666666, + 0.7666666666666666, + 0.7666666666666666, + 0.7666666666666666, + 0.7666666666666666, + 0.7666666666666666, + 0.7666666666666666, + 0.7333333333333333, + 0.7333333333333333, + 0.7333333333333333, + 0.7333333333333333, + 0.7333333333333333, + 0.7333333333333333, + 0.7333333333333333, + 0.7333333333333333, + 0.7333333333333333, + 0.7333333333333333, + 0.7333333333333333, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.7, + 0.6666666666666666, + 0.6666666666666666, + 0.6666666666666666, + 0.6666666666666666, + 0.6666666666666666, + 0.6666666666666666, + 0.6666666666666666, + 0.6666666666666666, + 0.6666666666666666, + 0.6666666666666666, + 0.6666666666666666, + 0.6333333333333333, + 0.6333333333333333, + 0.6333333333333333, + 0.6333333333333333, + 0.6333333333333333, + 0.6333333333333333, + 0.6333333333333333, + 0.6333333333333333, + 0.6333333333333333, + 0.6333333333333333, + 0.6333333333333333, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "type": "scatter", + "x": [ + 0, + 0.01, + 0.02, + 0.03, + 0.04, + 0.05, + 0.06, + 0.07, + 0.08, + 0.09, + 0.1, + 0.11, + 0.12, + 0.13, + 0.14, + 0.15, + 0.16, + 0.17, + 0.18, + 0.19, + 0.2, + 0.21, + 0.22, + 0.23, + 0.24, + 0.25, + 0.26, + 0.27, + 0.28, + 0.29, + 0.3, + 0.31, + 0.32, + 0.33, + 0.34, + 0.35000000000000003, + 0.36, + 0.37, + 0.38, + 0.39, + 0.4, + 0.41000000000000003, + 0.42, + 0.43, + 0.44, + 0.45, + 0.46, + 0.47000000000000003, + 0.48, + 0.49, + 0.5, + 0.51, + 0.52, + 0.53, + 0.54, + 0.55, + 0.56, + 0.5700000000000001, + 0.58, + 0.59, + 0.6, + 0.61, + 0.62, + 0.63, + 0.64, + 0.65, + 0.66, + 0.67, + 0.68, + 0.6900000000000001, + 0.7000000000000001, + 0.71, + 0.72, + 0.73, + 0.74, + 0.75, + 0.76, + 0.77, + 0.78, + 0.79, + 0.8, + 0.81, + 0.8200000000000001, + 0.8300000000000001, + 0.84, + 0.85, + 0.86, + 0.87, + 0.88, + 0.89, + 0.9, + 0.91, + 0.92, + 0.93, + 0.9400000000000001, + 0.9500000000000001, + 0.96, + 0.97, + 0.98, + 0.99, + 1 + ], + "y": [ + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0.8888888888888888, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ], + "layout": { + "autosize": true, + "height": 600, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Precision-Recall" + }, + "width": 1200, + "xaxis": { + "range": [ + -0.01, + 1.01 + ], + "showspikes": true, + "title": { + "text": "Recall" + } + }, + "yaxis": { + "range": [ + -0.01, + 1.01 + ], + "showspikes": true, + "title": { + "text": "Precision" + } + } + } + }, + "text/html": [ + "
" ] }, "metadata": {}, @@ -72,13 +1291,13 @@ ], "source": [ "threshold_iou = 0.5\n", - "iouType = 'segm'\n", + "iouType = \"segm\"\n", "\n", "cocoGt = COCO(prepared_coco_in_dict)\n", "cocoDt = cocoGt.loadRes(prepared_anns)\n", "\n", "cur = Curves(cocoGt, cocoDt, iou_tresh=threshold_iou, iouType=iouType)\n", - "cur.plot_pre_rec(plotly_backend=False)" + "cur.plot_pre_rec()" ] }, { @@ -89,9 +1308,1229 @@ "outputs": [ { "data": { - "image/png": "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smnTJueIlRcuXND3339/Q9sDAFdBwQKAMqZLly5yc3PT+fPntWDBgutat3r16pKkM2fOFHj2Yv/+/bmWLWk591ClpaXlO//gwYMFrhseHq7hw4frk08+0ZEjR7R582bVqVNHW7Zs0WuvvXbNfeccY84x56e034/fi4uLk5ubmxYuXCipaJcHLly4UBkZGerZs6deffVVNWjQQP7+/s5CuHfv3hLNfC2nT59Wv379dOXKFQ0cONBZJAv7dw0AZQUFCwDKmIiICD300EOSpJEjR17z/qOTJ08677UJCQlxXgI4c+bMPMtaluWcfs8995gLXYic4pLfc6O+++47HT58uMjbatasmf72t79JkrZv337N5du2bSvp1yHCcwbO+K1t27Zp+/btcnNzU5s2bYqcw6SwsDB1795dQUFBuuuuu9SiRYtrrpPzO1GjRo088yzLcj5H7fdyLtHL7xlVpuQMbnHkyBENGDBACQkJGjlypM6dO6e+ffvmeX4ZAJQ1FCwAKIPefvtt1a5dW8nJyWrVqpXWrl2bZ5nLly8rISFBjRo1ylVennrqKUnS//zP/2jHjh3O6ZZl6aWXXtL27dtVsWJFDRkypOQPRL8OliBJEyZMyHXP0oEDBxQbG5vvZWyfffaZVq9enefywaysLC1dulRS/uXi91q1aqUWLVooIyNDjzzyiC5evOicd/r0aT3yyCOSpH79+ik0NPT6D86Q//znPzp9+rQ2bNhQpOVzBtmYP3++jh075pyenZ2tsWPHav369fmuV7lyZXl6eur48ePFHjjkWl555RUtXbpUt912m959913ntLvvvlubNm3SqFGjSmS/AFBaGOQCAMqgwMBArVu3Tn379lVSUpJat26tmjVrqkGDBqpQoYJOnDihzZs3Kz09Xf7+/qpWrZpz3UceeUTr16/XRx99pKZNmyomJsb5oOE9e/bI29tbs2fPdg6mUdLGjBmj+fPna8mSJapTp46aNWumU6dOacuWLYqOjlbLli3zFIJVq1bprbfe0i233KJGjRopODhYaWlp2rhxo06ePKnq1asX+T/UZ8+erXbt2unzzz9XzZo11aZNG+eDhlNTU9W4cWNNnTq1JA69xHTt2lVNmjTRt99+qzp16igmJkY+Pj7atGmTjh49qtGjR+vVV1/Ns56Hh4e6deum+fPnq2HDhmrVqpUqVKggSfrXv/51w7lWr16tsWPHqkKFCpo3b55zWHx3d3fNmTNHjRo10uTJk9W2bVt17979hvcHAHbgDBYAlFHBwcFauXKlvvjiCw0YMEDlypXTihUrNH/+fO3cuVN33323Jk+erOTkZDVv3ty5nsPhUGJiombPnq1WrVrp22+/1fz583Xx4kXFxcVp27Ztuv/++0vtOGrWrKn169erV69eSktL06JFi3TixAk999xzWrJkSZ7nXEm/3pf0zDPPKCoqSjt37tS8efO0YcMGhYaG6uWXX9aOHTsUEhJSpP3XqlVLW7du1bPPPqugoCAtWrRIX375pSIiIjRp0iStXbtWgYGBpg+7RLm7uyspKUljxoxR9erVtWLFCiUlJalRo0basGGDOnXqVOC6H3zwgR555BE5HA7Nnz9f06dP1/Tp028406lTp/TQQw8pOztb77zzjm677bZc88PCwjRz5kznowIOHDhww/sEADs4rBsZQggAAAAA4MQZLAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBB3uwMAAHILDAyUw+HIM93hcKh8+fKqXbu24uLiNHDgQBvSAQCAwlCwAMDFjB07VhMnTtT999+v5s2bS5I2b96spUuX6u9//7uSk5M1bNgwXblyRUOGDLE5LQAA+C2HZVmW3SEAAP+vd+/euu+++/Too4/mmv7BBx9o+fLl+vTTT/X222/rww8/1Pfff29TSgAAkB/uwYJLSUxMVGZmZp7ply9fVmJiog2JgNK3bNky3XvvvXmmt2/fXsuWLZMkde7cWfv37y/taAAA4BooWHApAwcOVEpKSp7paWlp3G+Cm0alSpW0cOHCPNMXLlyoSpUqSZIuXLggPz+/0o4GAACugXuw4FIsy8r35v4jR44oICDAhkRA6XvhhRc0bNgwrVy50nkP1pYtW7RkyRK9//77kqQvv/xSMTExdsYEAAD54B4suIRGjRrJ4XBox44duv322+Xu/v/dPzs7W8nJyerUqZPmzp1rY0qg9Kxbt05Tp07Vnj17JEl169bV8OHD1bJlS5uTAQCAwnAGCy6hR48ekqTt27erY8eO8vX1dc7z9PRUeHi4evfubVM6oPRFR0crOjra7hgAAOA6cQYLLmXWrFnq27evypcvb3cUwFbZ2dn673//q127dkmSbr/9dnXr1k3lypWzORkAACgMBQsAXMzPP/+szp0765dfflHdunUlSXv27FFoaKgWL16siIgImxMCAICCULDgUrKzs/Xmm29q7ty5OnTokC5fvpxr/tmzZ21KBpSezp07y7Is/fvf/3aOGnjmzBn1799fbm5uWrx4sc0JAQBAQRimHS5lwoQJio+PV9++fZWSkqInn3xSvXr1kpubm8aPH293PKBUrFq1Sq+99pqzXElSUFCQJk2apFWrVtmYDCh9lmWJvwUDKEsY5AIu5d///remTZumBx54QOPHj9dDDz2kiIgINWjQQBs3btQ//vEPuyMCJc7Ly0tpaWl5pqenp8vT09OGREDpmz59ut58803t3btXkhQZGanHH39cgwcPtjkZUHpWrFihFStW6OTJk7p69WqueQkJCTalwrVwBgsu5fjx46pfv74kydfX1/nQ4S5dunBZFG4aXbp00dChQ7Vp0ybnX+83btyoRx99VN26dbM7HlDixo4dqxEjRqhr166aN2+e5s2bp65du+qJJ57Q2LFj7Y4HlIoJEyaoQ4cOWrFihU6fPq1z587l+oHr4gwWXEpISIiOHTumsLAwRUREaPny5WrcuLG2bNkiLy8vu+MBpWLKlCmKjY3V3XffLQ8PD0lSVlaWunfvrsmTJ9sbDigF7733nqZNm6aHHnrIOa1bt25q0KCBhg8frhdffNHGdEDpeP/99zVz5kw9/PDDdkfBdaJgwaX07NlTK1asUIsWLTR8+HD1799f06dP16FDh/TEE0/YHQ8oFRUrVtTnn3+un3/+2TlMe7169VS7dm2bkwGlIysrS02bNs0zvUmTJrpy5YoNiYDSd/nyZR4uX0YxiiBc2saNG7V+/XpFRkaqa9eudscBSsyTTz5Z5GXj4+NLMAlgv+HDh8vDwyPP7/pTTz2ljIwMvfPOOzYlA0rP6NGj5evrqxdeeMHuKLhOFCy4lFdeeUW33nqrBg0alGt6QkKCTp06pdGjR9uUDChZ99xzT67XW7du1ZUrV5zPwfrpp59Urlw5NWnSRF9//bUdEYFSM3z4cCUmJio0NFR33XWXJGnTpk06dOiQBgwY4Lx0VuIPDvjjGjFihBITE9WgQQM1aNAg1++9xO++K6NgwaWEh4dr9uzZeU6Jb9q0Sf369VNycrJNyYDSEx8fr6SkJM2aNUuBgYGSpHPnzmngwIFq3bq1Ro4caXNCwLzvvvtOd9xxh9zc3PL8waEgDoeDPzjgD6WonwN+910bBQsupXz58tq1a5dq1qyZa/r+/ft122236dKlSzYlA0pP9erVtXz5ct1+++25pv/www/q0KGDjh49alMyoOSUK1dOx44dU3BwsGrVqqUtW7YoKCjI7lhAqeJz8MfAMO1wKaGhoVq3bl2e6evWrVO1atVsSASUvtTUVJ06dSrP9FOnTuX7fCzgj6BixYrOqxQOHDiQ55k/wM2Az8EfA6MIwqUMGTJEjz/+uLKystSuXTtJvz5kb9SoUVwWhZtGz549NXDgQL3xxhtq3ry5pF8vk3366afVq1cvm9MBJaN3796KiYlR1apV5XA41LRpU5UrVy7fZffv31/K6YDSwefgj4FLBOFSLMvSM888oylTpujy5cuSfr1scPTo0TxcEjeNixcv6qmnnlJCQoKysrIkSe7u7vrrX/+q119/XT4+PjYnBErG0qVL9fPPP+sf//iHXnzxRfn5+eW73IgRI0o5GVB6+ByUfRQsuKT09HTt2rVL3t7eioyM5CHDuClduHBB+/btkyRFRERQrHDTGDhwoKZMmVLgf1gCNwM+B2UXBQsAAAAADGGQCwAAAAAwhIIFAAAAAIZQsOCyMjMzNX78eGVmZtodBbANnwOAzwEg8TkoS7gHCy4rNTVVAQEBSklJkb+/v91xAFvwOQD4HAASn4OyhDNYAAAAAGAIBQsAAAAADHG3O4Aru3r1qo4ePSo/Pz85HA6749x0UlNTc/0TuBnxOQD4HAASnwNXYFmW0tLSVK1aNbm5FXyeinuwCnHkyBGFhobaHQMAAACAizh8+LBCQkIKnM8ZrELkPDn709XfyceXp2jj5tS8ZiW7IwC225x81u4IgO3Cb6lgdwTAVulpaWp6e21nRygIBasQOZcF+vj6yecabyTwR8VIRYDk45dldwTAdn7+PnZHAFzCtW4dYpALAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCy4nI/en6whve5Vh4Y11LVFlJ4d9rAO7d9rdywAQCnj+wCQNq5bq9i+vdU4qqaqV/TW0kUL7I6Ea6BgweVs37xePf/yV30wb5nenDlfV7Ky9OTAPsq4eMHuaACAUsT3ASBdvHhBt9Wvr4mvT7Y7CorI3e4ApWH8+PH673//q+3bt9sdBUXwRsLcXK/HvDpV3e6K0p4fdqhh85Y2pQIAlDa+DwCp3X0d1e6+jnbHwHXgDBZc3oX0VEmSf8VAm5MAAOzE9wGAsqDMFKyrV6/qtddeU+3ateXl5aWwsDBNnDhRkjR69GjVqVNHFSpUUK1atfTCCy8oKytLkjRz5kxNmDBBO3bskMPhkMPh0MyZM208ElyPq1evaspLz6l+kxaqVaee3XEAADbh+wBAWVFmLhF89tlnNW3aNL355ptq1aqVjh07pt27d0uS/Pz8NHPmTFWrVk3ff/+9hgwZIj8/P40aNUp9+/bVDz/8oKVLl+qrr76SJAUEBOS7j8zMTGVmZjpfp6amlvyBoVDx40cpee9uvfO/i+2OAgCwEd8HAMqKMlGw0tLS9NZbb2nq1KmKjY2VJEVERKhVq1aSpOeff965bHh4uJ566inNmTNHo0aNkre3t3x9feXu7q4qVaoUup9XXnlFEyZMKLkDwXV5c8JobVi5XG/PXqjgqtXsjgMAsAnfBwDKkjJxieCuXbuUmZmp9u3b5zv/k08+UXR0tKpUqSJfX189//zzOnTo0HXv59lnn1VKSorz5/DhwzcaHcVgWZbenDBaq79crMkffaZqoTXsjgQAsAHfBwDKojJxBsvb27vAeRs2bNBf/vIXTZgwQR07dlRAQIDmzJmjN95447r34+XlJS8vrxuJCgPix4/SVws/1cvvfaQKPr46c+qEJMnXz19e5Qv+XQAA/LHwfQBIF9LTlbx/n/P1oYMH9MN3OxQYGKjqoWE2JkNBykTBioyMlLe3t1asWKHBgwfnmrd+/XrVqFFDzz33nHPawYMHcy3j6emp7OzsUsmKG/ff2TMkSf/o3z3X9Gcnva3OvR+yIxIAwAZ8HwDSjm1b1afr/w/TPuG50ZKkPg/11+T3ptkVC4UoEwWrfPnyGj16tEaNGiVPT09FR0fr1KlT+vHHHxUZGalDhw5pzpw5atasmRYvXqzPPvss1/rh4eFKTk7W9u3bFRISIj8/P85UubA1e0/bHQEA4AL4PgCklq3b6JfzGXbHwHUoE/dgSdILL7ygkSNHauzYsapXr5769u2rkydPqlu3bnriiSf02GOPqWHDhlq/fr1eeOGFXOv27t1bnTp10j333KPKlSvrf//3f206CgAAAAB/ZA7Lsiy7Q7iq1NRUBQQEaOnWZPn4+dkdB7DF3bWC7I4A2G7D/jN2RwBsV6uyj90RAFulpaYqKuxWpaSkyN/fv8DlyswZLAAAAABwdRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQd9MbTE5O1nfffacaNWqoYcOGpjcPAAAAAC6rWGewFixYoF69emnz5s25pr/++uuqU6eOevXqpSZNmmjQoEFGQgIAAABAWVCsgpWYmKilS5eqXr16zmm7d+/WM888I8uydOedd6pChQqaNWuWFi5caCwsAAAAALiyYhWsbdu26c4775Sfn59z2r///W9J0rvvvqutW7dqy5YtKleunD788EMzSQEAAADAxRWrYJ0+fVrVq1fPNS0pKUne3t6Ki4uTJEVFRalVq1b68ccfbzgkAAAAAJQFxSpYly5dUrly5Zyvs7OztXXrVrVo0UKenp7O6dWqVdPx48dvPCUAAAAAlAHFKljBwcHau3ev8/XGjRuVkZGh6OjoXMtlZGTIx8fnxhICAAAAQBlRrILVsmVL7dixQ3PmzFFKSopefvllORwO3XvvvbmW27Vrl6pVq2YkKAAAAAC4umIVrNGjR8vd3V1/+ctfVKlSJX3xxRdq3Lix2rRp41zm8OHD2r17t5o1a2YsLAAAAAC4smIVrMaNG2vJkiWKiYlRvXr1FBcXp0WLFuVaZu7cuQoICFD79u2NBAUAAAAAV+ewLMuyO4SrSk1NVUBAgJZuTZbPb4akB24md9cKsjsCYLsN+8/YHQGwXa3K3FePm1taaqqiwm5VSkqK/P39C1yuWGewAAAAAAB5UbAAAAAAwBD3oizUrl27Yu/A4XBoxYoVxV4fAAAAAMqKIhWspKSkYu/A4XAUe10AAAAAKEuKVLBWrlxZ0jkAAAAAoMwrUsGKiYkp6RwAAAAAUOYxyAUAAAAAGELBAgAAAABDinSJYEGOHTumzz//XHv27FFqaqrye2axw+HQ9OnTb2Q3AAAAAFAmFLtgvf3223r66aeVlZXlnJZTsHJGDrQsi4IFAAAA4KZRrEsEV6xYoREjRqh8+fJ65plndPfdd0uSPvjgA40cOVLh4eGSpMcff1wJCQnGwgIAAACAKytWwXrrrbfkcDi0bNkyTZw4UZGRkZKkIUOG6PXXX9fOnTsVGxurhIQEtW7d2mhgAAAAAHBVxSpYmzdvVuPGjdWiRYt853t5eem9995T+fLl9eKLL95QQAAAAAAoK4pVsM6dO6eIiAjnaw8PD0lSRkaGc5qXl5dat26tFStW3GBEAAAAACgbilWwKlWqpAsXLjhfBwYGSpIOHTqUa7ns7GydOXPmBuIBAAAAQNlRrIIVFhamw4cPO1/fcccdsixLixYtck5LT0/XmjVrFBIScuMpAQAAAKAMKNYw7TExMXrzzTd14sQJ3XrrrXrggQfk4+OjMWPG6Pjx4woLC9OsWbN09uxZ9evXz3RmAAAAAHBJxSpYffr00bZt27R9+3Z17NhRlSpVUnx8vB599FHFx8dL+vUZWOHh4ZowYYLRwAAAAADgqopVsJo1a6Yvv/wy17QhQ4aoSZMmmjdvns6ePat69epp4MCBCggIMBIUAAAAAFxdsQpWQRo3bqzGjRub3CQAAAAAlBnFGuQCAAAAAJAXBQsAAAAADCnWJYLlypUr8rIOh0NXrlwpzm4AAAAAoEwpVsGyLKtElgUAAACAsqxYlwhevXo135/s7Gzt379fU6ZMUWBgoMaNG6erV6+azgwAAAAALsnoKIIOh0Ph4eF67LHHdMcdd+jee+/VHXfcod69e5vcDQAAAAC4pBIb5KJt27Zq1KiR88HDAAAAAPBHZ/QM1u/VqlVLX3zxRUnuolQ0r1lJ/v7+dscAbLFs7fd2RwBs17FVfbsjAABs5m1dLtJyJTpM+969exnkAgAAAMBNo0QK1pUrVzRx4kRt375djRo1KoldAAAAAIDLKdYlgu3atStwXlpamvbv36/z58/Lzc1NY8aMKXY4AAAAAChLilWwkpKSrrlMZGSkJk2apE6dOhVnFwAAAABQ5hSrYK1cubLAeZ6enqpevbrCwsKKHQoAAAAAyqJiFayYmBjTOQAAAACgzCvWIBeJiYlav379NZfbuHGjEhMTi7MLAAAAAChzilWw4uLi9K9//euay02fPl0DBw4szi4AAAAAoMwp0edg8QwsAAAAADeTEi1YJ0+eVIUKFUpyFwAAAADgMoo8yMXq1atzvT5+/HieaTmuXLmiH3/8UcuXL1f9+vVvLCEAAAAAlBFFLlht27aVw+Fwvl62bJmWLVtW6DqWZWnYsGHFTwcAAAAAZUiRC1abNm2cBWvVqlUKDg5WVFRUvst6enoqJCREvXv3VufOnc0kBQAAAAAXV+SClZSU5Pzfbm5uuv/++5WQkFASmQAAAACgTCrWg4ZXrlypKlWqmM4CAAAAAGVasQpWTEyM6RwAAAAAUOYVa5j2pUuXql27dvr6668LXGbFihVq166dvvzyy2KHAwAAAICypFgFa8aMGdq8ebOaNWtW4DLNmzfXpk2bNHPmzOJmAwAAAIAypVgF65tvvlHDhg3l5+dX4DJ+fn5q1KiRNm/eXOxwAAAAAFCWFKtgHTt2TGFhYddcLjQ0VMeOHSvOLgAAAACgzClWwfL09FRaWto1l0tPT5ebW7F2AQAAAABlTrHaT2RkpNatW6eLFy8WuMzFixe1bt061apVq9jhAAAAAKAsKVbB6tq1q86fP6/HHntMlmXlmW9ZloYPH66UlBR17979hkMCAAAAQFngsPJrSNdw/vx53XHHHTp27JgaNWqkQYMGKSoqSpK0e/duJSQkaNu2bapSpYq+//57VapUyXjw0pCamqqAgACdPZcif39/u+MAtli29nu7IwC269iqvt0RAAA2S01NVaXAAKWkFN4NivWg4YoVK2rx4sXq2rWrtm7dqm3btuWab1mWQkJCtGDBgjJbrgAAAADgehWrYEnSnXfeqd27d2vatGlatmyZDh48KEkKCwtTp06dNHjwYPn4+BgLCgAAAACurliXCBbFmTNnlJiYqISEBH3/fdm8xIhLBAEuEQQkLhEEAJTwJYIFsSxLS5cu1fTp07Vo0SJlZWWZ3DwAAAAAuDQjBSs5OVkJCQmaOXOmjh496hxZsHHjxhowYICJXQAAAACAyyt2wcrMzNT8+fM1ffp0rV69WpZlybIsORwOjRo1SgMGDNBtt91mMisAAAAAuLTrLljffvutpk+frjlz5iglJUWWZcnd3V2dO3fWd999p4MHD2rSpEklkRUAAAAAXFqRCta5c+f08ccfa/r06c4BKyzLUlRUlAYNGqQBAwYoODhYrVu3do4mCAAAAAA3myIVrKpVqyorK0uWZcnX11d9+/bVoEGDdPfdd5d0PgAAAAAoM4pUsC5fviyHw6GQkBB99NFHiomJKelcAAAAAFDmuBVlofr168uyLB05ckTt2rVTw4YNNWXKFJ05c6ak8wEAAABAmVGkgrVjxw5t3rxZQ4cOlZ+fn7777js98cQTql69uvr27atly5aphJ5XDAAAAABlhsO6zmaUkZGhuXPnavr06Vq7du2vG3E4VL16dWVkZOjs2bPKzs4ukbClLTU1VQEBATp7rvCnNQN/ZMvWfm93BMB2HVvVtzsCAMBmqampqhQYoJSUwrtBkc5g/Za3t7diY2O1evVq7dmzR6NGjdKtt96qI0eOOC8ZjI6O1ocffqiUlJTiHwEAAAAAlDHXXbB+KzIyUpMmTdLhw4f13//+V126dJGbm5s2bNigYcOGqWrVqurXr5+prAAAAADg0m6oYOUoV66cunXrpgULFujw4cOaOHGiIiIidOnSJc2bN8/ELgAAAADA5RkpWL9VpUoVPfvss/rpp5+0cuVK9e/f3/QuAAAAAMAlFek5WMUVExPDM7MAAAAA3DSMn8ECAAAAgJsVBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQ9ztDlBUbdu2VcOGDTV58mS7owBAiVv830+05PO5OnH8qCSpRniEHop9RE3vam1zMgAAUJgyU7AA4GZyS+VbFffI46oWEiZZlr5aukD/89wITfnXXNWoWdvueAAAoAAULABwQS2i2+Z6HTvkH1ry+Vzt3vkdBQsAABfmkvdgXbhwQQMGDJCvr6+qVq2qN954I9f8c+fOacCAAQoMDFSFChV0//33a+/evbmWmTZtmkJDQ1WhQgX17NlT8fHxqlixYikeBQCYkZ2drVUrvtClSxmqd/uddscBAACFcMmC9fTTT2vVqlX6/PPPtXz5ciUlJWnr1q3O+XFxcfrmm2+0YMECbdiwQZZlqXPnzsrKypIkrVu3To8++qhGjBih7du367777tPEiRPtOhwAKJYD+35S704t1OO+pnon/iU9/9JkhYVH2B0LAAAUwmFZlmV3iN9KT09XUFCQPv74Y/Xp00eSdPbsWYWEhGjo0KH6+9//rjp16mjdunVq2bKlJOnMmTMKDQ3VrFmz1KdPH/Xr10/p6elatGiRc7v9+/fXokWLdP78+QL3nZmZqczMTOfr1NRUhYaG6uy5FPn7+5fMAQMubtna7+2OcNPKysrSqRPHdOFCutat+lLLFv1Hr05JoGTZoGOr+nZHAADYLDU1VZUCA5SSUng3cLkzWPv27dPly5fVokUL57RKlSqpbt26kqRdu3bJ3d091/ygoCDVrVtXu3btkiTt2bNHzZs3z7Xd37/OzyuvvKKAgADnT2hoqIlDAoBi8fDwULWQMEXWvU1xQ0eoZu06+nz+v+2OBQAACuFyBctOzz77rFJSUpw/hw8ftjsSADhZV68qK+uy3TEAAEAhXK5gRUREyMPDQ5s2bXJOO3funH766SdJUr169XTlypVc88+cOaM9e/botttukyTVrVtXW7ZsybXd37/Oj5eXl/z9/XP9AIAdZn74ln7Y8Y1OHPtFB/b9pJkfvqXvt3+je+59wO5oAACgEC43TLuvr6/++te/6umnn1ZQUJCCg4P13HPPyc3t1y4YGRmp7t27a8iQIfrggw/k5+enZ555RtWrV1f37t0lScOHD1ebNm0UHx+vrl276uuvv9YXX3whh8Nh56EBQJGdP3dWb7z8vM6eOSUfH1+FR9TR/7z+vho1u9vuaAAAoBAuV7Ak6fXXX1d6erq6du0qPz8/jRw5UikpKc75M2bM0IgRI9SlSxddvnxZbdq00ZIlS+Th4SFJio6O1vvvv68JEybo+eefV8eOHfXEE09o6tSpdh0SAFyXx0dPsDsCAAAoBpcbRbCkDBkyRLt379aaNWuKvE5qaqoCAgIYRRA3NUYRBBhFEABQ9FEEXfIMlgn//Oc/dd9998nHx0dffPGFZs2apXfffdfuWAAAAAD+wP6wBWvz5s167bXXlJaWplq1amnKlCkaPHiw3bEAAAAA/IH9YQvW3Llz7Y4AAAAA4CbjcsO0AwAAAEBZRcECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAAAAABhCwQIAAAAAQyhYAAAAAGAIBQsAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMAQChYAAAAAGELBAgAAAABDKFgAAAAAYAgFCwAAAAAMoWABAAAAgCEULAAAAAAwhIIFAAAAAIa42x3AlVmWJUlKTU21OQlgn4sX0u2OANiO7wEAQM53QU5HKAgFqxBpaWmSpPAaoTYnAQAAAOAK0tLSFBAQUOB8h3WtCnYTu3r1qo4ePSo/Pz85HA6749x0UlNTFRoaqsOHD8vf39/uOIAt+BwAfA4Aic+BK7AsS2lpaapWrZrc3Aq+04ozWIVwc3NTSEiI3TFuev7+/vwfCW56fA4APgeAxOfAboWducrBIBcAAAAAYAgFCwAAAAAMoWDBZXl5eWncuHHy8vKyOwpgGz4HAJ8DQOJzUJYwyAUAAAAAGMIZLAAAAAAwhIIFAAAAAIZQsAAAAADAEAoWAKBYwsPD5XA4cv14eXkpLCxMffv21Zo1a+yOKEkaP368HA6Hxo8fn2v6zJkz5XA4FBcXV+IZDhw4IIfDofDw8BLfFwDAXhQsAMANiY6OVmxsrGJjY3X//ffr6tWrmjt3rmJiYhQfH293vFKRUzYPHDhgdxQAgM3c7Q4AACjbBg8enOss0KVLl/TII48oMTFRo0aNUpcuXVSnTh37AhagZ8+euuuuuxQQEFDi+6pevbp27dolDw+PEt8XAMBenMECABhVvnx5vfPOO/Lx8VF2drb+85//2B0pXwEBAYqKilLVqlVLfF8eHh6KiopSREREie8LAGAvChYAwDhfX1/VrVtXkpyXzeXcpyVJM2bM0N13362AgIA8l9YdPXpUTz75pOrVq6cKFSrIz89PzZo109SpU3XlypV895eRkaHx48crMjJSXl5eqlq1qmJjY3Xo0KECM17rHqxffvlFTz/9tOrXry8/Pz/5+PioTp06iouL0/r163Nt4+DBg5KkmjVr5ronLSkpyfkeFHYP1pEjRzR8+HBFRkaqfPnyCggIUHR0tD744ANlZ2cXmv3ChQt69tlnVbt2bXl5ealKlSqKjY3VL7/8ku++vvrqK3Xt2lW33nqrPDw8FBgYqMjISPXv31+rV68u8P0CABQNlwgCAEpEamqqJMnLyyvX9OHDh+vdd99Vy5Yt9cADD2j//v3O4rV69Wr16NFD586dU3h4uO677z5lZmZq8+bNGj58uBYuXKhFixblutTu4sWLat++vTZu3CgfHx916NBB3t7eWrZsmRYvXqwHHnjgurOvWLFCDz74oM6fP6/g4GC1b99enp6eOnDggGbPni1JatmypWrXrq3Y2FjNnz9fFy5cUO/eveXr6+vcTpUqVa65ry1btqhTp046e/aswsLC1KNHD6WkpCgpKUnr16/XZ599pgULFsjT0zPPuikpKWrZsqUOHTqk1q1b64477tCGDRuUmJioVatWaceOHbkugZw1a5YGDhwoSWrevLnuueceZWRk6MiRI5ozZ45uueUWtWnT5rrfLwDAb1gAABRDjRo1LEnWjBkz8szbsWOH5ebmZkmyEhISLMuyLEmWJMvf39/asGFDnnWOHTtmBQUFWQ6Hw3r33Xet7Oxs57zTp09b7dq1syRZEyZMyLXeU089ZUmyoqKirF9++cU5/cKFC1b37t2d+x03blyu9WbMmGFJsmJjY3NNP3TokBUQEGBJsp555hkrMzMz1/wTJ05Ya9asyfe9SE5Ozve9Sk5OtiRZNWrUyDX90qVLznUfffRR6/Lly855+/bts8LDwy1J1pgxY/LNLsnq2LGjlZKS4px39uxZq2HDhpYk6+WXX861Xs2aNS1JefLnHNfWrVvzzQ8AKDouEQQAGJOSkqIlS5aoV69eunr1qqpVq6Y//elPuZZ56qmndNddd+VZd/LkyTpz5oz+/ve/a9iwYXJz+/+vqKCgICUmJsrDw0NTp06VZVmSfr008IMPPpAkvfnmm6pWrZpznQoVKuj9999X+fLlr+sY4uPjlZKSoq5du+qVV17Jc+YoODhYrVq1uq5tFmTevHk6ePCgqlWrpsmTJ+c6M1erVi3985//lCS9/fbbunTpUp71fXx8NGPGDPn7+zunBQYG6plnnpH06+WAv3XixAkFBATkmz84OFiNGjUyclwAcDOjYAEAbsjAgQOd9xxVrFhRDzzwgPbt26eIiAgtWbJEPj4+uZZ/8MEH893O4sWLJUl9+/bNd3716tUVGRmpU6dOae/evZKkrVu3Ki0tTbfccos6deqUZ50qVaqoQ4cO13U8S5culSQNHTr0utYrjpx7tPr165fnUkpJ6tWrlwIDA5WWlqZvv/02z/ymTZvmO0hHvXr1JCnPfVjNmzdXSkqKBgwYoG+//VZXr141cBQAgN/iHiwAwA2Jjo5W7dq1JUmenp4KDg7WXXfdpU6dOsndPe/XTEEDPezfv1+S1Lp162vu89SpU6pTp46OHDlS6DalXweeuB45A1ZERUVd13rFkVOACsrocDhUs2ZNnTt3Lt9BK8LCwvJdL+eM1u/Per377rvq0qWLPvroI3300UfOAUTatWunhx9+uMDtAQCKjoIFALghv38O1rV4e3vnOz3nbMqDDz6Y56zX7wUFBRV5f39kv72Msijq1aunPXv2aPny5fr666+1fv16rVmzRl9//bVefPFFTZ8+Xf379y+htABwc6BgAQBcQmhoqPbu3avRo0eradOmRVqnevXqkpRrmPffK2xefsLCwrRnzx7t3r3beWaupOTkzzl7l5/k5ORcy94od3d3de7cWZ07d5b062iP8fHxmjBhgh555BH17NnzmgUXAFAw7sECALiE+++/X5I0d+7cIq/TpEkT+fr66vTp01q+fHme+SdOnMh3emFy7uWaNm1akdfJGQijoOd0FaRt27aSpE8++STfQSw+++wznTt3Tn5+fmrSpMl1bbuo/P39NX78eFWsWFEXL17UTz/9VCL7AYCbBQULAOASnn76aVWsWFHx8fF64403dPny5TzLJCcn6+OPP3a+9vb2dg5G8cQTT+jYsWPOeRkZGRo2bJgyMjKuK8eTTz4pPz8/LViwQM8//7yysrJyzT958qTWrl2ba1pISIgk6ccff7yuffXp00dhYWHOhyv/tqAlJydr5MiRkn59dtj1job4excvXlR8fLxOnTqVZ96aNWt0/vx5lStXznksAIDioWABAFxCSEiIPv/8cwUGBuqpp55SaGio2rdvr/79+6tr166qXbu2atWqpalTp+Za78UXX1Tz5s21c+dO1alTR926ddOf/vQn1apVS6tXr9aAAQOuK0dYWJjmz58vPz8/TZw4UaGhoerZs6f+9Kc/qUWLFgoJCdG//vWvXOv07t1bktS/f3/17t1bgwcP1uDBg7Vnz55C9+Xl5aX58+erUqVKeu+991S7dm3169dPDzzwgG677TYlJyerY8eOGjdu3HUdQ34uX76skSNHqkqVKmrYsKH69OmjP//5z2rZsqViYmIkSc8995wqV658w/sCgJsZ92ABAFxGmzZt9OOPP2rq1KlavHixtmzZoszMTAUHByssLMxZYH7Lx8dHK1eu1KRJkzR79mwtW7ZMgYGBuvfee/XSSy9p5syZ152jQ4cO+uGHHxQfH6+lS5dq6dKlcnd3V7Vq1fTwww9ryJAhuZYfNmyY0tLS9PHHH2vJkiXOy/369++vunXrFrqvZs2aafv27Xr11Vf1xRdf6LPPPpOXl5caNWqkAQMGaPDgwfmOxni9fH199f7772vVqlXatm2bvvzyS12+fFnVqlVTr1699Le//U3t2rW74f0AwM3OYeU8rREAAAAAcEO4RBAAAAAADKFgAQAAAIAhFCwAAAAAMISCBQAAAACGULAAAAAAwBAKFgAAAAAYQsECAAAAAEMoWAAAAABgCAULAAAAAAyhYAEAAACAIRQsAAAAADCEggUAAAAAhlCwAAAAAMCQ/wMTERwVuNrvWgAAAABJRU5ErkJggg==", - "text/plain": [ - "
" + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "colorscale": [ + [ + 0, + "rgb(247,251,255)" + ], + [ + 0.125, + "rgb(222,235,247)" + ], + [ + 0.25, + "rgb(198,219,239)" + ], + [ + 0.375, + "rgb(158,202,225)" + ], + [ + 0.5, + "rgb(107,174,214)" + ], + [ + 0.625, + "rgb(66,146,198)" + ], + [ + 0.75, + "rgb(33,113,181)" + ], + [ + 0.875, + "rgb(8,81,156)" + ], + [ + 1, + "rgb(8,48,107)" + ] + ], + "hovertemplate": "Real: %{y}
Predict: %{x}
Count: %{z:.0f}", + "showscale": false, + "type": "heatmap", + "x": [ + "cloud", + "heart", + "arrow", + "star", + "fp", + "fn" + ], + "y": [ + "cloud", + "heart", + "arrow", + "star" + ], + "z": [ + [ + 2, + 1, + 0, + 0, + 1, + 0 + ], + [ + 1, + 1, + 0, + 0, + 0, + 1 + ], + [ + 0, + 0, + 1, + 0, + 0, + 0 + ], + [ + 0, + 0, + 0, + 2, + 0, + 0 + ] + ] + } + ], + "layout": { + "annotations": [ + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "2", + "x": "cloud", + "xref": "x", + "y": "cloud", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "1", + "x": "heart", + "xref": "x", + "y": "cloud", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "arrow", + "xref": "x", + "y": "cloud", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "star", + "xref": "x", + "y": "cloud", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "1", + "x": "fp", + "xref": "x", + "y": "cloud", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "fn", + "xref": "x", + "y": "cloud", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "1", + "x": "cloud", + "xref": "x", + "y": "heart", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "1", + "x": "heart", + "xref": "x", + "y": "heart", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "arrow", + "xref": "x", + "y": "heart", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "star", + "xref": "x", + "y": "heart", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "fp", + "xref": "x", + "y": "heart", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "1", + "x": "fn", + "xref": "x", + "y": "heart", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "cloud", + "xref": "x", + "y": "arrow", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "heart", + "xref": "x", + "y": "arrow", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "1", + "x": "arrow", + "xref": "x", + "y": "arrow", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "star", + "xref": "x", + "y": "arrow", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "fp", + "xref": "x", + "y": "arrow", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "fn", + "xref": "x", + "y": "arrow", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "cloud", + "xref": "x", + "y": "star", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "heart", + "xref": "x", + "y": "star", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "arrow", + "xref": "x", + "y": "star", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "2", + "x": "star", + "xref": "x", + "y": "star", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "fp", + "xref": "x", + "y": "star", + "yref": "y" + }, + { + "font": { + "color": "white" + }, + "showarrow": false, + "text": "0", + "x": "fn", + "xref": "x", + "y": "star", + "yref": "y" + } + ], + "height": 700, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "Confusion Matrix" + }, + "width": 900, + "xaxis": { + "title": { + "text": "Predicted value" + } + }, + "yaxis": { + "title": { + "text": "Real value" + } + } + } + }, + "text/html": [ + "
" ] }, "metadata": {}, @@ -102,7 +2541,9 @@ "cocoGt = COCO(prepared_coco_in_dict)\n", "cocoDt = cocoGt.loadRes(prepared_anns)\n", "\n", - "results = PreviewResults(cocoGt, cocoDt, iou_tresh=threshold_iou, iouType=iouType)\n", + "results = PreviewResults(\n", + " cocoGt, cocoDt, iou_tresh=threshold_iou, iouType=iouType, useCats=False\n", + ")\n", "results.display_matrix()" ] }, @@ -112,23 +2553,1177 @@ "id": "8106fc0e", "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "WARNING:faster_coco_eval.extra.display:[cat_dog1.jpg] not found!\n", - "Loading default empty image\n", - "WARNING:faster_coco_eval.extra.display:[cat_dog2.jpg] not found!\n", - "Loading default empty image\n", - "WARNING:faster_coco_eval.extra.display:[cat_dog3.jpg] not found!\n", - "Loading default empty image\n" - ] - }, { "data": { - "image/png": "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", - "text/plain": [ - "
" + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hovertemplate": "x: %{x}
y: %{y}
color: [%{z[0]}, %{z[1]}, %{z[2]}]", + "name": "0", + "source": "data:image/jpeg;base64,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", + "type": "image", + "xaxis": "x", + "yaxis": "y" + }, + { + "fill": "toself", + "fillcolor": "rgba(238, 130, 238, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "tp", + "legendgrouptitle": { + "text": "tp" + }, + "line": { + "color": "rgb(238, 130, 238)" + }, + "mode": "lines", + "name": "", + "showlegend": true, + "text": "DT
id=1
category=heart
score=0.63
IoU=1.00", + "type": "scatter", + "x": [ + 32, + 26, + 22, + 25, + 29, + 26, + 26, + 29, + 34, + 37, + 39, + 39, + 36, + 37, + 31, + 30, + 31, + 34, + 37, + 41, + 44, + 46, + 53, + 56, + 56, + 65, + 70, + 76, + 82, + 88, + 93, + 95, + 102, + 107, + 111, + 116, + 117, + 125, + 129, + 130, + 129, + 127, + 128, + 127, + 122, + 119, + 114, + 108, + 102, + 98, + 97, + 91, + 85, + 82, + 77, + 75, + 70, + 66, + 60, + 57, + 53, + 47, + 41, + 37, + 35, + 32, + null + ], + "y": [ + 56, + 60, + 70, + 78, + 81, + 84, + 94, + 99, + 102, + 104, + 106, + 110, + 116, + 120, + 126, + 129, + 133, + 134, + 134, + 131, + 130, + 127, + 124, + 120, + 115, + 111, + 118, + 118, + 118, + 116, + 112, + 108, + 107, + 107, + 102, + 96, + 92, + 84, + 77, + 71, + 65, + 60, + 52, + 42, + 40, + 36, + 28, + 24, + 24, + 26, + 29, + 24, + 24, + 26, + 30, + 28, + 26, + 28, + 34, + 36, + 33, + 32, + 36, + 40, + 43, + 56, + null + ] + }, + { + "fill": "toself", + "fillcolor": "rgba(238, 130, 238, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "tp", + "legendgrouptitle": { + "text": "tp" + }, + "line": { + "color": "rgb(238, 130, 238)" + }, + "mode": "lines", + "name": "", + "showlegend": false, + "text": "DT
id=2
category=cloud
score=0.67
IoU=1.00", + "type": "scatter", + "x": [ + 151, + 145, + 146, + 151, + 159, + 173, + 188, + 198, + 212, + 224, + 235, + 245, + 250, + 252, + 247, + 237, + 223, + 216, + 207, + 203, + 199, + 193, + 185, + 178, + 170, + 161, + 155, + 151, + null + ], + "y": [ + 35, + 52, + 64, + 82, + 99, + 113, + 124, + 131, + 122, + 113, + 101, + 84, + 67, + 51, + 37, + 26, + 25, + 28, + 32, + 40, + 46, + 35, + 29, + 26, + 24, + 26, + 30, + 35, + null + ] + }, + { + "fill": "toself", + "fillcolor": "rgba(238, 130, 238, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "tp", + "legendgrouptitle": { + "text": "tp" + }, + "line": { + "color": "rgb(238, 130, 238)" + }, + "mode": "lines", + "name": "", + "showlegend": false, + "text": "DT
id=3
category=arrow
score=0.70
IoU=1.00", + "type": "scatter", + "x": [ + 4, + 56, + 59, + 60, + 110, + 109, + 60, + 60, + 58, + 4, + 4, + null + ], + "y": [ + 200, + 157, + 156, + 176, + 177, + 224, + 224, + 245, + 246, + 201, + 200, + null + ] + } + ], + "layout": { + "autosize": true, + "height": 700, + "margin": { + "t": 60 + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "image_id=1
image_fn=../tests/dataset/img_3.jpg" + }, + "width": 900, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 1 + ], + "range": [ + 0, + 256 + ] + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "range": [ + 256, + 0 + ] + } + } + }, + "text/html": [ + "
" ] }, "metadata": {}, @@ -136,9 +3731,1175 @@ }, { "data": { - "image/png": "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", - "text/plain": [ - "
" + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hovertemplate": "x: %{x}
y: %{y}
color: [%{z[0]}, %{z[1]}, %{z[2]}]", + "name": "0", + "source": "data:image/jpeg;base64,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", + "type": "image", + "xaxis": "x", + "yaxis": "y" + }, + { + "fill": "toself", + "fillcolor": "rgba(238, 130, 238, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "tp", + "legendgrouptitle": { + "text": "tp" + }, + "line": { + "color": "rgb(238, 130, 238)" + }, + "mode": "lines", + "name": "", + "showlegend": true, + "text": "DT
id=4
category=cloud
score=0.73
IoU=1.00", + "type": "scatter", + "x": [ + 32, + 26, + 22, + 25, + 29, + 26, + 26, + 29, + 34, + 37, + 39, + 39, + 36, + 37, + 31, + 30, + 31, + 34, + 37, + 41, + 44, + 46, + 53, + 56, + 56, + 65, + 70, + 76, + 82, + 88, + 93, + 95, + 102, + 107, + 111, + 116, + 117, + 125, + 129, + 130, + 129, + 127, + 128, + 127, + 122, + 119, + 114, + 108, + 102, + 98, + 97, + 91, + 85, + 82, + 77, + 75, + 70, + 66, + 60, + 57, + 53, + 47, + 41, + 37, + 35, + 32, + null + ], + "y": [ + 56, + 60, + 70, + 78, + 81, + 84, + 94, + 99, + 102, + 104, + 106, + 110, + 116, + 120, + 126, + 129, + 133, + 134, + 134, + 131, + 130, + 127, + 124, + 120, + 115, + 111, + 118, + 118, + 118, + 116, + 112, + 108, + 107, + 107, + 102, + 96, + 92, + 84, + 77, + 71, + 65, + 60, + 52, + 42, + 40, + 36, + 28, + 24, + 24, + 26, + 29, + 24, + 24, + 26, + 30, + 28, + 26, + 28, + 34, + 36, + 33, + 32, + 36, + 40, + 43, + 56, + null + ] + }, + { + "fill": "toself", + "fillcolor": "rgba(238, 130, 238, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "tp", + "legendgrouptitle": { + "text": "tp" + }, + "line": { + "color": "rgb(238, 130, 238)" + }, + "mode": "lines", + "name": "", + "showlegend": false, + "text": "DT
id=5
category=star
score=0.77
IoU=1.00", + "type": "scatter", + "x": [ + 83, + 116, + 100, + 116, + 84, + 65, + 44, + 12, + 27, + 10, + 44, + 64, + 83, + null + ], + "y": [ + 173, + 174, + 202, + 225, + 228, + 253, + 227, + 228, + 201, + 174, + 174, + 147, + 173, + null + ] + }, + { + "fill": "toself", + "fillcolor": "rgba(238, 130, 238, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "tp", + "legendgrouptitle": { + "text": "tp" + }, + "line": { + "color": "rgb(238, 130, 238)" + }, + "mode": "lines", + "name": "", + "showlegend": false, + "text": "DT
id=6
category=heart
score=0.80
IoU=1.00", + "type": "scatter", + "x": [ + 132, + 133, + 144, + 154, + 166, + 178, + 185, + 203, + 223, + 232, + 236, + 238, + 232, + 224, + 211, + 205, + 194, + 188, + 185, + 180, + 174, + 167, + 154, + 141, + 137, + 132, + null + ], + "y": [ + 154, + 176, + 200, + 213, + 226, + 231, + 237, + 228, + 205, + 188, + 172, + 158, + 142, + 133, + 131, + 132, + 139, + 148, + 151, + 143, + 136, + 133, + 130, + 138, + 143, + 154, + null + ] + } + ], + "layout": { + "autosize": true, + "height": 700, + "margin": { + "t": 60 + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "image_id=2
image_fn=../tests/dataset/img_1.jpg" + }, + "width": 900, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 1 + ], + "range": [ + 0, + 256 + ] + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "range": [ + 256, + 0 + ] + } + } + }, + "text/html": [ + "
" ] }, "metadata": {}, @@ -146,9 +4907,1352 @@ }, { "data": { - "image/png": "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", - "text/plain": [ - "
" + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "hovertemplate": "x: %{x}
y: %{y}
color: [%{z[0]}, %{z[1]}, %{z[2]}]", + "name": "0", + "source": "data:image/jpeg;base64,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", + "type": "image", + "xaxis": "x", + "yaxis": "y" + }, + { + "fill": "toself", + "fillcolor": "rgba(0, 0, 255, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "fn", + "legendgrouptitle": { + "text": "fn" + }, + "line": { + "color": "rgb(0, 0, 255)" + }, + "mode": "lines", + "name": "", + "showlegend": true, + "text": "FN
id=8
category=heart", + "type": "scatter", + "x": [ + 73, + 84, + 94, + 103, + 109, + 122, + 130, + 134, + 133, + 134, + 127, + 122, + 109, + 94, + 83, + 78, + 75, + 68, + 62, + 52, + 38, + 28, + 20, + 16, + 14, + 16, + 19, + 21, + 26, + 36, + 45, + 56, + 71, + 73, + null + ], + "y": [ + 144, + 140, + 132, + 126, + 117, + 101, + 82, + 66, + 55, + 45, + 35, + 27, + 21, + 25, + 34, + 43, + 47, + 35, + 28, + 22, + 21, + 24, + 36, + 45, + 56, + 71, + 84, + 92, + 101, + 113, + 123, + 133, + 144, + 144, + null + ] + }, + { + "fill": "toself", + "fillcolor": "rgba(238, 130, 238, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "tp", + "legendgrouptitle": { + "text": "tp" + }, + "line": { + "color": "rgb(238, 130, 238)" + }, + "mode": "lines", + "name": "", + "showlegend": true, + "text": "DT
id=7
category=cloud
score=0.83
IoU=1.00", + "type": "scatter", + "x": [ + 154, + 148, + 144, + 147, + 151, + 148, + 148, + 151, + 156, + 159, + 161, + 161, + 158, + 159, + 153, + 152, + 153, + 156, + 159, + 163, + 166, + 168, + 175, + 178, + 178, + 187, + 192, + 198, + 204, + 210, + 215, + 217, + 224, + 229, + 233, + 238, + 239, + 247, + 251, + 252, + 251, + 249, + 250, + 249, + 244, + 241, + 236, + 230, + 224, + 220, + 219, + 213, + 207, + 204, + 199, + 197, + 192, + 188, + 182, + 179, + 175, + 169, + 163, + 159, + 157, + 154, + null + ], + "y": [ + 34, + 38, + 48, + 56, + 59, + 62, + 72, + 77, + 80, + 82, + 84, + 88, + 94, + 98, + 104, + 107, + 111, + 112, + 112, + 109, + 108, + 105, + 102, + 98, + 93, + 89, + 96, + 96, + 96, + 94, + 90, + 86, + 85, + 85, + 80, + 74, + 70, + 62, + 55, + 49, + 43, + 38, + 30, + 20, + 18, + 14, + 6, + 2, + 2, + 4, + 7, + 2, + 2, + 4, + 8, + 6, + 4, + 6, + 12, + 14, + 11, + 10, + 14, + 18, + 21, + 34, + null + ] + }, + { + "fill": "toself", + "fillcolor": "rgba(238, 130, 238, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "tp", + "legendgrouptitle": { + "text": "tp" + }, + "line": { + "color": "rgb(238, 130, 238)" + }, + "mode": "lines", + "name": "", + "showlegend": false, + "text": "DT
id=8
category=star
score=0.87
IoU=1.00", + "type": "scatter", + "x": [ + 112, + 150, + 169, + 176, + 194, + 238, + 218, + 237, + 236, + 196, + 172, + 151, + 108, + 126, + 109, + 112, + null + ], + "y": [ + 149, + 148, + 120, + 120, + 149, + 149, + 183, + 211, + 215, + 214, + 246, + 215, + 214, + 180, + 151, + 149, + null + ] + }, + { + "fill": "toself", + "fillcolor": "rgba(255, 0, 0, 0.1)", + "hovertemplate": "{text}", + "legendgroup": "fp", + "legendgrouptitle": { + "text": "fp" + }, + "line": { + "color": "rgb(255, 0, 0)" + }, + "mode": "lines", + "name": "", + "showlegend": true, + "text": "FP
id=9
category=cloud
score=0.90", + "type": "scatter", + "x": [ + 14, + 8, + 4, + 7, + 11, + 8, + 8, + 11, + 16, + 19, + 21, + 21, + 18, + 19, + 13, + 12, + 13, + 16, + 19, + 23, + 26, + 28, + 35, + 38, + 38, + 47, + 52, + 58, + 64, + 70, + 75, + 77, + 84, + 89, + 93, + 98, + 99, + 107, + 111, + 112, + 111, + 109, + 110, + 109, + 104, + 101, + 96, + 90, + 84, + 80, + 79, + 73, + 67, + 64, + 59, + 57, + 52, + 48, + 42, + 39, + 35, + 29, + 23, + 19, + 17, + 14, + null + ], + "y": [ + 177, + 181, + 191, + 199, + 202, + 205, + 215, + 220, + 223, + 225, + 227, + 231, + 237, + 241, + 247, + 250, + 254, + 255, + 255, + 252, + 251, + 248, + 245, + 241, + 236, + 232, + 239, + 239, + 239, + 237, + 233, + 229, + 228, + 228, + 223, + 217, + 213, + 205, + 198, + 192, + 186, + 181, + 173, + 163, + 161, + 157, + 149, + 145, + 145, + 147, + 150, + 145, + 145, + 147, + 151, + 149, + 147, + 149, + 155, + 157, + 154, + 153, + 157, + 161, + 164, + 177, + null + ] + } + ], + "layout": { + "autosize": true, + "height": 700, + "margin": { + "t": 60 + }, + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "text": "image_id=3
image_fn=../tests/dataset/img_2.jpg" + }, + "width": 900, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 1 + ], + "range": [ + 0, + 256 + ] + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "range": [ + 256, + 0 + ] + } + } + }, + "text/html": [ + "
" ] }, "metadata": {}, @@ -156,7 +6260,11 @@ } ], "source": [ - "results.display_tp_fp_fn(line_width=20)" + "results = PreviewResults(\n", + " cocoGt, cocoDt, iou_tresh=threshold_iou, iouType=iouType, useCats=False\n", + ")\n", + "\n", + "results.display_tp_fp_fn(data_folder=\"../tests/dataset/\", image_ids=[1, 2, 3])" ] } ], @@ -179,7 +6287,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/examples/eval_example.ipynb b/examples/eval_example.ipynb index a266fb2..b70bd74 100644 --- a/examples/eval_example.ipynb +++ b/examples/eval_example.ipynb @@ -10,7 +10,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "faster_coco_eval.__version__='1.3.3'\n" + "faster_coco_eval.__version__='1.4.0'\n" ] } ], @@ -36,7 +36,7 @@ "def load(file):\n", " with open(file) as io:\n", " _data = json.load(io)\n", - " \n", + "\n", " return _data" ] }, @@ -47,8 +47,8 @@ "metadata": {}, "outputs": [], "source": [ - "prepared_coco_in_dict = load('../tests/data/gt_cat_dog.json')\n", - "prepared_anns = load('../tests/data/dt_cat_dog.json')" + "prepared_coco_in_dict = load(\"../tests/dataset/gt_dataset.json\")\n", + "prepared_anns = load(\"../tests/dataset/dt_dataset.json\")" ] }, { @@ -58,7 +58,7 @@ "metadata": {}, "outputs": [], "source": [ - "iouType = 'segm'\n", + "iouType = \"segm\"\n", "useCats = False" ] }, @@ -76,7 +76,7 @@ "cocoEval.params.maxDets = [len(cocoGt.anns)]\n", "\n", "if not useCats:\n", - " cocoEval.params.useCats = 0 # Выключение labels\n", + " cocoEval.params.useCats = 0 # Выключение labels\n", "\n", "cocoEval.evaluate()\n", "cocoEval.accumulate()\n", @@ -92,9 +92,9 @@ { "data": { "text/plain": [ - "array([ 0.60843942, 0.73833098, 0.73833098, -1. , -1. ,\n", - " 0.60843942, 0.71666667, 0. , 0. , -1. ,\n", - " -1. , 0.71666667])" + "array([ 0.78327833, 0.78327833, 0.78327833, -1. , 1. ,\n", + " 0. , 0.88888889, 0. , 0. , -1. ,\n", + " 1. , 0. ])" ] }, "execution_count": 6, @@ -115,22 +115,22 @@ { "data": { "text/plain": [ - "{'AP_all': 0.6084394153701084,\n", - " 'AP_50': 0.7383309759547382,\n", - " 'AP_75': 0.7383309759547382,\n", + "{'AP_all': 0.7832783278327835,\n", + " 'AP_50': 0.7832783278327836,\n", + " 'AP_75': 0.7832783278327836,\n", " 'AP_small': -1.0,\n", - " 'AP_medium': -1.0,\n", - " 'AP_large': 0.6084394153701084,\n", - " 'AR_all': 0.7166666666666666,\n", + " 'AP_medium': 1.0,\n", + " 'AP_large': 0.0,\n", + " 'AR_all': 0.888888888888889,\n", " 'AR_second': 0.0,\n", " 'AR_third': 0.0,\n", " 'AR_small': -1.0,\n", - " 'AR_medium': -1.0,\n", - " 'AR_large': 0.7166666666666666,\n", - " 'AR_50': 0.8333333333333334,\n", - " 'AR_75': 0.8333333333333334,\n", - " 'mIoU': 0.9042780340786216,\n", - " 'mAUC_50': 0.7357142857142857}" + " 'AR_medium': 1.0,\n", + " 'AR_large': 0.0,\n", + " 'AR_50': 0.8888888888888888,\n", + " 'AR_75': 0.8888888888888888,\n", + " 'mIoU': 1.0,\n", + " 'mAUC_50': 0.594074074074074}" ] }, "execution_count": 7, @@ -162,7 +162,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.6" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/faster_coco_eval/core/coco.py b/faster_coco_eval/core/coco.py index 4927a83..bc388f8 100644 --- a/faster_coco_eval/core/coco.py +++ b/faster_coco_eval/core/coco.py @@ -1,5 +1,5 @@ -__author__ = 'tylin' -__version__ = '2.0' +__author__ = "tylin" +__version__ = "2.0" # Interface for accessing the Microsoft COCO dataset. # Microsoft COCO is a large image dataset designed for object detection, @@ -54,11 +54,12 @@ import warnings import logging + logger = logging.getLogger(__name__) def _isArrayLike(obj): - return hasattr(obj, '__iter__') and hasattr(obj, '__len__') + return hasattr(obj, "__iter__") and hasattr(obj, "__len__") class COCO: @@ -75,46 +76,50 @@ def __init__(self, annotation_file=None): self.score_tresh: float = 0.0 if not annotation_file == None: - logger.debug('loading annotations into memory...') + logger.debug("loading annotations into memory...") tic = time.time() if type(annotation_file) is str: - with open(annotation_file, 'r') as f: + with open(annotation_file, "r") as f: self.dataset = json.load(f) elif type(annotation_file) is dict: self.dataset = annotation_file else: self.dataset = None - assert type(self.dataset) == dict, 'annotation file format {} not supported'.format( - type(self.dataset)) - logger.debug('Done (t={:0.2f}s)'.format(time.time() - tic)) + assert ( + type(self.dataset) == dict + ), "annotation file format {} not supported".format(type(self.dataset)) + logger.debug("Done (t={:0.2f}s)".format(time.time() - tic)) self.createIndex() def createIndex(self): # create index - logger.debug('creating index...') + logger.debug("creating index...") anns, cats, imgs = {}, {}, {} imgToAnns, catToImgs = defaultdict(list), defaultdict(list) - if 'annotations' in self.dataset: - for ann in self.dataset['annotations']: - ann['image_id'] = int(ann['image_id']) - imgToAnns[ann['image_id']].append(ann) - anns[ann['id']] = ann - - if 'images' in self.dataset: - for img in self.dataset['images']: - img['id'] = int(img['id']) - imgs[img['id']] = img - - if 'categories' in self.dataset: - for cat in self.dataset['categories']: - cats[cat['id']] = cat - - if 'annotations' in self.dataset and 'categories' in self.dataset: - for ann in self.dataset['annotations']: - catToImgs[ann['category_id']].append(ann['image_id']) - - logger.debug('index created!') + annsImgIds_dict = {} + if "images" in self.dataset: + for img in self.dataset["images"]: + img["id"] = int(img["id"]) + imgs[img["id"]] = img + annsImgIds_dict[img["id"]] = True + + if "annotations" in self.dataset: + for ann in self.dataset["annotations"]: + ann["image_id"] = int(ann["image_id"]) + if annsImgIds_dict.get(ann["image_id"]): + imgToAnns[ann["image_id"]].append(ann) + anns[ann["id"]] = ann + + if "categories" in self.dataset: + for cat in self.dataset["categories"]: + cats[cat["id"]] = cat + + if "annotations" in self.dataset and "categories" in self.dataset: + for ann in self.dataset["annotations"]: + catToImgs[ann["category_id"]].append(ann["image_id"]) + + logger.debug("index created!") # create class members self.anns = anns @@ -128,8 +133,8 @@ def info(self): Print information about the annotation file. :return: """ - for key, value in self.dataset['info'].items(): - logger.debug('{}: {}'.format(key, value)) + for key, value in self.dataset["info"].items(): + logger.debug("{}: {}".format(key, value)) def getAnnIds(self, imgIds=[], catIds=[], areaRng=[], iscrowd=None): """ @@ -144,22 +149,33 @@ def getAnnIds(self, imgIds=[], catIds=[], areaRng=[], iscrowd=None): catIds = catIds if _isArrayLike(catIds) else [catIds] if len(imgIds) == len(catIds) == len(areaRng) == 0: - anns = self.dataset['annotations'] + anns = self.dataset["annotations"] else: if not len(imgIds) == 0: - lists = [self.imgToAnns[imgId] - for imgId in imgIds if imgId in self.imgToAnns] + lists = [ + self.imgToAnns[imgId] for imgId in imgIds if imgId in self.imgToAnns + ] anns = list(itertools.chain.from_iterable(lists)) else: - anns = self.dataset['annotations'] - anns = anns if len(catIds) == 0 else [ - ann for ann in anns if ann['category_id'] in catIds] - anns = anns if len(areaRng) == 0 else [ - ann for ann in anns if ann['area'] > areaRng[0] and ann['area'] < areaRng[1]] + anns = self.dataset["annotations"] + anns = ( + anns + if len(catIds) == 0 + else [ann for ann in anns if ann["category_id"] in catIds] + ) + anns = ( + anns + if len(areaRng) == 0 + else [ + ann + for ann in anns + if ann["area"] > areaRng[0] and ann["area"] < areaRng[1] + ] + ) if not iscrowd == None: - ids = [ann['id'] for ann in anns if ann['iscrowd'] == iscrowd] + ids = [ann["id"] for ann in anns if ann["iscrowd"] == iscrowd] else: - ids = [ann['id'] for ann in anns] + ids = [ann["id"] for ann in anns] return ids def getCatIds(self, catNms=[], supNms=[], catIds=[]): @@ -175,25 +191,34 @@ def getCatIds(self, catNms=[], supNms=[], catIds=[]): catIds = catIds if _isArrayLike(catIds) else [catIds] if len(catNms) == len(supNms) == len(catIds) == 0: - cats = self.dataset['categories'] + cats = self.dataset["categories"] else: - cats = self.dataset['categories'] - cats = cats if len(catNms) == 0 else [ - cat for cat in cats if cat['name'] in catNms] - cats = cats if len(supNms) == 0 else [ - cat for cat in cats if cat['supercategory'] in supNms] - cats = cats if len(catIds) == 0 else [ - cat for cat in cats if cat['id'] in catIds] - ids = [cat['id'] for cat in cats] + cats = self.dataset["categories"] + cats = ( + cats + if len(catNms) == 0 + else [cat for cat in cats if cat["name"] in catNms] + ) + cats = ( + cats + if len(supNms) == 0 + else [cat for cat in cats if cat["supercategory"] in supNms] + ) + cats = ( + cats + if len(catIds) == 0 + else [cat for cat in cats if cat["id"] in catIds] + ) + ids = [cat["id"] for cat in cats] return ids def getImgIds(self, imgIds=[], catIds=[]): - ''' + """ Get img ids that satisfy given filter conditions. :param imgIds (int array) : get imgs for given ids :param catIds (int array) : get imgs with all given cats :return: ids (int array) : integer array of img ids - ''' + """ imgIds = imgIds if _isArrayLike(imgIds) else [imgIds] catIds = catIds if _isArrayLike(catIds) else [catIds] @@ -249,9 +274,9 @@ def loadRes(self, resFile, min_score=0): """ self.score_tresh = min_score res = COCO() - res.dataset['images'] = [img for img in self.dataset['images']] + res.dataset["images"] = [img for img in self.dataset["images"]] - logger.debug('Loading and preparing results...') + logger.debug("Loading and preparing results...") tic = time.time() if type(resFile) == str: anns = json.load(open(resFile)) @@ -259,55 +284,58 @@ def loadRes(self, resFile, min_score=0): anns = self.loadNumpyAnnotations(resFile) else: anns = resFile - assert type(anns) == list, 'results in not an array of objects' - - anns = [ann for ann in anns if ann.get('score', 1) >= self.score_tresh] - - annsImgIds = [ann['image_id'] for ann in anns] - assert set(annsImgIds) == (set(annsImgIds) & set(self.getImgIds())), \ - 'Results do not correspond to current coco set' - if 'caption' in anns[0]: - imgIds = set([img['id'] for img in res.dataset['images']]) & set( - [ann['image_id'] for ann in anns]) - res.dataset['images'] = [ - img for img in res.dataset['images'] if img['id'] in imgIds] + assert type(anns) == list, "results in not an array of objects" + + anns = [ann for ann in anns if ann.get("score", 1) >= self.score_tresh] + + annsImgIds = [ann["image_id"] for ann in anns] + assert set(annsImgIds) == ( + set(annsImgIds) & set(self.getImgIds()) + ), "Results do not correspond to current coco set" + if "caption" in anns[0]: + imgIds = set([img["id"] for img in res.dataset["images"]]) & set( + [ann["image_id"] for ann in anns] + ) + res.dataset["images"] = [ + img for img in res.dataset["images"] if img["id"] in imgIds + ] for id, ann in enumerate(anns): - ann['id'] = id+1 - elif 'bbox' in anns[0] and not anns[0]['bbox'] == []: - res.dataset['categories'] = copy.deepcopy( - self.dataset['categories']) + ann["id"] = id + 1 + elif "bbox" in anns[0] and not anns[0]["bbox"] == []: + res.dataset["categories"] = copy.deepcopy(self.dataset["categories"]) for id, ann in enumerate(anns): - bb = ann['bbox'] - x1, x2, y1, y2 = [bb[0], bb[0]+bb[2], bb[1], bb[1]+bb[3]] - if not 'segmentation' in ann: - ann['segmentation'] = [[x1, y1, x1, y2, x2, y2, x2, y1]] - ann['area'] = bb[2]*bb[3] - ann['id'] = id+1 - ann['iscrowd'] = 0 - elif 'segmentation' in anns[0]: - res.dataset['categories'] = copy.deepcopy( - self.dataset['categories']) + bb = ann["bbox"] + x1, x2, y1, y2 = [bb[0], bb[0] + bb[2], bb[1], bb[1] + bb[3]] + if not "segmentation" in ann: + ann["segmentation"] = [[x1, y1, x1, y2, x2, y2, x2, y1]] + ann["area"] = bb[2] * bb[3] + ann["id"] = id + 1 + ann["iscrowd"] = 0 + elif "segmentation" in anns[0]: + res.dataset["categories"] = copy.deepcopy(self.dataset["categories"]) for id, ann in enumerate(anns): # now only support compressed RLE format as segmentation results - ann['area'] = maskUtils.area(ann['segmentation']) - if not 'bbox' in ann: - ann['bbox'] = maskUtils.toBbox(ann['segmentation']) - ann['id'] = id+1 - ann['iscrowd'] = 0 - elif 'keypoints' in anns[0]: - res.dataset['categories'] = copy.deepcopy( - self.dataset['categories']) + ann["area"] = maskUtils.area(ann["segmentation"]) + if not "bbox" in ann: + ann["bbox"] = maskUtils.toBbox(ann["segmentation"]) + ann["id"] = id + 1 + ann["iscrowd"] = 0 + elif "keypoints" in anns[0]: + res.dataset["categories"] = copy.deepcopy(self.dataset["categories"]) for id, ann in enumerate(anns): - s = ann['keypoints'] + s = ann["keypoints"] x = s[0::3] y = s[1::3] x0, x1, y0, y1 = np.min(x), np.max(x), np.min(y), np.max(y) - ann['area'] = (x1-x0)*(y1-y0) - ann['id'] = id + 1 - ann['bbox'] = [x0, y0, x1-x0, y1-y0] - logger.debug('DONE (t={:0.2f}s)'.format(time.time() - tic)) + ann["area"] = (x1 - x0) * (y1 - y0) + ann["id"] = id + 1 + ann["bbox"] = [x0, y0, x1 - x0, y1 - y0] + logger.debug("DONE (t={:0.2f}s)".format(time.time() - tic)) + + annsImgIds_dict = {image["id"]: True for image in res.dataset["images"]} + anns = [ann for ann in anns if annsImgIds_dict.get(ann["image_id"])] - res.dataset['annotations'] = anns + res.dataset["annotations"] = anns res.createIndex() return res @@ -323,21 +351,23 @@ def loadNumpyAnnotations(self, data): :param data (numpy.ndarray) :return: annotations (python nested list) """ - logger.debug('Converting ndarray to lists...') - assert (type(data) == np.ndarray) + logger.debug("Converting ndarray to lists...") + assert type(data) == np.ndarray logger.debug(data.shape) - assert (data.shape[1] == 7) + assert data.shape[1] == 7 N = data.shape[0] ann = [] for i in range(N): if i % 1000000 == 0: - logger.debug('{}/{}'.format(i, N)) - ann += [{ - 'image_id': int(data[i, 0]), - 'bbox': [data[i, 1], data[i, 2], data[i, 3], data[i, 4]], - 'score': data[i, 5], - 'category_id': int(data[i, 6]), - }] + logger.debug("{}/{}".format(i, N)) + ann += [ + { + "image_id": int(data[i, 0]), + "bbox": [data[i, 1], data[i, 2], data[i, 3], data[i, 4]], + "score": data[i, 5], + "category_id": int(data[i, 6]), + } + ] return ann def annToRLE(self, ann): @@ -345,20 +375,20 @@ def annToRLE(self, ann): Convert annotation which can be polygons, uncompressed RLE to RLE. :return: binary mask (numpy 2D array) """ - t = self.imgs[ann['image_id']] - h, w = t['height'], t['width'] - segm = ann['segmentation'] + t = self.imgs[ann["image_id"]] + h, w = t["height"], t["width"] + segm = ann["segmentation"] if type(segm) == list: # polygon -- a single object might consist of multiple parts # we merge all parts into one mask rle code rles = maskUtils.frPyObjects(segm, h, w) rle = maskUtils.merge(rles) - elif type(segm['counts']) == list: + elif type(segm["counts"]) == list: # uncompressed RLE rle = maskUtils.frPyObjects(segm, h, w) else: # rle - rle = ann['segmentation'] + rle = ann["segmentation"] return rle def annToMask(self, ann): diff --git a/faster_coco_eval/core/cocoeval.py b/faster_coco_eval/core/cocoeval.py index 4cb09c0..7d64b50 100644 --- a/faster_coco_eval/core/cocoeval.py +++ b/faster_coco_eval/core/cocoeval.py @@ -1,13 +1,15 @@ -__author__ = 'tsungyi' +__author__ = "tsungyi" import numpy as np import datetime import time from collections import defaultdict from . import mask as maskUtils +from .coco import COCO import copy import logging + logger = logging.getLogger(__name__) @@ -61,27 +63,29 @@ class COCOeval: # Data, paper, and tutorials available at: http://mscoco.org/ # Code written by Piotr Dollar and Tsung-Yi Lin, 2015. # Licensed under the Simplified BSD License [see coco/license.txt] - def __init__(self, cocoGt=None, cocoDt=None, iouType='segm', print_function=logger.debug): - ''' + def __init__( + self, cocoGt=None, cocoDt=None, iouType="segm", print_function=logger.debug + ): + """ Initialize CocoEval using coco APIs for gt and dt :param cocoGt: coco object with ground truth annotations :param cocoDt: coco object with detection results :return: None - ''' + """ if not iouType: - logger.warning('iouType not specified. use default iouType segm') + logger.warning("iouType not specified. use default iouType segm") - self.cocoGt = cocoGt # ground truth COCO API - self.cocoDt = cocoDt # detections COCO API + self.cocoGt: COCO = cocoGt # ground truth COCO API + self.cocoDt: COCO = cocoDt # detections COCO API # per-image per-category evaluation results [KxAxI] elements self.evalImgs = defaultdict(list) - self.eval = {} # accumulated evaluation results - self._gts = defaultdict(list) # gt for evaluation - self._dts = defaultdict(list) # dt for evaluation + self.eval: dict = {} # accumulated evaluation results + self._gts = defaultdict(list) # gt for evaluation + self._dts = defaultdict(list) # dt for evaluation self.params = Params(iouType=iouType) # parameters - self._paramsEval = {} # parameters for evaluation - self.stats = [] # result summarization - self.ious = {} # ious between all gts and dts + self._paramsEval: dict = {} # parameters for evaluation + self.stats: list = [] # result summarization + self.ious: dict = {} # ious between all gts and dts if not cocoGt is None: self.params.imgIds = sorted(cocoGt.getImgIds()) @@ -90,59 +94,66 @@ def __init__(self, cocoGt=None, cocoDt=None, iouType='segm', print_function=logg self.print_function = print_function # output print function def _prepare(self): - ''' + """ Prepare ._gts and ._dts for evaluation based on params :return: None - ''' + """ + def _toMask(anns, coco): # modify ann['segmentation'] by reference for ann in anns: rle = coco.annToRLE(ann) - ann['rle'] = rle + ann["rle"] = rle + p = self.params if p.useCats: - gts = self.cocoGt.loadAnns(self.cocoGt.getAnnIds( - imgIds=p.imgIds, catIds=p.catIds)) - dts = self.cocoDt.loadAnns(self.cocoDt.getAnnIds( - imgIds=p.imgIds, catIds=p.catIds)) + gts = self.cocoGt.loadAnns( + self.cocoGt.getAnnIds(imgIds=p.imgIds, catIds=p.catIds) + ) + dts = self.cocoDt.loadAnns( + self.cocoDt.getAnnIds(imgIds=p.imgIds, catIds=p.catIds) + ) else: gts = self.cocoGt.loadAnns(self.cocoGt.getAnnIds(imgIds=p.imgIds)) dts = self.cocoDt.loadAnns(self.cocoDt.getAnnIds(imgIds=p.imgIds)) # convert ground truth to mask if iouType == 'segm' - if p.iouType == 'segm': + if p.iouType == "segm": _toMask(gts, self.cocoGt) _toMask(dts, self.cocoDt) # set ignore flag for gt in gts: - gt['ignore'] = gt['ignore'] if 'ignore' in gt else 0 - gt['ignore'] = 'iscrowd' in gt and gt['iscrowd'] - if p.iouType == 'keypoints': - gt['ignore'] = (gt['num_keypoints'] == 0) or gt['ignore'] - self._gts = defaultdict(list) # gt for evaluation - self._dts = defaultdict(list) # dt for evaluation + gt["ignore"] = gt["ignore"] if "ignore" in gt else 0 + gt["ignore"] = "iscrowd" in gt and gt["iscrowd"] + if p.iouType == "keypoints": + gt["ignore"] = (gt["num_keypoints"] == 0) or gt["ignore"] + self._gts = defaultdict(list) # gt for evaluation + self._dts = defaultdict(list) # dt for evaluation for gt in gts: - self._gts[gt['image_id'], gt['category_id']].append(gt) + self._gts[gt["image_id"], gt["category_id"]].append(gt) for dt in dts: - self._dts[dt['image_id'], dt['category_id']].append(dt) + self._dts[dt["image_id"], dt["category_id"]].append(dt) # per-image per-category evaluation results self.evalImgs = defaultdict(list) - self.eval = {} # accumulated evaluation results + self.eval = {} # accumulated evaluation results def evaluate(self): - ''' + """ Run per image evaluation on given images and store results (a list of dict) in self.evalImgs :return: None - ''' + """ tic = time.time() - self.print_function('Running per image evaluation...') + self.print_function("Running per image evaluation...") p = self.params # add backward compatibility if useSegm is specified in params if not p.useSegm is None: - p.iouType = 'segm' if p.useSegm == 1 else 'bbox' + p.iouType = "segm" if p.useSegm == 1 else "bbox" logger.warning( - 'useSegm (deprecated) is not None. Running {} evaluation'.format(p.iouType)) - self.print_function('Evaluate annotation type *{}*'.format(p.iouType)) + "useSegm (deprecated) is not None. Running {} evaluation".format( + p.iouType + ) + ) + self.print_function("Evaluate annotation type *{}*".format(p.iouType)) p.imgIds = list(np.unique(p.imgIds)) if p.useCats: p.catIds = list(np.unique(p.catIds)) @@ -153,24 +164,27 @@ def evaluate(self): # loop through images, area range, max detection number catIds = p.catIds if p.useCats else [-1] - if p.iouType == 'segm' or p.iouType == 'bbox': + if p.iouType == "segm" or p.iouType == "bbox": computeIoU = self.computeIoU - elif p.iouType == 'keypoints': + elif p.iouType == "keypoints": computeIoU = self.computeOks - self.ious = {(imgId, catId): computeIoU(imgId, catId) - for imgId in p.imgIds - for catId in catIds} + self.ious = { + (imgId, catId): computeIoU(imgId, catId) + for imgId in p.imgIds + for catId in catIds + } evaluateImg = self.evaluateImg maxDet = p.maxDets[-1] - self.evalImgs = [evaluateImg(imgId, catId, areaRng, maxDet) - for catId in catIds - for areaRng in p.areaRng - for imgId in p.imgIds - ] + self.evalImgs = [ + evaluateImg(imgId, catId, areaRng, maxDet) + for catId in catIds + for areaRng in p.areaRng + for imgId in p.imgIds + ] self._paramsEval = copy.deepcopy(self.params) toc = time.time() - self.print_function('DONE (t={:0.2f}s).'.format(toc-tic)) + self.print_function("DONE (t={:0.2f}s).".format(toc - tic)) def computeIoU(self, imgId, catId): p = self.params @@ -182,22 +196,22 @@ def computeIoU(self, imgId, catId): dt = [_ for cId in p.catIds for _ in self._dts[imgId, cId]] if len(gt) == 0 and len(dt) == 0: return [] - inds = np.argsort([-d['score'] for d in dt], kind='mergesort') + inds = np.argsort([-d["score"] for d in dt], kind="mergesort") dt = [dt[i] for i in inds] if len(dt) > p.maxDets[-1]: - dt = dt[0:p.maxDets[-1]] - - if p.iouType == 'segm': - g = [g['rle'] for g in gt] - d = [d['rle'] for d in dt] - elif p.iouType == 'bbox': - g = [g['bbox'] for g in gt] - d = [d['bbox'] for d in dt] + dt = dt[0 : p.maxDets[-1]] + + if p.iouType == "segm": + g = [g["rle"] for g in gt] + d = [d["rle"] for d in dt] + elif p.iouType == "bbox": + g = [g["bbox"] for g in gt] + d = [d["bbox"] for d in dt] else: - raise Exception('unknown iouType for iou computation') + raise Exception("unknown iouType for iou computation") # compute iou between each dt and gt region - iscrowd = [int(o['iscrowd']) for o in gt] + iscrowd = [int(o["iscrowd"]) for o in gt] ious = maskUtils.iou(d, g, iscrowd) return ious @@ -206,32 +220,32 @@ def computeOks(self, imgId, catId): # dimention here should be Nxm gts = self._gts[imgId, catId] dts = self._dts[imgId, catId] - inds = np.argsort([-d['score'] for d in dts], kind='mergesort') + inds = np.argsort([-d["score"] for d in dts], kind="mergesort") dts = [dts[i] for i in inds] if len(dts) > p.maxDets[-1]: - dts = dts[0:p.maxDets[-1]] + dts = dts[0 : p.maxDets[-1]] # if len(gts) == 0 and len(dts) == 0: if len(gts) == 0 or len(dts) == 0: return [] ious = np.zeros((len(dts), len(gts))) sigmas = p.kpt_oks_sigmas - vars = (sigmas * 2)**2 + vars = (sigmas * 2) ** 2 k = len(sigmas) # compute oks between each detection and ground truth object for j, gt in enumerate(gts): # create bounds for ignore regions(double the gt bbox) - g = np.array(gt['keypoints']) + g = np.array(gt["keypoints"]) xg = g[0::3] yg = g[1::3] vg = g[2::3] k1 = np.count_nonzero(vg > 0) - bb = gt['bbox'] + bb = gt["bbox"] x0 = bb[0] - bb[2] x1 = bb[0] + bb[2] * 2 y0 = bb[1] - bb[3] y1 = bb[1] + bb[3] * 2 for i, dt in enumerate(dts): - d = np.array(dt['keypoints']) + d = np.array(dt["keypoints"]) xd = d[0::3] yd = d[1::3] if k1 > 0: @@ -241,19 +255,19 @@ def computeOks(self, imgId, catId): else: # measure minimum distance to keypoints in (x0,y0) & (x1,y1) z = np.zeros((k)) - dx = np.max((z, x0-xd), axis=0)+np.max((z, xd-x1), axis=0) - dy = np.max((z, y0-yd), axis=0)+np.max((z, yd-y1), axis=0) - e = (dx**2 + dy**2) / vars / (gt['area']+np.spacing(1)) / 2 + dx = np.max((z, x0 - xd), axis=0) + np.max((z, xd - x1), axis=0) + dy = np.max((z, y0 - yd), axis=0) + np.max((z, yd - y1), axis=0) + e = (dx**2 + dy**2) / vars / (gt["area"] + np.spacing(1)) / 2 if k1 > 0: e = e[vg > 0] ious[i, j] = np.sum(np.exp(-e)) / e.shape[0] return ious def evaluateImg(self, imgId, catId, aRng, maxDet): - ''' + """ perform evaluation for single category and image :return: dict (single image results) - ''' + """ p = self.params if p.useCats: gt = self._gts[imgId, catId] @@ -265,33 +279,36 @@ def evaluateImg(self, imgId, catId, aRng, maxDet): return None for g in gt: - if g['ignore'] or (g['area'] < aRng[0] or g['area'] > aRng[1]): - g['_ignore'] = 1 + if g["ignore"] or (g["area"] < aRng[0] or g["area"] > aRng[1]): + g["_ignore"] = 1 else: - g['_ignore'] = 0 + g["_ignore"] = 0 # sort dt highest score first, sort gt ignore last - gtind = np.argsort([g['_ignore'] for g in gt], kind='mergesort') + gtind = np.argsort([g["_ignore"] for g in gt], kind="mergesort") gt = [gt[i] for i in gtind] - dtind = np.argsort([-d['score'] for d in dt], kind='mergesort') + dtind = np.argsort([-d["score"] for d in dt], kind="mergesort") dt = [dt[i] for i in dtind[0:maxDet]] - iscrowd = [int(o['iscrowd']) for o in gt] + iscrowd = [int(o["iscrowd"]) for o in gt] # load computed ious - ious = self.ious[imgId, catId][:, gtind] if len( - self.ious[imgId, catId]) > 0 else self.ious[imgId, catId] + ious = ( + self.ious[imgId, catId][:, gtind] + if len(self.ious[imgId, catId]) > 0 + else self.ious[imgId, catId] + ) T = len(p.iouThrs) G = len(gt) D = len(dt) gtm = np.zeros((T, G)) dtm = np.zeros((T, D)) - gtIg = np.array([g['_ignore'] for g in gt]) + gtIg = np.array([g["_ignore"] for g in gt]) dtIg = np.zeros((T, D)) if not len(ious) == 0: for tind, t in enumerate(p.iouThrs): for dind, d in enumerate(dt): # information about best match so far (m=-1 -> unmatched) - iou = min([t, 1-1e-10]) + iou = min([t, 1 - 1e-10]) m = -1 for gind, g in enumerate(gt): # if this gt already matched, and not a crowd, continue @@ -310,38 +327,38 @@ def evaluateImg(self, imgId, catId, aRng, maxDet): if m == -1: continue dtIg[tind, dind] = gtIg[m] - dtm[tind, dind] = gt[m]['id'] - gtm[tind, m] = d['id'] + dtm[tind, dind] = gt[m]["id"] + gtm[tind, m] = d["id"] # set unmatched detections outside of area range to ignore - a = np.array([d['area'] < aRng[0] or d['area'] > aRng[1] - for d in dt]).reshape((1, len(dt))) - dtIg = np.logical_or(dtIg, np.logical_and( - dtm == 0, np.repeat(a, T, 0))) + a = np.array([d["area"] < aRng[0] or d["area"] > aRng[1] for d in dt]).reshape( + (1, len(dt)) + ) + dtIg = np.logical_or(dtIg, np.logical_and(dtm == 0, np.repeat(a, T, 0))) # store results for given image and category return { - 'image_id': imgId, - 'category_id': catId, - 'aRng': aRng, - 'maxDet': maxDet, - 'dtIds': [d['id'] for d in dt], - 'gtIds': [g['id'] for g in gt], - 'dtMatches': dtm, - 'gtMatches': gtm, - 'dtScores': [d['score'] for d in dt], - 'gtIgnore': gtIg, - 'dtIgnore': dtIg, + "image_id": imgId, + "category_id": catId, + "aRng": aRng, + "maxDet": maxDet, + "dtIds": [d["id"] for d in dt], + "gtIds": [g["id"] for g in gt], + "dtMatches": dtm, + "gtMatches": gtm, + "dtScores": [d["score"] for d in dt], + "gtIgnore": gtIg, + "dtIgnore": dtIg, } def accumulate(self, p=None): - ''' + """ Accumulate per image evaluation results and store the result in self.eval :param p: input params for evaluation :return: None - ''' - self.print_function('Accumulating evaluation results...') + """ + self.print_function("Accumulating evaluation results...") tic = time.time() if not self.evalImgs: - self.print_function('Please run evaluate() first') + self.print_function("Please run evaluate() first") # allows input customized parameters if p is None: p = self.params @@ -366,42 +383,43 @@ def accumulate(self, p=None): # get inds to evaluate k_list = [n for n, k in enumerate(p.catIds) if k in setK] m_list = [m for n, m in enumerate(p.maxDets) if m in setM] - a_list = [n for n, a in enumerate( - map(lambda x: tuple(x), p.areaRng)) if a in setA] + a_list = [ + n for n, a in enumerate(map(lambda x: tuple(x), p.areaRng)) if a in setA + ] i_list = [n for n, i in enumerate(p.imgIds) if i in setI] I0 = len(_pe.imgIds) A0 = len(_pe.areaRng) # retrieve E at each category, area range, and max number of detections for k, k0 in enumerate(k_list): - Nk = k0*A0*I0 + Nk = k0 * A0 * I0 for a, a0 in enumerate(a_list): - Na = a0*I0 + Na = a0 * I0 for m, maxDet in enumerate(m_list): E = [self.evalImgs[Nk + Na + i] for i in i_list] E = [e for e in E if not e is None] if len(E) == 0: continue - dtScores = np.concatenate( - [e['dtScores'][0:maxDet] for e in E]) + dtScores = np.concatenate([e["dtScores"][0:maxDet] for e in E]) # different sorting method generates slightly different results. # mergesort is used to be consistent as Matlab implementation. - inds = np.argsort(-dtScores, kind='mergesort') + inds = np.argsort(-dtScores, kind="mergesort") dtScoresSorted = dtScores[inds] - dtm = np.concatenate([e['dtMatches'][:, 0:maxDet] - for e in E], axis=1)[:, inds] + dtm = np.concatenate( + [e["dtMatches"][:, 0:maxDet] for e in E], axis=1 + )[:, inds] dtIg = np.concatenate( - [e['dtIgnore'][:, 0:maxDet] for e in E], axis=1)[:, inds] - gtIg = np.concatenate([e['gtIgnore'] for e in E]) + [e["dtIgnore"][:, 0:maxDet] for e in E], axis=1 + )[:, inds] + gtIg = np.concatenate([e["gtIgnore"] for e in E]) npig = np.count_nonzero(gtIg == 0) if npig == 0: continue - tps = np.logical_and(dtm, np.logical_not(dtIg)) - fps = np.logical_and( - np.logical_not(dtm), np.logical_not(dtIg)) + tps = np.logical_and(dtm, np.logical_not(dtIg)) + fps = np.logical_and(np.logical_not(dtm), np.logical_not(dtIg)) tp_sum = np.cumsum(tps, axis=1).astype(dtype=float) fp_sum = np.cumsum(fps, axis=1).astype(dtype=float) @@ -411,7 +429,7 @@ def accumulate(self, p=None): fp = np.array(fp) nd = len(tp) rc = tp / npig - pr = tp / (fp+tp+np.spacing(1)) + pr = tp / (fp + tp + np.spacing(1)) q = np.zeros((R,)) ss = np.zeros((R,)) @@ -425,11 +443,11 @@ def accumulate(self, p=None): pr = pr.tolist() q = q.tolist() - for i in range(nd-1, 0, -1): - if pr[i] > pr[i-1]: - pr[i-1] = pr[i] + for i in range(nd - 1, 0, -1): + if pr[i] > pr[i - 1]: + pr[i - 1] = pr[i] - inds = np.searchsorted(rc, p.recThrs, side='left') + inds = np.searchsorted(rc, p.recThrs, side="left") try: for ri, pi in enumerate(inds): q[ri] = pr[pi] @@ -440,36 +458,39 @@ def accumulate(self, p=None): scores[t, :, k, a, m] = np.array(ss) self.eval = { - 'params': p, - 'counts': [T, R, K, A, M], - 'date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), - 'precision': precision, - 'recall': recall, - 'scores': scores, + "params": p, + "counts": [T, R, K, A, M], + "date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + "precision": precision, + "recall": recall, + "scores": scores, } toc = time.time() - self.print_function('DONE (t={:0.2f}s).'.format(toc-tic)) + self.print_function("DONE (t={:0.2f}s).".format(toc - tic)) def summarize(self): - ''' + """ Compute and display summary metrics for evaluation results. Note this functin can *only* be applied on the default parameter setting - ''' - def _summarize(ap=1, iouThr=None, areaRng='all', maxDets=100): + """ + + def _summarize(ap=1, iouThr=None, areaRng="all", maxDets=100): p = self.params - iStr = ' {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}' - titleStr = 'Average Precision' if ap == 1 else 'Average Recall' - typeStr = '(AP)' if ap == 1 else '(AR)' - iouStr = '{:0.2f}:{:0.2f}'.format(p.iouThrs[0], p.iouThrs[-1]) \ - if iouThr is None else '{:0.2f}'.format(iouThr) - - aind = [i for i, aRng in enumerate( - p.areaRngLbl) if aRng == areaRng] + iStr = " {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}" + titleStr = "Average Precision" if ap == 1 else "Average Recall" + typeStr = "(AP)" if ap == 1 else "(AR)" + iouStr = ( + "{:0.2f}:{:0.2f}".format(p.iouThrs[0], p.iouThrs[-1]) + if iouThr is None + else "{:0.2f}".format(iouThr) + ) + + aind = [i for i, aRng in enumerate(p.areaRngLbl) if aRng == areaRng] mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets] if ap == 1: # dimension of precision: [TxRxKxAxM] - s = self.eval['precision'] + s = self.eval["precision"] # IoU if iouThr is not None: t = np.where(iouThr == p.iouThrs)[0] @@ -477,7 +498,7 @@ def _summarize(ap=1, iouThr=None, areaRng='all', maxDets=100): s = s[:, :, :, aind, mind] else: # dimension of recall: [TxKxAxM] - s = self.eval['recall'] + s = self.eval["recall"] if iouThr is not None: t = np.where(iouThr == p.iouThrs)[0] s = s[t] @@ -486,66 +507,75 @@ def _summarize(ap=1, iouThr=None, areaRng='all', maxDets=100): mean_s = -1 else: mean_s = np.mean(s[s > -1]) - self.print_function(iStr.format(titleStr, typeStr, - iouStr, areaRng, maxDets, mean_s)) + self.print_function( + iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s) + ) return mean_s def _summarizeDets(): stats = np.zeros((14,)) stats[0] = _summarize(1, maxDets=self.params.maxDets[-1]) # AP_all stats[1] = _summarize( - 1, iouThr=.5, maxDets=self.params.maxDets[-1]) # AP_50 + 1, iouThr=0.5, maxDets=self.params.maxDets[-1] + ) # AP_50 stats[2] = _summarize( - 1, iouThr=.75, maxDets=self.params.maxDets[-1]) # AP_75 - stats[3] = _summarize(1, areaRng='small', - maxDets=self.params.maxDets[-1]) # AP_small - stats[4] = _summarize(1, areaRng='medium', - maxDets=self.params.maxDets[-1]) # AP_medium - stats[5] = _summarize(1, areaRng='large', - maxDets=self.params.maxDets[-1]) # AP_large + 1, iouThr=0.75, maxDets=self.params.maxDets[-1] + ) # AP_75 + stats[3] = _summarize( + 1, areaRng="small", maxDets=self.params.maxDets[-1] + ) # AP_small + stats[4] = _summarize( + 1, areaRng="medium", maxDets=self.params.maxDets[-1] + ) # AP_medium + stats[5] = _summarize( + 1, areaRng="large", maxDets=self.params.maxDets[-1] + ) # AP_large # AR_first or AR_all stats[6] = _summarize(0, maxDets=self.params.maxDets[0]) if len(self.params.maxDets) >= 2: - stats[7] = _summarize( - 0, maxDets=self.params.maxDets[1]) # AR_second + stats[7] = _summarize(0, maxDets=self.params.maxDets[1]) # AR_second if len(self.params.maxDets) >= 3: - stats[8] = _summarize( - 0, maxDets=self.params.maxDets[2]) # AR_third - - stats[9] = _summarize(0, areaRng='small', - maxDets=self.params.maxDets[-1]) # AR_small - stats[10] = _summarize(0, areaRng='medium', - maxDets=self.params.maxDets[-1]) # AR_medium + stats[8] = _summarize(0, maxDets=self.params.maxDets[2]) # AR_third + + stats[9] = _summarize( + 0, areaRng="small", maxDets=self.params.maxDets[-1] + ) # AR_small + stats[10] = _summarize( + 0, areaRng="medium", maxDets=self.params.maxDets[-1] + ) # AR_medium stats[11] = _summarize( - 0, areaRng='large', maxDets=self.params.maxDets[-1]) # AR_large + 0, areaRng="large", maxDets=self.params.maxDets[-1] + ) # AR_large stats[12] = _summarize( - 0, iouThr=.5, maxDets=self.params.maxDets[-1]) # AR_50 + 0, iouThr=0.5, maxDets=self.params.maxDets[-1] + ) # AR_50 stats[13] = _summarize( - 0, iouThr=.75, maxDets=self.params.maxDets[-1]) # AR_75 + 0, iouThr=0.75, maxDets=self.params.maxDets[-1] + ) # AR_75 return stats def _summarizeKps(): stats = np.zeros((10,)) stats[0] = _summarize(1, maxDets=20) - stats[1] = _summarize(1, maxDets=20, iouThr=.5) - stats[2] = _summarize(1, maxDets=20, iouThr=.75) - stats[3] = _summarize(1, maxDets=20, areaRng='medium') - stats[4] = _summarize(1, maxDets=20, areaRng='large') + stats[1] = _summarize(1, maxDets=20, iouThr=0.5) + stats[2] = _summarize(1, maxDets=20, iouThr=0.75) + stats[3] = _summarize(1, maxDets=20, areaRng="medium") + stats[4] = _summarize(1, maxDets=20, areaRng="large") stats[5] = _summarize(0, maxDets=20) - stats[6] = _summarize(0, maxDets=20, iouThr=.5) - stats[7] = _summarize(0, maxDets=20, iouThr=.75) - stats[8] = _summarize(0, maxDets=20, areaRng='medium') - stats[9] = _summarize(0, maxDets=20, areaRng='large') + stats[6] = _summarize(0, maxDets=20, iouThr=0.5) + stats[7] = _summarize(0, maxDets=20, iouThr=0.75) + stats[8] = _summarize(0, maxDets=20, areaRng="medium") + stats[9] = _summarize(0, maxDets=20, areaRng="large") return stats if not self.eval: - raise Exception('Please run accumulate() first') + raise Exception("Please run accumulate() first") iouType = self.params.iouType - if iouType == 'segm' or iouType == 'bbox': + if iouType == "segm" or iouType == "bbox": summarize = _summarizeDets - elif iouType == 'keypoints': + elif iouType == "keypoints": summarize = _summarizeKps self.all_stats = summarize() @@ -556,47 +586,76 @@ def __str__(self): class Params: - ''' + """ Params for coco evaluation api - ''' + """ def setDetParams(self): self.imgIds = [] self.catIds = [] # np.arange causes trouble. the data point on arange is slightly larger than the true value - self.iouThrs = np.linspace(.5, 0.95, int( - np.round((0.95 - .5) / .05)) + 1, endpoint=True) - self.recThrs = np.linspace(.0, 1.00, int( - np.round((1.00 - .0) / .01)) + 1, endpoint=True) + self.iouThrs = np.linspace( + 0.5, 0.95, int(np.round((0.95 - 0.5) / 0.05)) + 1, endpoint=True + ) + self.recThrs = np.linspace( + 0.0, 1.00, int(np.round((1.00 - 0.0) / 0.01)) + 1, endpoint=True + ) self.maxDets = [1, 10, 100] - self.areaRng = [[0 ** 2, 1e5 ** 2], [0 ** 2, 32 ** 2], - [32 ** 2, 96 ** 2], [96 ** 2, 1e5 ** 2]] - self.areaRngLbl = ['all', 'small', 'medium', 'large'] + self.areaRng = [ + [0**2, 1e5**2], + [0**2, 32**2], + [32**2, 96**2], + [96**2, 1e5**2], + ] + self.areaRngLbl = ["all", "small", "medium", "large"] self.useCats = 1 def setKpParams(self): self.imgIds = [] self.catIds = [] # np.arange causes trouble. the data point on arange is slightly larger than the true value - self.iouThrs = np.linspace(.5, 0.95, int( - np.round((0.95 - .5) / .05)) + 1, endpoint=True) - self.recThrs = np.linspace(.0, 1.00, int( - np.round((1.00 - .0) / .01)) + 1, endpoint=True) + self.iouThrs = np.linspace( + 0.5, 0.95, int(np.round((0.95 - 0.5) / 0.05)) + 1, endpoint=True + ) + self.recThrs = np.linspace( + 0.0, 1.00, int(np.round((1.00 - 0.0) / 0.01)) + 1, endpoint=True + ) self.maxDets = [20] - self.areaRng = [[0 ** 2, 1e5 ** 2], - [32 ** 2, 96 ** 2], [96 ** 2, 1e5 ** 2]] - self.areaRngLbl = ['all', 'medium', 'large'] + self.areaRng = [[0**2, 1e5**2], [32**2, 96**2], [96**2, 1e5**2]] + self.areaRngLbl = ["all", "medium", "large"] self.useCats = 1 - self.kpt_oks_sigmas = np.array( - [.26, .25, .25, .35, .35, .79, .79, .72, .72, .62, .62, 1.07, 1.07, .87, .87, .89, .89])/10.0 - - def __init__(self, iouType='segm'): - if iouType == 'segm' or iouType == 'bbox': + self.kpt_oks_sigmas = ( + np.array( + [ + 0.26, + 0.25, + 0.25, + 0.35, + 0.35, + 0.79, + 0.79, + 0.72, + 0.72, + 0.62, + 0.62, + 1.07, + 1.07, + 0.87, + 0.87, + 0.89, + 0.89, + ] + ) + / 10.0 + ) + + def __init__(self, iouType="segm"): + if iouType == "segm" or iouType == "bbox": self.setDetParams() - elif iouType == 'keypoints': + elif iouType == "keypoints": self.setKpParams() else: - raise Exception('iouType not supported') + raise Exception("iouType not supported") self.iouType = iouType # useSegm is deprecated self.useSegm = None diff --git a/faster_coco_eval/core/faster_eval_api.py b/faster_coco_eval/core/faster_eval_api.py index 215393e..1a29ce6 100644 --- a/faster_coco_eval/core/faster_eval_api.py +++ b/faster_coco_eval/core/faster_eval_api.py @@ -52,7 +52,9 @@ def evaluate(self): elif p.iouType == "keypoints": computeIoU = self.computeOks self.ious = { - (imgId, catId): computeIoU(imgId, catId) for imgId in p.imgIds for catId in catIds + (imgId, catId): computeIoU(imgId, catId) + for imgId in p.imgIds + for catId in catIds } # bottleneck maxDet = p.maxDets[-1] @@ -65,8 +67,7 @@ def convert_instances_to_cpp(instances, is_det=False): for instance in instances: instance_cpp = _C.InstanceAnnotation( int(instance["id"]), - instance["score"] if is_det else instance.get( - "score", 0.0), + instance["score"] if is_det else instance.get("score", 0.0), instance["area"], bool(instance.get("iscrowd", 0)), bool(instance.get("ignore", 0)), @@ -76,28 +77,35 @@ def convert_instances_to_cpp(instances, is_det=False): # Convert GT annotations, detections, and IOUs to a format that's fast to access in C++ ground_truth_instances = [ - [convert_instances_to_cpp(self._gts[imgId, catId]) - for catId in p.catIds] + [convert_instances_to_cpp(self._gts[imgId, catId]) for catId in p.catIds] for imgId in p.imgIds ] detected_instances = [ - [convert_instances_to_cpp( - self._dts[imgId, catId], is_det=True) for catId in p.catIds] + [ + convert_instances_to_cpp(self._dts[imgId, catId], is_det=True) + for catId in p.catIds + ] for imgId in p.imgIds ] - ious = [[self.ious[imgId, catId] for catId in catIds] - for imgId in p.imgIds] + ious = [[self.ious[imgId, catId] for catId in catIds] for imgId in p.imgIds] if not p.useCats: # For each image, flatten per-category lists into a single list - ground_truth_instances = [[[o for c in i for o in c]] - for i in ground_truth_instances] - detected_instances = [[[o for c in i for o in c]] - for i in detected_instances] + ground_truth_instances = [ + [[o for c in i for o in c]] for i in ground_truth_instances + ] + detected_instances = [ + [[o for c in i for o in c]] for i in detected_instances + ] # Call C++ implementation of self.evaluateImgs() self._evalImgs_cpp = _C.COCOevalEvaluateImages( - p.areaRng, maxDet, p.iouThrs, ious, ground_truth_instances, detected_instances + p.areaRng, + maxDet, + p.iouThrs, + ious, + ground_truth_instances, + detected_instances, ) self._evalImgs = None @@ -105,8 +113,8 @@ def convert_instances_to_cpp(instances, is_det=False): toc = time.time() - self.print_function('COCOeval_opt.evaluate() finished...') - self.print_function('DONE (t={:0.2f}s).'.format(toc-tic)) + self.print_function("COCOeval_opt.evaluate() finished...") + self.print_function("DONE (t={:0.2f}s).".format(toc - tic)) def accumulate(self): """ @@ -128,19 +136,33 @@ def accumulate(self): # precision and scores are num_iou_thresholds X num_recall_thresholds X num_categories X # num_area_ranges X num_max_detections - self.eval["precision"] = np.array( - self.eval["precision"]).reshape(self.eval["counts"]) - self.eval["scores"] = np.array( - self.eval["scores"]).reshape(self.eval["counts"]) - - cat_count = self.eval['counts'][2] - iou_tresh = self.eval['counts'][0] - area_ranges = self.eval['counts'][3] + self.eval["precision"] = np.array(self.eval["precision"]).reshape( + self.eval["counts"] + ) + self.eval["scores"] = np.array(self.eval["scores"]).reshape(self.eval["counts"]) try: - self.ground_truth_shape = [cat_count, area_ranges, iou_tresh, -1] - self.ground_truth_orig_id = np.array(self.eval['ground_truth_orig_id']).reshape(self.ground_truth_shape) - self.ground_truth_matches = np.array(self.eval['ground_truth_matches']).reshape(self.ground_truth_shape) + self.detection_matches = np.vstack( + np.array(self.eval["detection_matches"]).reshape( + self.eval["counts"][0], self.eval["counts"][3], -1 + ) + ) + assert self.detection_matches.shape[1] == len(self.cocoDt.anns) + + self.ground_truth_matches = np.vstack( + np.array(self.eval["ground_truth_matches"]).reshape( + self.eval["counts"][0], self.eval["counts"][3], -1 + ) + ) + assert self.ground_truth_matches.shape[1] == len(self.cocoGt.anns) + + self.ground_truth_orig_id = np.vstack( + np.array(self.eval["ground_truth_orig_id"]).reshape( + self.eval["counts"][0], self.eval["counts"][3], -1 + ) + ) + assert self.ground_truth_orig_id.shape[1] == len(self.cocoGt.anns) + self.math_matches() self.matched = True except Exception as e: @@ -149,158 +171,170 @@ def accumulate(self): toc = time.time() - self.print_function('COCOeval_opt.accumulate() finished...') - self.print_function('DONE (t={:0.2f}s).'.format(toc-tic)) - - + self.print_function("COCOeval_opt.accumulate() finished...") + self.print_function("DONE (t={:0.2f}s).".format(toc - tic)) def math_matches(self): - for category_id in range(self.ground_truth_shape[0]): - for area_range_id in range(self.ground_truth_shape[1]): - for iou_tresh_id in range(self.ground_truth_shape[2]): - for _row, gt_id in enumerate(self.ground_truth_orig_id[category_id,area_range_id,iou_tresh_id]): - if gt_id == -1: - continue - - dt_id = self.ground_truth_matches[category_id,area_range_id,iou_tresh_id][_row] - - _gt_ann = self.cocoGt.anns[gt_id] - _dt_ann = self.cocoDt.anns[dt_id] - - if _gt_ann['image_id'] != _dt_ann['image_id']: - continue - - iou = self.computeAnnIoU(_gt_ann, _dt_ann) - - if not _gt_ann.get('matched', False): - _dt_ann['tp'] = True - _dt_ann['gt_id'] = gt_id - _dt_ann['iou'] = iou - - _gt_ann['dt_id'] = dt_id - _gt_ann['matched'] = True - else: - # TODO: Непонятно почему не находит. Проверить на тестовых данных - _old_dt_ann = self.cocoDt.anns.get(_gt_ann['dt_id']) - if _old_dt_ann is None: - continue - - if _old_dt_ann['id'] == _dt_ann['id']: - continue - else: - if (_old_dt_ann.get('iou', self.computeAnnIoU(_gt_ann, _old_dt_ann)) < iou) or (_old_dt_ann['score'] < _dt_ann['score']): - _dt_ann['tp'] = True - _dt_ann['gt_id'] = gt_id - _dt_ann['iou'] = iou - _gt_ann['dt_id'] = dt_id - - for key in ['tp', 'gt_id', 'iou']: - if key in _old_dt_ann: - del _old_dt_ann[key] + for gidx, ground_truth_matches in enumerate(self.ground_truth_matches): + gt_ids = self.ground_truth_orig_id[gidx] + + for idx, dt_id in enumerate(ground_truth_matches): + if dt_id == 0: + continue + + gt_id = gt_ids[idx] + if gt_id == -1: + continue + + _gt_ann = self.cocoGt.anns[gt_id] + _dt_ann = self.cocoDt.anns[dt_id] + + if int(_gt_ann["image_id"]) != int(_dt_ann["image_id"]): + continue + + if self.params.useCats == 1: + if int(_gt_ann["category_id"]) != int(_dt_ann["category_id"]): + continue + + iou = self.computeAnnIoU(_gt_ann, _dt_ann) + + if not _gt_ann.get("matched", False): + _dt_ann["tp"] = True + _dt_ann["gt_id"] = gt_id + _dt_ann["iou"] = iou + + _gt_ann["dt_id"] = dt_id + _gt_ann["matched"] = True + else: + _old_dt_ann = self.cocoDt.anns[_gt_ann["dt_id"]] + + if _old_dt_ann.get("iou", 0) < iou: + for _key in ["tp", "gt_id", "iou"]: + if _old_dt_ann.get(_key) is not None: + del _old_dt_ann[_key] + + _dt_ann["tp"] = True + _dt_ann["gt_id"] = gt_id + _dt_ann["iou"] = iou + + _gt_ann["dt_id"] = dt_id for dt_id in self.cocoDt.anns.keys(): - if self.cocoDt.anns[dt_id].get('gt_id') is None: - self.cocoDt.anns[dt_id]['fp'] = True + if self.cocoDt.anns[dt_id].get("gt_id") is None: + self.cocoDt.anns[dt_id]["fp"] = True for gt_id in self.cocoGt.anns.keys(): - if self.cocoGt.anns[gt_id].get('matched') is None: - self.cocoGt.anns[gt_id]['fn'] = True + if self.cocoGt.anns[gt_id].get("matched") is None: + self.cocoGt.anns[gt_id]["fn"] = True def computeAnnIoU(self, gt_ann, dt_ann): g = [] d = [] - if self.params.iouType == 'segm': - g.append(gt_ann['rle']) - d.append(dt_ann['rle']) - elif self.params.iouType == 'bbox': - g.append(gt_ann['bbox']) - d.append(dt_ann['bbox']) - + if self.params.iouType == "segm": + g.append(gt_ann["rle"]) + d.append(dt_ann["rle"]) + elif self.params.iouType == "bbox": + g.append(gt_ann["bbox"]) + d.append(dt_ann["bbox"]) + return maskUtils.iou(d, g, [0]).max() - - def compute_mIoU(self, categories=None): + + def compute_mIoU(self, categories=None, raw=False): g = [] d = [] s = [] for _, dt_ann in self.cocoDt.anns.items(): - if dt_ann.get('tp', False): - gt_ann = self.cocoGt.anns[dt_ann['gt_id']] - if categories is None or gt_ann['category_id'] in categories: - s.append(dt_ann.get('score', 1)) - if self.params.iouType == 'segm': - g.append(gt_ann['rle']) - d.append(dt_ann['rle']) - elif self.params.iouType == 'bbox': - g.append(gt_ann['bbox']) - d.append(dt_ann['bbox']) + if dt_ann.get("tp", False): + gt_ann = self.cocoGt.anns[dt_ann["gt_id"]] + if categories is None or gt_ann["category_id"] in categories: + s.append(dt_ann.get("score", 1)) + if self.params.iouType == "segm": + g.append(gt_ann["rle"]) + d.append(dt_ann["rle"]) + elif self.params.iouType == "bbox": + g.append(gt_ann["bbox"]) + d.append(dt_ann["bbox"]) else: - raise Exception('unknown iouType for iou computation') + raise Exception("unknown iouType for iou computation") iscrowd = [0 for o in g] - + ious = maskUtils.iou(d, g, iscrowd) + if raw: + return ious + if len(ious) == 0: return 0 else: ious = ious.diagonal() return ious.mean() - + def compute_mAUC(self): aucs = [] - for K in range(self.eval['counts'][2]): - for A in range(self.eval['counts'][3]): - precision_list = self.eval['precision'][0, :, K, A, :].ravel() - + for K in range(self.eval["counts"][2]): + for A in range(self.eval["counts"][3]): + precision_list = self.eval["precision"][0, :, K, A, :].ravel() + recall_list = self.params.recThrs auc = COCOeval_faster.calc_auc(recall_list, precision_list) - + if auc != -1: aucs.append(auc) - + if len(aucs): return sum(aucs) / len(aucs) else: return 0 - + def summarize(self): super().summarize() - + if self.matched: self.all_stats = np.append(self.all_stats, self.compute_mIoU()) self.all_stats = np.append(self.all_stats, self.compute_mAUC()) - @property def stats_as_dict(self): iouType = self.params.iouType - assert (iouType == 'segm' or iouType == - 'bbox'), f'iouType={iouType} not supported' + assert ( + iouType == "segm" or iouType == "bbox" + ), "iouType={} not supported".format(iouType) labels = [ - "AP_all", "AP_50", "AP_75", - "AP_small", "AP_medium", "AP_large", - "AR_all", "AR_second", "AR_third", - "AR_small", "AR_medium", "AR_large", "AR_50", "AR_75"] - + "AP_all", + "AP_50", + "AP_75", + "AP_small", + "AP_medium", + "AP_large", + "AR_all", + "AR_second", + "AR_third", + "AR_small", + "AR_medium", + "AR_large", + "AR_50", + "AR_75", + ] + if self.matched: labels += ["mIoU", "mAUC_" + str(int(self.params.iouThrs[0] * 100))] - + maxDets = self.params.maxDets if len(maxDets) > 1: - labels[6] = f'AR_{maxDets[0]}' + labels[6] = "AR_{}".format(maxDets[0]) if len(maxDets) >= 2: - labels[7] = f'AR_{maxDets[1]}' + labels[7] = "AR_{}".format(maxDets[1]) if len(maxDets) >= 3: - labels[8] = f'AR_{maxDets[2]}' + labels[8] = "AR_{}".format(maxDets[2]) return {_label: float(self.all_stats[i]) for i, _label in enumerate(labels)} - @staticmethod def calc_auc(recall_list, precision_list): # https://towardsdatascience.com/how-to-efficiently-implement-area-under-precision-recall-curve-pr-auc-a85872fd7f14 @@ -313,4 +347,4 @@ def calc_auc(recall_list, precision_list): mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i]) i = np.where(mrec[1:] != mrec[:-1])[0] - return np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1]) \ No newline at end of file + return np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1]) diff --git a/faster_coco_eval/core/mask.py b/faster_coco_eval/core/mask.py index 8e354e7..7925c04 100644 --- a/faster_coco_eval/core/mask.py +++ b/faster_coco_eval/core/mask.py @@ -61,7 +61,7 @@ def iou(d: list, g: list, iscrowd: list): ------- iou_array : np.ndarray Intersection over union between masks or bbox. - """ + """ return _mask.iou(d, g, iscrowd) @@ -71,7 +71,7 @@ def encode(bimask: np.ndarray): return _mask.encode(bimask) elif len(bimask.shape) == 2: h, w = bimask.shape - return _mask.encode(bimask.reshape((h, w, 1), order='F'))[0] + return _mask.encode(bimask.reshape((h, w, 1), order="F"))[0] def decode(rleObjs): diff --git a/faster_coco_eval/extra/__init__.py b/faster_coco_eval/extra/__init__.py index ae324a6..189b32f 100644 --- a/faster_coco_eval/extra/__init__.py +++ b/faster_coco_eval/extra/__init__.py @@ -1,2 +1,2 @@ from .curves import Curves -from .display import PreviewResults \ No newline at end of file +from .display import PreviewResults diff --git a/faster_coco_eval/extra/curves.py b/faster_coco_eval/extra/curves.py index 29573ec..d9bbc52 100644 --- a/faster_coco_eval/extra/curves.py +++ b/faster_coco_eval/extra/curves.py @@ -1,107 +1,88 @@ from ..core.faster_eval_api import COCOeval_faster from .extra import ExtraEval -import numpy as np import logging -import matplotlib.pyplot as plt - -try: - from plotly.subplots import make_subplots - import plotly.graph_objects as go - plotly_available = True -except: - plotly_available = False +from plotly.subplots import make_subplots +import plotly.graph_objects as go logger = logging.getLogger(__name__) + class Curves(ExtraEval): def build_curve(self, label): curve = [] if self.useCats: - cat_ids = list(range(self.eval['precision'].shape[2])) + cat_ids = list(range(self.eval["precision"].shape[2])) else: cat_ids = [0] for category_id in cat_ids: - _label = f"[{label}={category_id}] " + _label = "[{}={}] ".format(label, category_id) if len(cat_ids) == 1: _label = "" - precision_list = self.eval['precision'][:, - :, category_id, :, :].ravel() + precision_list = self.eval["precision"][:, :, category_id, :, :].ravel() recall_list = self.recThrs - scores = self.eval['scores'][:, :, category_id, :, :].ravel() + scores = self.eval["scores"][:, :, category_id, :, :].ravel() auc = round(COCOeval_faster.calc_auc(recall_list, precision_list), 4) - curve.append(dict( - recall_list=recall_list, - precision_list=precision_list, - name=f'{_label}auc: {auc:.3f}', - scores=scores, - auc=auc, - category_id=category_id, - )) + curve.append( + dict( + recall_list=recall_list, + precision_list=precision_list, + name="{}auc: {:.3f}".format(_label, auc), + scores=scores, + auc=auc, + category_id=category_id, + ) + ) return curve - def plot_pre_rec(self, curves=None, plotly_backend=False, label="category_id"): + def plot_pre_rec(self, curves=None, label="category_id"): if curves is None: curves = self.build_curve(label) - use_plotly = False - if plotly_backend: - if plotly_available: - fig = make_subplots(rows=1, cols=1, subplot_titles=[ - 'Precision-Recall']) - use_plotly = True - else: - logger.warning('plotly not instaled...') - - if not use_plotly: - fig, axes = plt.subplots(ncols=1) - fig.set_size_inches(15, 7) - axes = [axes] + fig = go.Figure() for _curve in curves: - recall_list = _curve['recall_list'] - precision_list = _curve['precision_list'] - scores = _curve['scores'] - name = _curve['name'] - - if use_plotly: - fig.add_trace( - go.Scatter( - x=recall_list, - y=precision_list, - name=name, - text=scores, - hovertemplate='Pre: %{y:.3f}
' + - 'Rec: %{x:.3f}
' + - 'Score: %{text:.3f}', - showlegend=True, - mode='lines', - ), - row=1, col=1 + recall_list = _curve["recall_list"] + precision_list = _curve["precision_list"] + scores = _curve["scores"] + name = _curve["name"] + + fig.add_trace( + go.Scatter( + x=recall_list, + y=precision_list, + name=name, + text=scores, + hovertemplate="Pre: %{y:.3f}
" + + "Rec: %{x:.3f}
" + + "Score: %{text:.3f}", + showlegend=True, + mode="lines", ) - else: - axes[0].set_title('Precision-Recall') - axes[0].set_xlabel('Recall') - axes[0].set_ylabel('Precision') - axes[0].plot(recall_list, precision_list, label=name) - axes[0].grid(True) - axes[0].legend() - - if use_plotly: - margin = 0.01 - fig.layout.yaxis.range = [0 - margin, 1 + margin] - fig.layout.xaxis.range = [0 - margin, 1 + margin] - - fig.layout.yaxis.title = 'Precision' - fig.layout.xaxis.title = 'Recall' - - fig.update_layout(height=600, width=1200) - fig.show() - else: - plt.show() \ No newline at end of file + ) + + margin = 0.01 + fig.layout.yaxis.range = [0 - margin, 1 + margin] + fig.layout.xaxis.range = [0 - margin, 1 + margin] + + fig.layout.yaxis.title = "Precision" + fig.layout.xaxis.title = "Recall" + + fig.update_xaxes(showspikes=True) + fig.update_yaxes(showspikes=True) + + layout = { + "title": "Precision-Recall", + "autosize": True, + "height": 600, + "width": 1200, + } + + fig.update_layout(layout) + fig.show() diff --git a/faster_coco_eval/extra/display.py b/faster_coco_eval/extra/display.py index df95991..4c42f98 100644 --- a/faster_coco_eval/extra/display.py +++ b/faster_coco_eval/extra/display.py @@ -5,179 +5,201 @@ import logging import os.path as osp -import matplotlib.pyplot as plt - -try: - import plotly.express as px - plotly_available = True -except: - plotly_available = False +import plotly.express as px +import plotly.graph_objs as go logger = logging.getLogger(__name__) class PreviewResults(ExtraEval): - A = 128 + A = 0.1 DT_COLOR = (238, 130, 238, A) - GT_COLOR = (0, 255, 0, A) - FN_COLOR = (0, 0, 255, A) - FP_COLOR = (255, 0, 0, A) + GT_COLOR = (0, 255, 0, A) + FN_COLOR = (0, 0, 255, A) + FP_COLOR = (255, 0, 0, A) + + def get_ann_poly(self, ann, color, text=None, legendgroup=None): + all_x = [] + all_y = [] - def draw_ann(self, draw, ann, color, width=5): - if self.iouType == 'bbox': - x1, y1, w, h = ann['bbox'] - draw.rectangle([x1, y1, x1+w, y1+h], outline=color, width=width) + if self.iouType == "bbox": + x1, y1, w, h = ann["bbox"] + all_x = [x1, x1 + w, x1 + w, x1, x1, None] + all_y = [y1, y1, y1 + h, y1 + h, y1, None] else: - for poly in ann['segmentation']: + for poly in ann["segmentation"]: if len(poly) > 3: - draw.line(poly, width=width, fill=color, joint='curve') - - def plot_img(self, img, force_matplot=False, figsize=None, slider=False): - if plotly_available and not force_matplot and slider: - fig = px.imshow(img, animation_frame=0, - binary_compression_level=5, - binary_format='jpg', - aspect='auto', - labels=dict(animation_frame="shown picture")) - - fig.update_layout(height=700, width=900) - fig.update_layout(autosize=True) - fig.show() + poly += poly[:2] + poly = np.array(poly).reshape(-1, 2) + all_x += poly[:, 0].tolist() + [None] + all_y += poly[:, 1].tolist() + [None] + + return go.Scatter( + x=all_x, + y=all_y, + name="", + text=text, + hovertemplate="{text}", + mode="lines", + legendgroup=legendgroup, + legendgrouptitle_text=legendgroup, + showlegend=False, + fill="toself", + fillcolor="rgba{}".format(color), + line=dict(color="rgb{}".format(color[:3])), + ) + + def display_image( + self, + image_id=1, + display_fp=True, + display_fn=True, + display_tp=True, + display_gt=True, + data_folder=None, + categories=None, + ): + polygons = [] + + image = self.cocoGt.imgs[image_id] + gt_anns = {ann["id"]: ann for ann in self.cocoGt.imgToAnns[image_id]} + dt_anns = {ann["id"]: ann for ann in self.cocoDt.imgToAnns[image_id]} + + if data_folder is not None: + image_fn = osp.join(data_folder, image["file_name"]) + else: + image_fn = image["file_name"] + if osp.exists(image_fn): + im = Image.open(image_fn).convert("RGB") else: - is_pillow = 'Image' in str(type(img)) - if is_pillow: - img = [img] - count = 1 - elif type(img) is list: - count = len(img) - else: - is_batch = len(img.shape) == 4 - if not is_batch: - img = np.array([img]) - count = img.shape[0] - - for img_i in range(count): - if figsize is not None: - plt.figure(figsize=figsize) - plt.imshow(img[img_i], interpolation='nearest') - plt.axis('off') - plt.show() - - def print_colors_info(self, _print=False): - _print_func = logger.info - if _print: - _print_func = print - - if logger.getEffectiveLevel() <= 20 or _print: - _print_func(f"DT_COLOR : {self.DT_COLOR}") - im = Image.new("RGBA", (64, 32), self.DT_COLOR) - self.plot_img(im, force_matplot=True, figsize=(1, 0.5)) - _print_func("") - - _print_func(f"GT_COLOR : {self.GT_COLOR}") - im = Image.new("RGBA", (64, 32), self.GT_COLOR) - self.plot_img(im, force_matplot=True, figsize=(1, 0.5)) - _print_func("") - - _print_func(f"FN_COLOR : {self.FN_COLOR}") - im = Image.new("RGBA", (64, 32), self.FN_COLOR) - self.plot_img(im, force_matplot=True, figsize=(1, 0.5)) - _print_func("") - - _print_func(f"FP_COLOR : {self.FP_COLOR}") - im = Image.new("RGBA", (64, 32), self.FP_COLOR) - self.plot_img(im, force_matplot=True, figsize=(1, 0.5)) - _print_func("") - - def display_tp_fp_fn(self, image_ids=['all'], - line_width=7, - display_fp=True, - display_fn=True, - display_tp=True, - display_gt=True, - resize_out_image=None, - data_folder=None, - categories=None, - return_img=False, - ): - image_batch = [] - - for image_id, gt_anns in self.cocoGt.imgToAnns.items(): - if (image_id in image_ids) or 'all' in image_ids: - image = self.cocoGt.imgs[image_id] - - if data_folder is not None: - image_fn = osp.join(data_folder, image["file_name"]) - else: - image_fn = image["file_name"] - - if osp.exists(image_fn): - im = Image.open(image_fn).convert("RGB") - else: - logger.warning( - f'[{image_fn}] not found!\nLoading default empty image') - - im = Image.new("RGB", (image['width'], image['height'])) - - mask = Image.new("RGBA", im.size, (0, 0, 0, 0)) - draw = ImageDraw.Draw(mask) - - gt_anns = {ann['id']: ann for ann in gt_anns} - if len(gt_anns) > 0: - for ann in gt_anns.values(): - if categories is None or ann['category_id'] in categories: - is_fn = ann.get('fn', False) - - if is_fn and display_fn: - self.draw_ann( - draw, ann, color=self.FN_COLOR, width=line_width) - elif display_gt: - self.draw_ann( - draw, ann, color=self.GT_COLOR, width=line_width) - - dt_anns = self.cocoDt.imgToAnns[image_id] - dt_anns = {ann['id']: ann for ann in dt_anns} - - if len(dt_anns) > 0: - for ann in dt_anns.values(): - if categories is None or ann['category_id'] in categories: - if ann.get('tp', False): - if display_tp: - self.draw_ann( - draw, ann, color=self.DT_COLOR, width=line_width) - else: - if display_fp: - self.draw_ann( - draw, ann, color=self.FP_COLOR, width=line_width) - - im.paste(mask, mask) - image_batch.append(im) - - if len(image_batch) >= 1 and resize_out_image is None: - resize_out_image = image_batch[0].size - - if return_img: - return image_batch - - if len(image_batch) == 1: - self.plot_img(np.array(image_batch[0].resize(resize_out_image))) - elif len(image_batch) > 1: - image_batch = np.array( - [np.array(image.resize(resize_out_image)) for image in image_batch]) - self.plot_img(image_batch, slider=True) + logger.warning("[{}] not found!\nLoading default empty image".format(image_fn)) + + im = Image.new("RGB", (image["width"], image["height"])) + + categories_labels = { + category["id"]: category["name"] for _, category in self.cocoGt.cats.items() + } + + if len(gt_anns) > 0: + for ann in gt_anns.values(): + if categories is None or ann["category_id"] in categories: + if ann.get("fn", False): + if display_fn: + poly = self.get_ann_poly( + ann, + color=self.FN_COLOR, + text="FN
id={}
category={}".format( + ann["id"], categories_labels[ann["category_id"]] + ), + legendgroup="fn", + ) + polygons.append(poly) + else: + if display_gt: + poly = self.get_ann_poly( + ann, + color=self.GT_COLOR, + text="GT
id={}
category={}".format( + ann["id"], categories_labels[ann["category_id"]] + ), + legendgroup="gt", + ) + polygons.append(poly) + + if len(dt_anns) > 0: + for ann in dt_anns.values(): + if categories is None or ann["category_id"] in categories: + if ann.get("tp", False): + if display_tp: + poly = self.get_ann_poly( + ann, + color=self.DT_COLOR, + text="DT
id={}
category={}
score={:.2f}
IoU={:.2f}".format( + ann["id"], + categories_labels[ann["category_id"]], + ann["score"], + ann["iou"], + ), + legendgroup="tp", + ) + polygons.append(poly) + else: + if display_fp: + poly = self.get_ann_poly( + ann, + color=self.FP_COLOR, + text="FP
id={}
category={}
score={:.2f}".format( + ann["id"], + categories_labels[ann["category_id"]], + ann["score"], + ), + legendgroup="fp", + ) + polygons.append(poly) + + fig = px.imshow( + im, + binary_compression_level=5, + binary_format="jpg", + aspect="auto", + labels=dict(animation_frame="shown picture"), + ) + + legends = {} + for poly in polygons: + if legends.get(poly.legendgroup) is None: + poly.showlegend = True + legends[poly.legendgroup] = True + + fig.add_trace(poly) + + layout = { + "title": "image_id={}
image_fn={}".format(image_id, image_fn), + "autosize": True, + "height": 700, + "width": 900, + } + + fig.update_layout(layout) + fig.update_xaxes(range=[0, image["width"]]) + fig.update_yaxes(range=[image["height"], 0]) + fig.show() + + def display_tp_fp_fn( + self, + image_ids=["all"], + display_fp=True, + display_fn=True, + display_tp=True, + display_gt=False, + data_folder=None, + categories=None, + ): + for image_id, _ in self.cocoGt.imgToAnns.items(): + if (image_id in image_ids) or "all" in image_ids: + self.display_image( + image_id, + display_fp=display_fp, + display_fn=display_fn, + display_tp=display_tp, + display_gt=display_gt, + data_folder=data_folder, + categories=categories, + ) def _compute_confusion_matrix(self, y_true, y_pred, fp={}, fn={}): """ return classes*(classes + fp col + fn col) """ categories_real_ids = list(self.cocoGt.cats) - categories_enum_ids = {category_id: _i for _i, - category_id in enumerate(categories_real_ids)} + categories_enum_ids = { + category_id: _i for _i, category_id in enumerate(categories_real_ids) + } K = len(categories_enum_ids) - cm = np.zeros((K, K + 2), dtype=np.int32) + cm = np.zeros((K, K + 2), dtype=np.float32) for a, p in zip(y_true, y_pred): cm[categories_enum_ids[a]][categories_enum_ids[p]] += 1 @@ -190,7 +212,8 @@ def _compute_confusion_matrix(self, y_true, y_pred, fp={}, fn={}): def compute_confusion_matrix(self): if self.useCats: logger.warning( - f"The calculation may not be accurate. No intersection of classes. useCats={self.useCats}") + "The calculation may not be accurate. No intersection of classes. useCats={}".format(self.useCats) + ) y_true = [] y_pred = [] @@ -199,58 +222,80 @@ def compute_confusion_matrix(self): fp = {} for ann_id, ann in self.cocoGt.anns.items(): - if ann.get('dt_id') is not None: - y_true.append(ann['category_id']) - y_pred.append(self.cocoDt.anns[ann['dt_id']]['category_id']) + if ann.get("dt_id") is not None: + dt_ann = self.cocoDt.anns[ann["dt_id"]] + + y_true.append(ann["category_id"]) + y_pred.append(dt_ann["category_id"]) else: - if fn.get(ann['category_id']) is None: - fn[ann['category_id']] = 0 - fn[ann['category_id']] += 1 - + if fn.get(ann["category_id"]) is None: + fn[ann["category_id"]] = 0 + fn[ann["category_id"]] += 1 + for ann_id, ann in self.cocoDt.anns.items(): - if ann.get('gt_id') is None: - if fp.get(ann['category_id']) is None: - fp[ann['category_id']] = 0 - fp[ann['category_id']] += 1 + if ann.get("gt_id") is None: + if fp.get(ann["category_id"]) is None: + fp[ann["category_id"]] = 0 + fp[ann["category_id"]] += 1 # classes fp fn cm = self._compute_confusion_matrix(y_true, y_pred, fp=fp, fn=fn) return cm - def display_matrix(self, in_percent=False, conf_matrix=None, figsize=(10, 10), fontsize=16): + def display_matrix(self, in_percent=False, conf_matrix=None): if conf_matrix is None: conf_matrix = self.compute_confusion_matrix() - names = [category['name'] - for category_id, category in self.cocoGt.cats.items()] - names += ['fp', 'fn'] + labels = [category["name"] for _, category in self.cocoGt.cats.items()] + labels += ["fp", "fn"] if in_percent: - sum_by_col = conf_matrix.sum(axis=1) - - fig, ax = plt.subplots(figsize=figsize) - ax.matshow(conf_matrix, cmap='Blues', alpha=0.3) - for i in range(conf_matrix.shape[0]): - for j in range(conf_matrix.shape[1]): + conf_matrix /= conf_matrix.sum(axis=1).reshape(-1, 1) + conf_matrix *= 100 - value = conf_matrix[i, j] + hovertemplate = "Real: %{y}
" "Predict: %{x}
" - if in_percent: - value = int(value / sum_by_col[i] * 100) - - if value > 0: - ax.text(x=j, y=i, s=value, va='center', ha='center') - - plt.xlabel('Predictions', fontsize=fontsize) - plt.ylabel('Actuals', fontsize=fontsize) - - plt.xticks(list(range(len(names))), names, rotation=90) - plt.yticks(list(range(len(names[:-2]))), names[:-2]) - - title = 'Confusion Matrix' if in_percent: - title += ' [%]' - - plt.title(title, fontsize=fontsize) - plt.show() + hovertemplate += "Percent: %{z:.0f}" + else: + hovertemplate += "Count: %{z:.0f}" + + heatmap = go.Heatmap( + z=conf_matrix, + x=labels, + y=labels[:-2], + colorscale="Blues", + hovertemplate=hovertemplate, + ) + + annotations = [] + for j, row in enumerate(conf_matrix): + for i, value in enumerate(row): + text_value = "{:.0f}".format(value) + if in_percent: + text_value += "%" + + annotations.append( + { + "x": labels[i], + "y": labels[j], + "font": {"color": "white"}, + "text": text_value, + "xref": "x1", + "yref": "y1", + "showarrow": False, + } + ) + + layout = { + "title": "Confusion Matrix", + "xaxis": {"title": "Predicted value"}, + "yaxis": {"title": "Real value"}, + "annotations": annotations, + } + + fig = go.Figure(data=[heatmap], layout=layout) + fig.update_traces(showscale=False) + fig.update_layout(height=700, width=900) + fig.show() diff --git a/faster_coco_eval/extra/extra.py b/faster_coco_eval/extra/extra.py index 640ead4..e420e52 100644 --- a/faster_coco_eval/extra/extra.py +++ b/faster_coco_eval/extra/extra.py @@ -3,26 +3,29 @@ import numpy as np import logging +import copy logger = logging.getLogger(__name__) -class ExtraEval(): - def __init__(self, - cocoGt: COCO = None, - cocoDt: COCO = None, - iouType: str = 'bbox', - min_score: float = 0, - iou_tresh: float = 0.0, - recall_count: int = 100, - useCats: bool = False, - ): + +class ExtraEval: + def __init__( + self, + cocoGt: COCO = None, + cocoDt: COCO = None, + iouType: str = "bbox", + min_score: float = 0, + iou_tresh: float = 0.0, + recall_count: int = 100, + useCats: bool = False, + ): self.iouType = iouType self.min_score = min_score self.iou_tresh = iou_tresh self.useCats = useCats self.recall_count = recall_count - self.cocoGt = cocoGt - self.cocoDt = cocoDt + self.cocoGt = copy.deepcopy(cocoGt) + self.cocoDt = copy.deepcopy(cocoDt) self.evaluate() @@ -36,10 +39,10 @@ def evaluate(self): cocoEval.params.recThrs = self.recThrs cocoEval.params.useCats = int(self.useCats) # Выключение labels - + self.cocoEval = cocoEval cocoEval.evaluate() cocoEval.accumulate() - - self.eval = cocoEval.eval \ No newline at end of file + + self.eval = cocoEval.eval diff --git a/faster_coco_eval/version.py b/faster_coco_eval/version.py index 5ea556a..d0206d6 100644 --- a/faster_coco_eval/version.py +++ b/faster_coco_eval/version.py @@ -1,2 +1,2 @@ -__version__ = '1.3.3' -__author__ = 'MiXaiLL76' +__version__ = "1.4.0" +__author__ = "MiXaiLL76" diff --git a/requirements/optional.txt b/requirements/optional.txt index 16d5dd3..d42d0ad 100644 --- a/requirements/optional.txt +++ b/requirements/optional.txt @@ -1,3 +1 @@ -matplotlib -Pillow plotly \ No newline at end of file diff --git a/setup.py b/setup.py index 1d5f6d9..c2de4b9 100644 --- a/setup.py +++ b/setup.py @@ -101,8 +101,8 @@ def get_extensions(version_info): "csrc/faster_eval_api/coco_eval/cocoeval.cpp", "csrc/faster_eval_api/faster_eval_api.cpp", ] - print(f"Sources: {sources}") - + print("Sources: {}".format(sources)) + ext_modules += [ Pybind11Extension( name="faster_coco_eval.faster_eval_api_cpp", @@ -120,8 +120,8 @@ def get_extensions(version_info): 'csrc/mask/common' ] - print(f"Sources: {sources}") - print(f"Include: {include_dirs}") + print("Sources: {}".format(sources)) + print("Include: {}".format(include_dirs)) ext_modules += [ Extension( diff --git a/tests/basic.py b/tests/basic.py index 1ca121e..115e50a 100644 --- a/tests/basic.py +++ b/tests/basic.py @@ -14,28 +14,29 @@ def load(file): class TestBaseCoco(unittest.TestCase): def test_coco(self): - prepared_coco_in_dict = load('data/gt_cat_dog.json') - prepared_anns = load('data/dt_cat_dog.json') + prepared_coco_in_dict = load("dataset/gt_dataset.json") + prepared_anns = load("dataset/dt_dataset.json") + stats_as_dict = { - 'AP_all': 0.6084394153701084, - 'AP_50': 0.7383309759547382, - 'AP_75': 0.7383309759547382, - 'AP_small': -1.0, - 'AP_medium': -1.0, - 'AP_large': 0.6084394153701084, - 'AR_all': 0.7166666666666666, - 'AR_second': 0.0, - 'AR_third': 0.0, - 'AR_small': -1.0, - 'AR_medium': -1.0, - 'AR_large': 0.7166666666666666, - 'AR_50': 0.8333333333333334, - 'AR_75': 0.8333333333333334, - 'mIoU': 0.9042780340786216, - 'mAUC_50': 0.7357142857142857, + "AP_all": 0.7832783278327835, + "AP_50": 0.7832783278327836, + "AP_75": 0.7832783278327836, + "AP_small": -1.0, + "AP_medium": 1.0, + "AP_large": 0.0, + "AR_all": 0.888888888888889, + "AR_second": 0.0, + "AR_third": 0.0, + "AR_small": -1.0, + "AR_medium": 1.0, + "AR_large": 0.0, + "AR_50": 0.8888888888888888, + "AR_75": 0.8888888888888888, + "mIoU": 1.0, + "mAUC_50": 0.594074074074074, } - iouType = 'segm' + iouType = "segm" useCats = False cocoGt = COCO(prepared_coco_in_dict) @@ -56,22 +57,33 @@ def test_coco(self): class TestConfusionMatrix(unittest.TestCase): def test_coco(self): - prepared_coco_in_dict = load('data/gt_cat_dog.json') - prepared_anns = load('data/dt_cat_dog.json') - prepared_result = [[2, 0, 2, 1], [0, 3, 0, 0]] + prepared_coco_in_dict = load("dataset/gt_dataset.json") + prepared_anns = load("dataset/dt_dataset.json") + + prepared_result = [ + [2.0, 1.0, 0.0, 0.0, 1.0, 0.0], + [1.0, 1.0, 0.0, 0.0, 0.0, 1.0], + [0.0, 0.0, 1.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 2.0, 0.0, 0.0], + ] - iouType = 'segm' + iouType = "segm" useCats = False cocoGt = COCO(prepared_coco_in_dict) cocoDt = cocoGt.loadRes(prepared_anns) results = PreviewResults( - cocoGt=cocoGt, cocoDt=cocoDt, iouType=iouType, iou_tresh=0.5, useCats=useCats) + cocoGt=cocoGt, + cocoDt=cocoDt, + iouType=iouType, + iou_tresh=0.5, + useCats=useCats, + ) result_cm = results.compute_confusion_matrix().tolist() self.assertEqual(result_cm, prepared_result) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/tests/data/dt_cat_dog.json b/tests/data/dt_cat_dog.json deleted file mode 100644 index 6e64d50..0000000 --- a/tests/data/dt_cat_dog.json +++ /dev/null @@ -1,1110 +0,0 @@ -[ - { - "id": 0, - "iscrowd": 0, - "image_id": 1, - "category_id": 1, - "score" : 1.0, - "segmentation": [ - [ - 100.95959595959614, - 3089.989898989899, - 604.818181818182, - 3028.292929292929, - 903.0202020202022, - 2781.5050505050503, - 1175.5151515151515, - 2580.989898989899, - 1489.1414141414143, - 2462.7373737373737, - 1679.3737373737374, - 2385.616161616161, - 1951.8686868686868, - 2349.6262626262624, - 2352.89898989899, - 2473.020202020202, - 2481.4343434343436, - 2488.4444444444443, - 2486.5757575757575, - 2087.4141414141413, - 2548.2727272727275, - 2025.7171717171716, - 2476.2929292929293, - 1773.7878787878788, - 2584.2626262626263, - 1588.6969696969695, - 2712.7979797979797, - 1650.3939393939393, - 2841.3333333333335, - 1809.7777777777776, - 3149.8181818181815, - 1814.9191919191917, - 3278.3535353535353, - 1475.5858585858584, - 3376.040404040404, - 1475.5858585858584, - 3463.4444444444443, - 1604.121212121212, - 3484.0101010101007, - 1773.7878787878788, - 3473.7272727272725, - 1897.181818181818, - 3520, - 2020.5757575757575, - 3566.272727272727, - 2097.6969696969695, - 3617.6868686868684, - 2262.222222222222, - 3741.080808080808, - 2534.7171717171714, - 3735.939393939394, - 2863.7676767676767, - 3653.6767676767677, - 3197.959595959596, - 3365.7575757575755, - 3295.646464646464, - 3247.5050505050503, - 3609.272727272727, - 3046.989898989899, - 3629.8383838383834, - 2928.7373737373737, - 3748.090909090909, - 2723.080808080808, - 3773.7979797979797, - 2502, - 3501.30303030303, - 2352.89898989899, - 3413.89898989899, - 2013.5656565656566, - 3439.6060606060605, - 1828.4747474747476, - 3444.7474747474744, - 1627.959595959596, - 3480.7373737373737, - 1412.020202020202, - 3511.585858585858, - 1283.4848484848485, - 3583.5656565656564, - 1190.939393939394, - 3527.0101010101007, - 1005.848484848485, - 3568.141414141414, - 651.0909090909092, - 3542.434343434343, - 625.3838383838386, - 3665.8282828282827, - 409.4444444444446, - 3670.9696969696965, - 224.35353535353553, - 3583.5656565656564, - 286.0505050505052, - 3403.616161616161, - 8.414141414141607, - 3439.6060606060605, - 8.414141414141607, - 3095.1313131313127 - ] - ], - "bbox": [ - 8.414141414141607, - 1475.5858585858584, - 3732.666666666666, - 2298.212121212121 - ], - "area": 4223541.052545659 - }, - { - "id": 1, - "iscrowd": 0, - "image_id": 1, - "category_id": 2, - "score" : 0.7, - "segmentation": [ - [ - 3242.3636363636365, - 776.3535353535353, - 3293.777777777778, - 925.4545454545454, - 3298.9191919191917, - 992.2929292929292, - 3304.060606060606, - 1095.121212121212, - 3360.6161616161617, - 1136.2525252525252, - 3422.313131313131, - 1100.262626262626, - 3643.3939393939395, - 1203.090909090909, - 3715.373737373737, - 1249.3636363636363, - 3782.212121212121, - 1357.3333333333333, - 3782.212121212121, - 1521.8585858585857, - 3741.080808080808, - 1706.949494949495, - 3694.808080808081, - 1943.4545454545453, - 3689.6666666666665, - 2071.989898989899, - 3689.6666666666665, - 2143.969696969697, - 3746.222222222222, - 2313.6363636363635, - 3807.9191919191917, - 2545, - 3818.20202020202, - 2678.6767676767677, - 3828.4848484848485, - 2848.343434343434, - 3792.494949494949, - 3028.292929292929, - 3751.363636363636, - 3125.9797979797977, - 3746.222222222222, - 3233.9494949494947, - 3597.121212121212, - 3357.343434343434, - 3504.5757575757575, - 3419.0404040404037, - 3386.3232323232323, - 3527.0101010101007, - 3293.777777777778, - 3619.555555555555, - 3201.2323232323233, - 3691.5353535353534, - 3129.252525252525, - 3758.373737373737, - 3154.959595959596, - 3784.080808080808, - 3591.9797979797977, - 3778.9393939393935, - 3951.8787878787875, - 3763.515151515151, - 4183.242424242424, - 3784.080808080808, - 4291.212121212121, - 3799.5050505050503, - 4455.737373737374, - 3629.8383838383834, - 4568.848484848485, - 3634.9797979797977, - 5334.919191919192, - 3573.282828282828, - 5489.161616161616, - 3573.282828282828, - 5627.979797979798, - 3573.282828282828, - 5771.939393939394, - 3547.5757575757575, - 5931.323232323232, - 3537.292929292929, - 5982.737373737374, - 3326.494949494949, - 5987.878787878788, - 2971.7373737373737, - 5967.313131313131, - 2755.7979797979797, - 5977.595959595959, - 2591.272727272727, - 5972.454545454545, - 2287.929292929293, - 5972.454545454545, - 2215.9494949494947, - 5756.515151515151, - 2200.525252525252, - 5381.191919191919, - 2143.969696969697, - 4923.60606060606, - 1979.4444444444443, - 4743.656565656565, - 1892.040404040404, - 4831.060606060606, - 1732.6565656565656, - 4872.191919191919, - 1532.141414141414, - 4903.040404040404, - 1455.0202020202019, - 5016.151515151515, - 1460.161616161616, - 5226.949494949495, - 1444.7373737373737, - 5247.515151515151, - 1393.323232323232, - 5427.464646464647, - 1521.8585858585857, - 5437.747474747474, - 1604.121212121212, - 5509.727272727272, - 1624.6868686868686, - 5561.141414141414, - 1460.161616161616, - 5633.121212121212, - 1377.8989898989898, - 5571.424242424242, - 1249.3636363636363, - 5473.737373737374, - 1197.949494949495, - 5365.767676767677, - 1095.121212121212, - 5283.50505050505, - 1033.4242424242423, - 5201.242424242424, - 1007.7171717171716, - 5103.555555555556, - 992.2929292929292, - 4959.595959595959, - 951.161616161616, - 4815.636363636363, - 935.7373737373737, - 4738.515151515151, - 925.4545454545454, - 4579.131313131313, - 786.6363636363636, - 4502.010101010101, - 724.9393939393939, - 4306.636363636363, - 704.3737373737373, - 4162.676767676768, - 714.6565656565656, - 3982.7272727272725, - 766.070707070707, - 3915.8888888888887, - 735.2222222222222, - 3725.6565656565654, - 668.3838383838383, - 3576.5555555555557, - 658.10101010101, - 3406.8888888888887, - 694.090909090909 - ] - ], - "bbox": [ - 3129.252525252525, - 658.10101010101, - 2858.626262626263, - 3141.40404040404 - ], - "area": 5565113.276961538 - }, - { - "id": 2, - "iscrowd": 0, - "image_id": 2, - "category_id": 2, - "score" : 0.6, - "segmentation": [ - [ - 885.1948051948051, - 1009.8701298701297, - 1117.9220779220777, - 841.5584415584415, - 1423.3766233766232, - 619.2207792207791, - 1510.6493506493505, - 610.9090909090909, - 1494.025974025974, - 548.5714285714286, - 1533.5064935064934, - 396.8831168831168, - 1645.7142857142856, - 309.6103896103896, - 1791.168831168831, - 236.88311688311686, - 1843.116883116883, - 218.18181818181816, - 1922.0779220779218, - 74.8051948051948, - 1996.8831168831166, - 37.4025974025974, - 2015.5844155844154, - 31.168831168831165, - 2077.9220779220777, - 12.467532467532466, - 2144.4155844155844, - 6.233766233766233, - 2185.9740259740256, - 20.77922077922078, - 2215.064935064935, - 41.55844155844156, - 2237.9220779220777, - 56.1038961038961, - 2273.246753246753, - 74.8051948051948, - 2314.805194805195, - 112.2077922077922, - 2325.1948051948048, - 139.2207792207792, - 2323.116883116883, - 297.1428571428571, - 2314.805194805195, - 311.68831168831167, - 2289.87012987013, - 292.987012987013, - 2208.8311688311687, - 251.42857142857142, - 2181.8181818181815, - 230.64935064935062, - 2152.7272727272725, - 220.25974025974023, - 2142.337662337662, - 214.025974025974, - 2113.246753246753, - 197.4025974025974, - 2080, - 187.012987012987, - 2077.9220779220777, - 187.012987012987, - 2052.987012987013, - 195.3246753246753, - 2040.5194805194803, - 205.7142857142857, - 2036.3636363636363, - 226.49350649350646, - 2030.12987012987, - 236.88311688311686, - 2025.9740259740258, - 251.42857142857142, - 2036.3636363636363, - 265.97402597402595, - 2073.7662337662337, - 278.4415584415584, - 2098.7012987012986, - 292.987012987013, - 2146.493506493506, - 319.99999999999994, - 2167.272727272727, - 336.6233766233766, - 2188.051948051948, - 344.93506493506493, - 2204.6753246753246, - 355.3246753246753, - 2215.064935064935, - 363.6363636363636, - 2235.8441558441555, - 376.1038961038961, - 2250.38961038961, - 390.6493506493506, - 2264.935064935065, - 415.5844155844155, - 2279.4805194805194, - 428.051948051948, - 2291.9480519480517, - 446.7532467532467, - 2298.181818181818, - 469.6103896103896, - 2298.181818181818, - 496.6233766233766, - 2298.181818181818, - 511.1688311688311, - 2302.337662337662, - 536.1038961038961, - 2310.6493506493503, - 550.6493506493506, - 2314.805194805195, - 558.9610389610389, - 2321.0389610389607, - 588.051948051948, - 2321.0389610389607, - 621.2987012987012, - 2314.805194805195, - 648.3116883116883, - 2310.6493506493503, - 685.7142857142857, - 2308.5714285714284, - 702.3376623376623, - 2306.493506493506, - 712.7272727272726, - 2306.493506493506, - 718.9610389610389, - 2304.4155844155844, - 741.8181818181818, - 2304.4155844155844, - 777.1428571428571, - 2308.5714285714284, - 812.4675324675324, - 2308.5714285714284, - 843.6363636363635, - 2308.5714285714284, - 856.103896103896, - 2323.116883116883, - 870.6493506493506, - 2331.428571428571, - 883.1168831168831, - 2387.5324675324673, - 968.3116883116883, - 2406.233766233766, - 1032.7272727272725, - 2410.38961038961, - 1088.8311688311687, - 2395.8441558441555, - 1111.6883116883116, - 2383.3766233766232, - 1128.3116883116882, - 2377.142857142857, - 1138.7012987012986, - 2354.285714285714, - 1124.155844155844, - 2341.8181818181815, - 1130.3896103896102, - 2331.428571428571, - 1147.012987012987, - 2312.7272727272725, - 1159.4805194805194, - 2298.181818181818, - 1174.025974025974, - 2279.4805194805194, - 1188.5714285714284, - 2252.4675324675322, - 1196.8831168831168, - 2235.8441558441555, - 1205.194805194805, - 2227.5324675324673, - 1209.3506493506493, - 2208.8311688311687, - 1225.9740259740258, - 2208.8311688311687, - 1232.2077922077922, - 2217.142857142857, - 1273.7662337662337, - 2219.220779220779, - 1294.5454545454545, - 2221.298701298701, - 1309.090909090909, - 2229.6103896103896, - 1327.7922077922076, - 2235.8441558441555, - 1340.25974025974, - 2233.7662337662337, - 1356.8831168831168, - 2217.142857142857, - 1394.2857142857142, - 2202.5974025974024, - 1404.6753246753246, - 2179.7402597402597, - 1410.9090909090908, - 2167.272727272727, - 1412.9870129870128, - 2131.9480519480517, - 1419.2207792207791, - 2098.7012987012986, - 1421.2987012987012, - 2084.155844155844, - 1412.9870129870128, - 2071.6883116883114, - 1408.8311688311687, - 2023.8961038961038, - 1385.9740259740258, - 2023.8961038961038, - 1385.9740259740258, - 2017.6623376623374, - 1371.4285714285713, - 2015.5844155844154, - 1371.4285714285713, - 1992.7272727272725, - 1381.8181818181818, - 1969.8701298701296, - 1390.12987012987, - 1957.4025974025972, - 1392.2077922077922, - 1938.7012987012986, - 1392.2077922077922, - 1919.9999999999998, - 1396.3636363636363, - 1899.2207792207791, - 1400.5194805194803, - 1888.8311688311687, - 1400.5194805194803, - 1874.2857142857142, - 1404.6753246753246, - 1855.5844155844154, - 1421.2987012987012, - 1843.116883116883, - 1435.8441558441557, - 1836.8831168831166, - 1448.3116883116882, - 1828.5714285714284, - 1460.7792207792206, - 1797.4025974025972, - 1479.4805194805194, - 1741.2987012987012, - 1514.8051948051946, - 1716.3636363636363, - 1518.9610389610389, - 1699.7402597402595, - 1523.116883116883, - 1685.194805194805, - 1523.116883116883, - 1676.8831168831168, - 1523.116883116883, - 1645.7142857142856, - 1516.8831168831168, - 1641.5584415584415, - 1516.8831168831168, - 1616.6233766233765, - 1510.6493506493505, - 1593.7662337662337, - 1504.4155844155844, - 1556.3636363636363, - 1481.5584415584415, - 1539.7402597402595, - 1458.7012987012986, - 1531.4285714285713, - 1431.6883116883116, - 1531.4285714285713, - 1415.0649350649348, - 1531.4285714285713, - 1383.8961038961038, - 1531.4285714285713, - 1371.4285714285713, - 1537.6623376623374, - 1356.8831168831168, - 1539.7402597402595, - 1344.4155844155844, - 1545.9740259740258, - 1325.7142857142856, - 1533.5064935064934, - 1321.5584415584415, - 1483.6363636363635, - 1311.168831168831, - 1485.7142857142856, - 1302.8571428571427, - 1473.246753246753, - 1267.5324675324673, - 1452.4675324675322, - 1217.6623376623374, - 1450.3896103896102, - 1198.9610389610389, - 1452.4675324675322, - 1178.181818181818, - 1467.012987012987, - 1161.5584415584415, - 1491.948051948052, - 1147.012987012987, - 1514.8051948051946, - 1124.155844155844, - 1527.272727272727, - 1107.5324675324675, - 1541.8181818181818, - 1065.9740259740258, - 1552.207792207792, - 1047.2727272727273, - 1558.4415584415583, - 1022.3376623376622, - 1556.3636363636363, - 999.4805194805194, - 1525.194805194805, - 999.4805194805194, - 1512.7272727272725, - 999.4805194805194, - 1512.7272727272725, - 949.6103896103896, - 1516.8831168831168, - 918.4415584415583, - 1527.272727272727, - 889.3506493506493, - 1537.6623376623374, - 870.6493506493506, - 1548.0519480519479, - 839.4805194805194, - 1548.0519480519479, - 827.012987012987, - 1531.4285714285713, - 808.3116883116883, - 1516.8831168831168, - 799.9999999999999, - 1487.7922077922076, - 789.6103896103896, - 1446.2337662337661, - 787.5324675324674, - 1408.8311688311687, - 791.6883116883116, - 1365.194805194805, - 802.077922077922, - 1315.3246753246751, - 804.1558441558441, - 1294.5454545454545, - 795.8441558441558, - 1277.9220779220777, - 785.4545454545454, - 1238.4415584415583, - 770.9090909090909, - 1232.2077922077922, - 824.9350649350648, - 1248.8311688311687, - 849.8701298701297, - 1257.142857142857, - 860.2597402597402, - 1238.4415584415583, - 878.9610389610389, - 1217.6623376623374, - 883.1168831168831, - 1188.5714285714284, - 899.7402597402596, - 1159.4805194805194, - 926.7532467532467, - 1126.2337662337661, - 955.8441558441558, - 1107.5324675324675, - 976.6233766233765, - 1080.5194805194803, - 1009.8701298701297, - 1061.8181818181818, - 1038.9610389610389, - 1036.8831168831168, - 1080.5194805194803, - 1018.1818181818181, - 1095.064935064935, - 1016.103896103896, - 1095.064935064935, - 984.9350649350648, - 1101.2987012987012, - 953.7662337662337, - 1101.2987012987012, - 935.064935064935, - 1101.2987012987012, - 901.8181818181818, - 1101.2987012987012, - 881.0389610389609, - 1078.4415584415583, - 889.3506493506493, - 1057.6623376623374 - ] - ], - "bbox": [ - 1477.4025974025972, - 211.94805194805193, - 908.0519480519479, - 1286.2337662337661 - ], - "area": 890848.9121268343 - }, - { - "id": 3, - "iscrowd": 0, - "image_id": 2, - "category_id": 1, - "score" : 0.6, - "segmentation": [ - [ - 1533.5064935064934, - 829.090909090909, - 1533.5064935064934, - 893.5064935064934, - 1533.5064935064934, - 989.090909090909, - 1521.038961038961, - 1074.2857142857142, - 1502.337662337662, - 1190.6493506493505, - 1473.246753246753, - 1286.2337662337661, - 1433.7662337662337, - 1334.025974025974, - 1334.025974025974, - 1367.2727272727273, - 1259.2207792207791, - 1379.7402597402597, - 1174.025974025974, - 1429.6103896103896, - 1101.2987012987012, - 1467.012987012987, - 1051.4285714285713, - 1502.337662337662, - 1020.2597402597402, - 1512.7272727272725, - 989.090909090909, - 1489.8701298701296, - 978.7012987012986, - 1452.4675324675322, - 1003.6363636363635, - 1379.7402597402597, - 1063.8961038961038, - 1352.7272727272725, - 1122.077922077922, - 1321.5584415584415, - 1157.4025974025974, - 1294.5454545454545, - 1159.4805194805194, - 1277.9220779220777, - 1092.9870129870128, - 1304.9350649350647, - 1063.8961038961038, - 1323.6363636363635, - 1049.3506493506493, - 1300.7792207792206, - 1043.116883116883, - 1246.7532467532467, - 1047.2727272727273, - 1155.3246753246751, - 1049.3506493506493, - 1107.5324675324675, - 1061.8181818181818, - 1038.9610389610389, - 1153.246753246753, - 943.3766233766233, - 1198.9610389610389, - 878.9610389610389, - 1242.5974025974024, - 847.7922077922077, - 1257.142857142857, - 777.1428571428571, - 1437.9220779220777, - 804.1558441558441, - 1489.8701298701296, - 810.3896103896103, - 1543.8961038961038, - 824.9350649350648 - ] - ], - "bbox": [ - 978.7012987012986, - 777.1428571428571, - 565.1948051948052, - 735.5844155844154 - ], - "area": 251237.5105414065 - }, - { - "id": 4, - "iscrowd": 0, - "image_id": 2, - "category_id": 1, - "score" : 0.65, - "segmentation": [ - [ - 1460.7792207792206, - 615.064935064935, - 1344.4155844155844, - 642.077922077922, - 1259.2207792207791, - 689.8701298701299, - 1190.6493506493505, - 748.051948051948, - 1165.7142857142856, - 787.5324675324674, - 1101.2987012987012, - 841.5584415584415, - 1016.103896103896, - 905.9740259740258, - 945.4545454545454, - 953.7662337662337, - 905.9740259740258, - 976.6233766233765, - 860.2597402597402, - 984.9350649350648, - 797.9220779220778, - 945.4545454545454, - 723.1168831168831, - 935.064935064935, - 631.6883116883116, - 943.3766233766233, - 567.2727272727273, - 951.6883116883116, - 479.99999999999994, - 966.2337662337661, - 448.8311688311688, - 930.9090909090908, - 457.1428571428571, - 889.3506493506493, - 459.22077922077915, - 851.9480519480519, - 450.9090909090909, - 816.6233766233765, - 590.12987012987, - 806.2337662337661, - 654.5454545454545, - 804.1558441558441, - 696.1038961038961, - 804.1558441558441, - 718.9610389610389, - 791.6883116883116, - 764.6753246753246, - 754.2857142857142, - 789.6103896103896, - 706.4935064935064, - 835.3246753246752, - 679.4805194805194, - 899.7402597402596, - 664.9350649350649, - 957.9220779220778, - 652.4675324675324, - 1078.4415584415583, - 619.2207792207791, - 1097.142857142857, - 615.064935064935, - 1136.6233766233765, - 612.9870129870129, - 1223.8961038961038, - 615.064935064935, - 1304.9350649350647, - 629.6103896103896, - 1338.181818181818, - 629.6103896103896, - 1390.12987012987, - 612.9870129870129, - 1433.7662337662337, - 606.7532467532467 - ] - ], - "bbox": [ - 448.8311688311688, - 606.7532467532467, - 1011.9480519480519, - 378.18181818181813 - ], - "area": 165996.2894248608 - }, - { - "id": 5, - "iscrowd": 0, - "image_id": 3, - "category_id": 1, - "score" : 0.8, - "segmentation": [ - [ - 919.4805194805195, - 892.987012987013, - 847.7922077922078, - 917.922077922078, - 763.6363636363636, - 983.3766233766235, - 695.0649350649351, - 1033.2467532467533, - 635.8441558441559, - 1104.935064935065, - 595.3246753246754, - 1154.8051948051948, - 551.6883116883117, - 1248.3116883116884, - 504.935064935065, - 1323.1168831168832, - 467.53246753246754, - 1376.1038961038962, - 436.3636363636364, - 1450.909090909091, - 392.72727272727275, - 1516.3636363636365, - 342.8571428571429, - 1553.7662337662339, - 333.50649350649354, - 1600.5194805194806, - 458.1818181818182, - 1684.6753246753246, - 517.4025974025974, - 1687.7922077922078, - 670.1298701298701, - 1762.5974025974026, - 794.8051948051948, - 1790.6493506493507, - 900.7792207792209, - 1818.7012987012988, - 1006.7532467532468, - 1877.922077922078, - 1112.7272727272727, - 1927.7922077922078, - 1231.1688311688313, - 1940.2597402597403, - 1387.012987012987, - 2011.9480519480521, - 1468.051948051948, - 2036.883116883117, - 1648.831168831169, - 2036.883116883117, - 1689.3506493506495, - 2002.5974025974026, - 1726.753246753247, - 1983.896103896104, - 1823.3766233766235, - 1974.5454545454547, - 1907.5324675324675, - 1980.7792207792209, - 1997.922077922078, - 2018.1818181818182, - 2025.974025974026, - 2055.5844155844156, - 2125.714285714286, - 2061.818181818182, - 2247.2727272727275, - 2068.0519480519483, - 2353.2467532467535, - 2068.0519480519483, - 2418.701298701299, - 2011.9480519480521, - 2368.8311688311687, - 1893.5064935064936, - 2247.2727272727275, - 1790.6493506493507, - 2156.883116883117, - 1690.909090909091, - 2113.2467532467535, - 1644.1558441558443, - 2044.6753246753249, - 1578.7012987012988, - 2013.5064935064936, - 1482.077922077922, - 2038.4415584415585, - 1401.0389610389611, - 2029.0909090909092, - 1260.7792207792209, - 2004.1558441558443, - 1039.4805194805194, - 2038.4415584415585, - 830.6493506493507, - 2038.4415584415585, - 740.2597402597403, - 2016.6233766233768, - 665.4545454545455, - 1988.5714285714287, - 547.0129870129871, - 1979.2207792207794, - 475.32467532467535, - 1851.4285714285716, - 459.7402597402598, - 1742.3376623376623, - 475.32467532467535, - 1580.2597402597403, - 522.0779220779222, - 1399.4805194805197, - 515.8441558441559, - 1318.4415584415585, - 515.8441558441559, - 1175.064935064935, - 522.0779220779222, - 1087.7922077922078, - 587.5324675324675, - 1022.3376623376624, - 699.7402597402598, - 969.3506493506494, - 811.948051948052 - ] - ], - "bbox": [ - 333.50649350649354, - 459.7402597402598, - 2085.1948051948057, - 1608.3116883116886 - ], - "area": 2027852.2516444596 - }, - { - "id": 6, - "iscrowd": 0, - "image_id": 3, - "category_id": 2, - "score" : 0.51, - "segmentation": [ - [ - 2078.961038961039, - 702.8571428571429, - 2153.7662337662337, - 727.7922077922078, - 2203.636363636364, - 774.5454545454546, - 2262.857142857143, - 827.5324675324675, - 2312.727272727273, - 861.8181818181819, - 2431.1688311688313, - 815.0649350649351, - 2608.831168831169, - 783.8961038961039, - 2730.3896103896104, - 765.1948051948052, - 2889.3506493506493, - 755.8441558441559, - 3007.792207792208, - 762.0779220779222, - 3110.6493506493507, - 836.8831168831169, - 3148.0519480519483, - 936.6233766233767, - 3166.753246753247, - 1008.3116883116884, - 3232.2077922077924, - 1111.1688311688313, - 3300.779220779221, - 1260.7792207792209, - 3325.714285714286, - 1372.987012987013, - 3372.4675324675327, - 1466.4935064935066, - 3422.3376623376626, - 1535.064935064935, - 3484.6753246753246, - 1616.1038961038962, - 3550.12987012987, - 1731.4285714285716, - 3612.4675324675327, - 1787.5324675324675, - 3652.9870129870133, - 1856.1038961038962, - 3677.922077922078, - 1924.6753246753249, - 3631.1688311688313, - 1971.4285714285716, - 3540.779220779221, - 1990.1298701298701, - 3472.2077922077924, - 1946.4935064935066, - 3409.87012987013, - 1852.987012987013, - 3291.4285714285716, - 1800, - 3120, - 1762.5974025974026, - 3001.5584415584417, - 1821.818181818182, - 2889.3506493506493, - 1831.1688311688313, - 2770.909090909091, - 1828.051948051948, - 2699.220779220779, - 1809.3506493506495, - 2602.597402597403, - 1728.3116883116884, - 2568.3116883116886, - 1622.3376623376623, - 2521.5584415584417, - 1566.2337662337663, - 2406.2337662337663, - 1535.064935064935, - 2284.6753246753246, - 1550.6493506493507, - 2197.4025974025976, - 1588.051948051948, - 2097.662337662338, - 1591.1688311688313, - 2057.1428571428573, - 1466.4935064935066, - 2175.5844155844156, - 1441.5584415584417, - 2281.5584415584417, - 1435.3246753246754, - 2284.6753246753246, - 1363.6363636363637, - 2231.688311688312, - 1251.4285714285716, - 2191.1688311688313, - 1058.1818181818182, - 2125.714285714286, - 902.3376623376624, - 2078.961038961039, - 780.7792207792209, - 2091.4285714285716, - 718.4415584415585, - 2125.714285714286, - 696.6233766233767, - 2144.4155844155844, - 718.4415584415585 - ] - ], - "bbox": [ - 2057.1428571428573, - 696.6233766233767, - 1620.7792207792209, - 1293.5064935064934 - ], - "area": 1102920.0202394996 - } -] \ No newline at end of file diff --git a/tests/data/gt_cat_dog.json b/tests/data/gt_cat_dog.json deleted file mode 100644 index 5b33801..0000000 --- a/tests/data/gt_cat_dog.json +++ /dev/null @@ -1,1285 +0,0 @@ -{ - "info": { - "description": "my-project-name" - }, - "images": [ - { - "id": 1, - "width": 6022, - "height": 4072, - "file_name": "cat_dog1.jpg" - }, - { - "id": 2, - "width": 2560, - "height": 1600, - "file_name": "cat_dog2.jpg" - }, - { - "id": 3, - "width": 3840, - "height": 2160, - "file_name": "cat_dog3.jpg" - } - ], - "annotations": [ - { - "id": 11, - "iscrowd": 0, - "image_id": 1, - "category_id": 2, - "segmentation": [ - [ - 3232.080808080808, - 760.9292929292928, - 3550.8484848484845, - 647.8181818181818, - 3833.6262626262624, - 601.5454545454545, - 4131.828282828283, - 714.6565656565656, - 4466.020202020201, - 637.5353535353535, - 4856.767676767677, - 935.7373737373737, - 5201.242424242424, - 961.4444444444443, - 5622.838383838383, - 1311.060606060606, - 5535.434343434343, - 1588.6969696969695, - 5432.60606060606, - 1619.5454545454545, - 5309.212121212121, - 1434.4545454545453, - 5268.080808080807, - 1413.8888888888887, - 5201.242424242424, - 1491.010101010101, - 4918.464646464647, - 1485.8686868686868, - 4836.20202020202, - 1974.30303030303, - 5427.464646464647, - 2195.3838383838383, - 6003.30303030303, - 2200.525252525252, - 6003.30303030303, - 3604.1313131313127, - 4388.898989898989, - 3670.9696969696965, - 4368.333333333333, - 3784.080808080808, - 1448.0101010101012, - 3856.0606060606056, - 1329.7575757575758, - 3753.232323232323, - 1370.888888888889, - 3660.6868686868684, - 1283.4848484848485, - 3645.262626262626, - 1365.7474747474748, - 3573.282828282828, - 1633.1010101010102, - 3496.1616161616157, - 1910.7373737373737, - 3455.0303030303025, - 2363.181818181818, - 3439.6060606060605, - 2496.8585858585857, - 3511.585858585858, - 2604.8282828282827, - 3665.8282828282827, - 2733.3636363636365, - 3804.646464646464, - 2980.151515151515, - 3778.9393939393935, - 3016.141414141414, - 3645.262626262626, - 3221.7979797979797, - 3655.545454545454, - 3355.4747474747473, - 3496.1616161616157, - 3386.3232323232323, - 3305.929292929293, - 3746.222222222222, - 3218.525252525252, - 3746.222222222222, - 2925.464646464646, - 3777.070707070707, - 2586.1313131313127, - 3777.070707070707, - 2246.7979797979797, - 3710.2323232323233, - 1886.8989898989898, - 3699.9494949494947, - 1239.080808080808, - 3437.7373737373737, - 1100.262626262626, - 3329.7676767676767, - 1151.6767676767677 - ] - ], - "bbox": [ - 1283.4848484848485, - 601.5454545454545, - 4719.818181818182, - 3254.515151515151 - ], - "area": 6400775.724977043 - }, - { - "id": 1, - "iscrowd": 0, - "image_id": 1, - "category_id": 1, - "segmentation": [ - [ - 100.95959595959614, - 3089.989898989899, - 604.818181818182, - 3028.292929292929, - 903.0202020202022, - 2781.5050505050503, - 1175.5151515151515, - 2580.989898989899, - 1489.1414141414143, - 2462.7373737373737, - 1679.3737373737374, - 2385.616161616161, - 1951.8686868686868, - 2349.6262626262624, - 2352.89898989899, - 2473.020202020202, - 2481.4343434343436, - 2488.4444444444443, - 2486.5757575757575, - 2087.4141414141413, - 2548.2727272727275, - 2025.7171717171716, - 2476.2929292929293, - 1773.7878787878788, - 2584.2626262626263, - 1588.6969696969695, - 2712.7979797979797, - 1650.3939393939393, - 2841.3333333333335, - 1809.7777777777776, - 3149.8181818181815, - 1814.9191919191917, - 3278.3535353535353, - 1475.5858585858584, - 3376.040404040404, - 1475.5858585858584, - 3463.4444444444443, - 1604.121212121212, - 3484.0101010101007, - 1773.7878787878788, - 3473.7272727272725, - 1897.181818181818, - 3520, - 2020.5757575757575, - 3566.272727272727, - 2097.6969696969695, - 3617.6868686868684, - 2262.222222222222, - 3741.080808080808, - 2534.7171717171714, - 3735.939393939394, - 2863.7676767676767, - 3653.6767676767677, - 3197.959595959596, - 3365.7575757575755, - 3295.646464646464, - 3247.5050505050503, - 3609.272727272727, - 3046.989898989899, - 3629.8383838383834, - 2928.7373737373737, - 3748.090909090909, - 2723.080808080808, - 3773.7979797979797, - 2502, - 3501.30303030303, - 2352.89898989899, - 3413.89898989899, - 2013.5656565656566, - 3439.6060606060605, - 1828.4747474747476, - 3444.7474747474744, - 1627.959595959596, - 3480.7373737373737, - 1412.020202020202, - 3511.585858585858, - 1283.4848484848485, - 3583.5656565656564, - 1190.939393939394, - 3527.0101010101007, - 1005.848484848485, - 3568.141414141414, - 651.0909090909092, - 3542.434343434343, - 625.3838383838386, - 3665.8282828282827, - 409.4444444444446, - 3670.9696969696965, - 224.35353535353553, - 3583.5656565656564, - 286.0505050505052, - 3403.616161616161, - 8.414141414141607, - 3439.6060606060605, - 8.414141414141607, - 3095.1313131313127 - ] - ], - "bbox": [ - 8.414141414141607, - 1475.5858585858584, - 3732.666666666666, - 2298.212121212121 - ], - "area": 4223541.052545659 - }, - { - "id": 2, - "iscrowd": 0, - "image_id": 2, - "category_id": 2, - "segmentation": [ - [ - 885.1948051948051, - 1009.8701298701297, - 1117.9220779220777, - 841.5584415584415, - 1423.3766233766232, - 619.2207792207791, - 1510.6493506493505, - 610.9090909090909, - 1494.025974025974, - 548.5714285714286, - 1533.5064935064934, - 396.8831168831168, - 1645.7142857142856, - 309.6103896103896, - 1791.168831168831, - 236.88311688311686, - 1843.116883116883, - 218.18181818181816, - 1922.0779220779218, - 74.8051948051948, - 1996.8831168831166, - 37.4025974025974, - 2015.5844155844154, - 31.168831168831165, - 2077.9220779220777, - 12.467532467532466, - 2144.4155844155844, - 6.233766233766233, - 2185.9740259740256, - 20.77922077922078, - 2215.064935064935, - 41.55844155844156, - 2237.9220779220777, - 56.1038961038961, - 2273.246753246753, - 74.8051948051948, - 2314.805194805195, - 112.2077922077922, - 2325.1948051948048, - 139.2207792207792, - 2323.116883116883, - 297.1428571428571, - 2314.805194805195, - 311.68831168831167, - 2289.87012987013, - 292.987012987013, - 2208.8311688311687, - 251.42857142857142, - 2181.8181818181815, - 230.64935064935062, - 2152.7272727272725, - 220.25974025974023, - 2142.337662337662, - 214.025974025974, - 2113.246753246753, - 197.4025974025974, - 2080, - 187.012987012987, - 2077.9220779220777, - 187.012987012987, - 2052.987012987013, - 195.3246753246753, - 2040.5194805194803, - 205.7142857142857, - 2036.3636363636363, - 226.49350649350646, - 2030.12987012987, - 236.88311688311686, - 2025.9740259740258, - 251.42857142857142, - 2036.3636363636363, - 265.97402597402595, - 2073.7662337662337, - 278.4415584415584, - 2098.7012987012986, - 292.987012987013, - 2146.493506493506, - 319.99999999999994, - 2167.272727272727, - 336.6233766233766, - 2188.051948051948, - 344.93506493506493, - 2204.6753246753246, - 355.3246753246753, - 2215.064935064935, - 363.6363636363636, - 2235.8441558441555, - 376.1038961038961, - 2250.38961038961, - 390.6493506493506, - 2264.935064935065, - 415.5844155844155, - 2279.4805194805194, - 428.051948051948, - 2291.9480519480517, - 446.7532467532467, - 2298.181818181818, - 469.6103896103896, - 2298.181818181818, - 496.6233766233766, - 2298.181818181818, - 511.1688311688311, - 2302.337662337662, - 536.1038961038961, - 2310.6493506493503, - 550.6493506493506, - 2314.805194805195, - 558.9610389610389, - 2321.0389610389607, - 588.051948051948, - 2321.0389610389607, - 621.2987012987012, - 2314.805194805195, - 648.3116883116883, - 2310.6493506493503, - 685.7142857142857, - 2308.5714285714284, - 702.3376623376623, - 2306.493506493506, - 712.7272727272726, - 2306.493506493506, - 718.9610389610389, - 2304.4155844155844, - 741.8181818181818, - 2304.4155844155844, - 777.1428571428571, - 2308.5714285714284, - 812.4675324675324, - 2308.5714285714284, - 843.6363636363635, - 2308.5714285714284, - 856.103896103896, - 2323.116883116883, - 870.6493506493506, - 2331.428571428571, - 883.1168831168831, - 2387.5324675324673, - 968.3116883116883, - 2406.233766233766, - 1032.7272727272725, - 2410.38961038961, - 1088.8311688311687, - 2395.8441558441555, - 1111.6883116883116, - 2383.3766233766232, - 1128.3116883116882, - 2377.142857142857, - 1138.7012987012986, - 2354.285714285714, - 1124.155844155844, - 2341.8181818181815, - 1130.3896103896102, - 2331.428571428571, - 1147.012987012987, - 2312.7272727272725, - 1159.4805194805194, - 2298.181818181818, - 1174.025974025974, - 2279.4805194805194, - 1188.5714285714284, - 2252.4675324675322, - 1196.8831168831168, - 2235.8441558441555, - 1205.194805194805, - 2227.5324675324673, - 1209.3506493506493, - 2208.8311688311687, - 1225.9740259740258, - 2208.8311688311687, - 1232.2077922077922, - 2217.142857142857, - 1273.7662337662337, - 2219.220779220779, - 1294.5454545454545, - 2221.298701298701, - 1309.090909090909, - 2229.6103896103896, - 1327.7922077922076, - 2235.8441558441555, - 1340.25974025974, - 2233.7662337662337, - 1356.8831168831168, - 2217.142857142857, - 1394.2857142857142, - 2202.5974025974024, - 1404.6753246753246, - 2179.7402597402597, - 1410.9090909090908, - 2167.272727272727, - 1412.9870129870128, - 2131.9480519480517, - 1419.2207792207791, - 2098.7012987012986, - 1421.2987012987012, - 2084.155844155844, - 1412.9870129870128, - 2071.6883116883114, - 1408.8311688311687, - 2023.8961038961038, - 1385.9740259740258, - 2023.8961038961038, - 1385.9740259740258, - 2017.6623376623374, - 1371.4285714285713, - 2015.5844155844154, - 1371.4285714285713, - 1992.7272727272725, - 1381.8181818181818, - 1969.8701298701296, - 1390.12987012987, - 1957.4025974025972, - 1392.2077922077922, - 1938.7012987012986, - 1392.2077922077922, - 1919.9999999999998, - 1396.3636363636363, - 1899.2207792207791, - 1400.5194805194803, - 1888.8311688311687, - 1400.5194805194803, - 1874.2857142857142, - 1404.6753246753246, - 1855.5844155844154, - 1421.2987012987012, - 1843.116883116883, - 1435.8441558441557, - 1836.8831168831166, - 1448.3116883116882, - 1828.5714285714284, - 1460.7792207792206, - 1797.4025974025972, - 1479.4805194805194, - 1741.2987012987012, - 1514.8051948051946, - 1716.3636363636363, - 1518.9610389610389, - 1699.7402597402595, - 1523.116883116883, - 1685.194805194805, - 1523.116883116883, - 1676.8831168831168, - 1523.116883116883, - 1645.7142857142856, - 1516.8831168831168, - 1641.5584415584415, - 1516.8831168831168, - 1616.6233766233765, - 1510.6493506493505, - 1593.7662337662337, - 1504.4155844155844, - 1556.3636363636363, - 1481.5584415584415, - 1539.7402597402595, - 1458.7012987012986, - 1531.4285714285713, - 1431.6883116883116, - 1531.4285714285713, - 1415.0649350649348, - 1531.4285714285713, - 1383.8961038961038, - 1531.4285714285713, - 1371.4285714285713, - 1537.6623376623374, - 1356.8831168831168, - 1539.7402597402595, - 1344.4155844155844, - 1545.9740259740258, - 1325.7142857142856, - 1533.5064935064934, - 1321.5584415584415, - 1483.6363636363635, - 1311.168831168831, - 1485.7142857142856, - 1302.8571428571427, - 1473.246753246753, - 1267.5324675324673, - 1452.4675324675322, - 1217.6623376623374, - 1450.3896103896102, - 1198.9610389610389, - 1452.4675324675322, - 1178.181818181818, - 1467.012987012987, - 1161.5584415584415, - 1491.948051948052, - 1147.012987012987, - 1514.8051948051946, - 1124.155844155844, - 1527.272727272727, - 1107.5324675324675, - 1541.8181818181818, - 1065.9740259740258, - 1552.207792207792, - 1047.2727272727273, - 1558.4415584415583, - 1022.3376623376622, - 1556.3636363636363, - 999.4805194805194, - 1525.194805194805, - 999.4805194805194, - 1512.7272727272725, - 999.4805194805194, - 1512.7272727272725, - 949.6103896103896, - 1516.8831168831168, - 918.4415584415583, - 1527.272727272727, - 889.3506493506493, - 1537.6623376623374, - 870.6493506493506, - 1548.0519480519479, - 839.4805194805194, - 1548.0519480519479, - 827.012987012987, - 1531.4285714285713, - 808.3116883116883, - 1516.8831168831168, - 799.9999999999999, - 1487.7922077922076, - 789.6103896103896, - 1446.2337662337661, - 787.5324675324674, - 1408.8311688311687, - 791.6883116883116, - 1365.194805194805, - 802.077922077922, - 1315.3246753246751, - 804.1558441558441, - 1294.5454545454545, - 795.8441558441558, - 1277.9220779220777, - 785.4545454545454, - 1238.4415584415583, - 770.9090909090909, - 1232.2077922077922, - 824.9350649350648, - 1248.8311688311687, - 849.8701298701297, - 1257.142857142857, - 860.2597402597402, - 1238.4415584415583, - 878.9610389610389, - 1217.6623376623374, - 883.1168831168831, - 1188.5714285714284, - 899.7402597402596, - 1159.4805194805194, - 926.7532467532467, - 1126.2337662337661, - 955.8441558441558, - 1107.5324675324675, - 976.6233766233765, - 1080.5194805194803, - 1009.8701298701297, - 1061.8181818181818, - 1038.9610389610389, - 1036.8831168831168, - 1080.5194805194803, - 1018.1818181818181, - 1095.064935064935, - 1016.103896103896, - 1095.064935064935, - 984.9350649350648, - 1101.2987012987012, - 953.7662337662337, - 1101.2987012987012, - 935.064935064935, - 1101.2987012987012, - 901.8181818181818, - 1101.2987012987012, - 881.0389610389609, - 1078.4415584415583, - 889.3506493506493, - 1057.6623376623374 - ] - ], - "bbox": [ - 881.0389610389609, - 6.233766233766233, - 1529.350649350649, - 1516.8831168831166 - ], - "area": 1078218.114353179 - }, - { - "id": 3, - "iscrowd": 0, - "image_id": 2, - "category_id": 1, - "segmentation": [ - [ - 450.9090909090909, - 835.3246753246752, - 500.77922077922074, - 818.7012987012986, - 542.3376623376623, - 812.4675324675324, - 581.8181818181818, - 820.7792207792207, - 621.2987012987012, - 827.012987012987, - 675.3246753246752, - 824.9350649350648, - 710.6493506493506, - 827.012987012987, - 741.8181818181818, - 822.8571428571428, - 760.5194805194805, - 791.6883116883116, - 766.7532467532467, - 756.3636363636363, - 768.8311688311687, - 733.5064935064935, - 808.3116883116883, - 716.8831168831168, - 845.7142857142857, - 708.5714285714286, - 899.7402597402596, - 694.0259740259739, - 937.1428571428571, - 671.1688311688312, - 966.2337662337661, - 656.6233766233765, - 1009.8701298701297, - 642.077922077922, - 1051.4285714285713, - 629.6103896103896, - 1111.6883116883116, - 623.3766233766233, - 1171.948051948052, - 617.1428571428571, - 1217.6623376623374, - 615.064935064935, - 1302.8571428571427, - 619.2207792207791, - 1346.4935064935064, - 619.2207792207791, - 1394.2857142857142, - 619.2207792207791, - 1541.8181818181818, - 839.4805194805194, - 1525.194805194805, - 901.8181818181818, - 1496.103896103896, - 939.2207792207791, - 1500.25974025974, - 962.077922077922, - 1516.8831168831168, - 989.090909090909, - 1521.038961038961, - 1022.3376623376622, - 1533.5064935064934, - 1024.4155844155844, - 1535.5844155844154, - 1038.9610389610389, - 1516.8831168831168, - 1074.2857142857142, - 1496.103896103896, - 1103.3766233766232, - 1471.168831168831, - 1140.7792207792206, - 1442.077922077922, - 1167.7922077922076, - 1423.3766233766232, - 1192.7272727272725, - 1419.2207792207791, - 1221.8181818181818, - 1437.9220779220777, - 1246.7532467532467, - 1458.7012987012986, - 1269.6103896103896, - 1458.7012987012986, - 1298.7012987012986, - 1400.5194805194803, - 1309.090909090909, - 1317.4025974025972, - 1340.25974025974, - 1246.7532467532467, - 1367.2727272727273, - 1207.2727272727273, - 1404.6753246753246, - 1147.012987012987, - 1450.3896103896102, - 1099.2207792207791, - 1491.948051948052, - 1078.4415584415583, - 1529.3506493506493, - 1047.2727272727273, - 1552.207792207792, - 987.012987012987, - 1518.9610389610389, - 970.3896103896103, - 1473.246753246753, - 962.077922077922, - 1433.7662337662337, - 995.3246753246752, - 1388.0519480519479, - 1014.0259740259739, - 1358.9610389610389, - 1057.6623376623374, - 1340.25974025974, - 1095.064935064935, - 1329.8701298701299, - 1134.5454545454545, - 1315.3246753246751, - 1151.168831168831, - 1296.6233766233765, - 1117.9220779220777, - 1300.7792207792206, - 1078.4415584415583, - 1317.4025974025972, - 1034.8051948051948, - 1327.7922077922076, - 1014.0259740259739, - 1317.4025974025972, - 1003.6363636363635, - 1286.2337662337661, - 1005.7142857142857, - 1255.0649350649348, - 1020.2597402597402, - 1230.12987012987, - 1036.8831168831168, - 1184.4155844155844, - 1041.038961038961, - 1142.8571428571427, - 1030.6493506493505, - 1117.9220779220777, - 982.8571428571428, - 1099.2207792207791, - 941.2987012987012, - 1078.4415584415583, - 891.4285714285713, - 1005.7142857142857, - 872.7272727272726, - 970.3896103896103, - 841.5584415584415, - 953.7662337662337, - 779.2207792207791, - 935.064935064935, - 729.3506493506493, - 926.7532467532467, - 691.9480519480519, - 926.7532467532467, - 623.3766233766233, - 943.3766233766233, - 556.8831168831168, - 957.9220779220778, - 531.9480519480519, - 962.077922077922, - 496.6233766233766, - 959.9999999999999, - 475.8441558441558, - 943.3766233766233, - 486.2337662337662, - 895.5844155844155, - 515.3246753246752, - 885.1948051948051, - 492.4675324675324, - 874.8051948051947, - 469.6103896103896, - 843.6363636363635, - 498.70129870129864, - 833.2467532467532, - 446.7532467532467, - 806.2337662337661 - ] - ], - "bbox": [ - 446.7532467532467, - 615.064935064935, - 1095.064935064935, - 937.142857142857 - ], - "area": 478664.7326699269 - }, - { - "id": 4, - "iscrowd": 0, - "image_id": 3, - "category_id": 1, - "segmentation": [ - [ - 2004.1558441558443, - 709.0909090909091, - 2010.3896103896104, - 571.948051948052, - 2019.74025974026, - 547.0129870129871, - 2032.2077922077924, - 506.4935064935065, - 2032.2077922077924, - 456.62337662337666, - 2025.974025974026, - 403.6363636363637, - 2007.2727272727275, - 375.5844155844156, - 2001.0389610389611, - 369.35064935064935, - 1938.7012987012988, - 378.7012987012987, - 1873.2467532467533, - 431.6883116883117, - 1835.844155844156, - 456.62337662337666, - 1810.909090909091, - 487.7922077922078, - 1770.3896103896104, - 515.8441558441559, - 1748.5714285714287, - 537.6623376623377, - 1714.2857142857144, - 543.8961038961039, - 1639.4805194805197, - 547.0129870129871, - 1561.5584415584417, - 556.3636363636364, - 1489.8701298701299, - 565.7142857142858, - 1427.5324675324675, - 562.5974025974026, - 1309.0909090909092, - 550.1298701298701, - 1262.3376623376623, - 531.4285714285714, - 1228.051948051948, - 522.0779220779222, - 1165.7142857142858, - 494.02597402597405, - 1109.6103896103896, - 450.3896103896104, - 1047.2727272727273, - 425.4545454545455, - 1031.6883116883118, - 419.22077922077926, - 988.0519480519481, - 447.2727272727273, - 972.4675324675325, - 506.4935064935065, - 991.1688311688312, - 578.1818181818182, - 1000.5194805194806, - 656.1038961038961, - 1003.6363636363637, - 730.909090909091, - 1012.987012987013, - 802.5974025974026, - 991.1688311688312, - 858.7012987012987, - 922.5974025974026, - 892.987012987013, - 854.025974025974, - 896.1038961038961, - 797.922077922078, - 961.5584415584416, - 763.6363636363636, - 998.961038961039, - 716.8831168831169, - 1014.5454545454546, - 673.2467532467533, - 1033.2467532467533, - 585.974025974026, - 1020.7792207792209, - 492.46753246753246, - 1033.2467532467533, - 430.12987012987014, - 1045.7142857142858, - 339.7402597402598, - 1067.5324675324675, - 236.88311688311688, - 1098.7012987012988, - 171.42857142857144, - 1145.4545454545455, - 84.15584415584416, - 1251.4285714285716, - 56.103896103896105, - 1295.064935064935, - 49.87012987012987, - 1397.922077922078, - 34.285714285714285, - 1472.7272727272727, - 77.92207792207793, - 1588.051948051948, - 137.14285714285714, - 1637.922077922078, - 155.84415584415586, - 1672.2077922077922, - 227.53246753246754, - 1681.5584415584417, - 302.3376623376624, - 1709.6103896103898, - 402.0779220779221, - 1694.0259740259742, - 492.46753246753246, - 1669.0909090909092, - 570.3896103896104, - 1681.5584415584417, - 685.7142857142858, - 1722.0779220779223, - 751.1688311688312, - 1728.3116883116884, - 891.4285714285714, - 1812.4675324675325, - 931.948051948052, - 1843.6363636363637, - 963.1168831168832, - 1862.3376623376623, - 1118.961038961039, - 1896.6233766233768, - 1153.2467532467533, - 1927.7922077922078, - 1262.3376623376623, - 1974.5454545454547, - 1290.3896103896104, - 1990.1298701298701, - 1312.2077922077922, - 2002.5974025974026, - 1362.077922077922, - 2018.1818181818182, - 1421.2987012987014, - 2043.1168831168832, - 1464.935064935065, - 2055.5844155844156, - 1580.2597402597403, - 2036.883116883117, - 1630.1298701298701, - 2036.883116883117, - 1664.4155844155846, - 2024.4155844155846, - 1704.935064935065, - 1996.3636363636365, - 1704.935064935065, - 1968.3116883116884, - 1704.935064935065, - 1962.0779220779223, - 1879.4805194805197, - 2002.5974025974026, - 1885.7142857142858, - 1980.7792207792209, - 1941.818181818182, - 1980.7792207792209, - 1957.4025974025974, - 1987.0129870129872, - 1982.3376623376623, - 2030.6493506493507, - 2060.2597402597403, - 2064.935064935065, - 2110.12987012987, - 2089.87012987013, - 2203.636363636364, - 2083.6363636363635, - 2275.3246753246754, - 2080.5194805194806, - 2353.2467532467535, - 2086.753246753247, - 2396.883116883117, - 2074.285714285714, - 2421.818181818182, - 2046.2337662337663, - 2449.87012987013, - 2008.831168831169, - 2409.3506493506493, - 1927.7922077922078, - 2359.4805194805194, - 1881.0389610389611, - 2294.025974025974, - 1815.5844155844156, - 2228.571428571429, - 1750.1298701298701, - 2156.883116883117, - 1694.0259740259742, - 2038.4415584415585, - 1641.0389610389611, - 1966.753246753247, - 1575.5844155844156, - 2069.6103896103896, - 1519.4805194805197, - 2144.4155844155844, - 1460.2597402597403, - 2194.285714285714, - 1435.3246753246754, - 2244.155844155844, - 1416.6233766233768, - 2209.87012987013, - 1366.753246753247, - 2153.7662337662337, - 1251.4285714285716, - 2138.1818181818185, - 1173.5064935064936, - 2172.4675324675327, - 1092.4675324675325, - 2131.948051948052, - 998.961038961039, - 2091.4285714285716, - 899.2207792207793, - 2066.4935064935066, - 799.4805194805195 - ] - ], - "bbox": [ - 34.285714285714285, - 369.35064935064935, - 2415.5844155844156, - 1720.5194805194806 - ], - "area": 2380009.84989037 - }, - { - "id": 5, - "iscrowd": 0, - "image_id": 3, - "category_id": 2, - "segmentation": [ - [ - 2110.12987012987, - 705.9740259740261, - 2135.064935064935, - 709.0909090909091, - 2259.7402597402597, - 808.8311688311688, - 2272.2077922077924, - 818.1818181818182, - 2312.727272727273, - 864.9350649350649, - 2334.5454545454545, - 836.8831168831169, - 2440.5194805194806, - 811.948051948052, - 2512.2077922077924, - 787.0129870129871, - 2534.025974025974, - 777.6623376623377, - 2605.714285714286, - 746.4935064935065, - 2652.4675324675327, - 721.5584415584416, - 2749.090909090909, - 693.5064935064935, - 2842.597402597403, - 677.922077922078, - 2939.220779220779, - 677.922077922078, - 3010.909090909091, - 693.5064935064935, - 3088.831168831169, - 721.5584415584416, - 3116.883116883117, - 727.7922077922078, - 3132.4675324675327, - 808.8311688311688, - 3107.5324675324678, - 864.9350649350649, - 3098.1818181818185, - 886.7532467532468, - 3135.5844155844156, - 914.8051948051949, - 3194.805194805195, - 952.2077922077923, - 3225.974025974026, - 1048.831168831169, - 3263.3766233766237, - 1111.1688311688313, - 3272.727272727273, - 1123.6363636363637, - 3297.662337662338, - 1245.1948051948052, - 3297.662337662338, - 1285.7142857142858, - 3300.779220779221, - 1351.1688311688313, - 3313.2467532467535, - 1419.7402597402597, - 3325.714285714286, - 1475.844155844156, - 3347.5324675324678, - 1491.4285714285716, - 3378.701298701299, - 1513.2467532467533, - 3437.922077922078, - 1541.2987012987014, - 3472.2077922077924, - 1553.7662337662339, - 3537.662337662338, - 1581.818181818182, - 3565.714285714286, - 1619.2207792207794, - 3596.883116883117, - 1700.2597402597403, - 3593.766233766234, - 1750.1298701298701, - 3631.1688311688313, - 1837.4025974025974, - 3643.636363636364, - 1849.8701298701299, - 3690.3896103896104, - 1877.922077922078, - 3709.0909090909095, - 1896.6233766233768, - 3718.4415584415588, - 1915.3246753246754, - 3740.2597402597403, - 1971.4285714285716, - 3740.2597402597403, - 2021.2987012987014, - 3693.506493506494, - 2052.4675324675327, - 3640.5194805194806, - 2080.5194805194806, - 3606.2337662337663, - 2064.935064935065, - 3571.948051948052, - 2068.0519480519483, - 3525.194805194805, - 2064.935064935065, - 3490.909090909091, - 2027.5324675324675, - 3450.3896103896104, - 2008.831168831169, - 3422.3376623376626, - 1952.7272727272727, - 3381.818181818182, - 1865.4545454545455, - 3372.4675324675327, - 1852.987012987013, - 3325.714285714286, - 1852.987012987013, - 3294.5454545454545, - 1815.5844155844156, - 3194.805194805195, - 1800, - 3063.8961038961043, - 1818.7012987012988, - 2908.0519480519483, - 1843.6363636363637, - 2842.597402597403, - 1843.6363636363637, - 2758.4415584415588, - 1849.8701298701299, - 2705.4545454545455, - 1849.8701298701299, - 2677.4025974025976, - 1812.4675324675325, - 2661.818181818182, - 1781.2987012987014, - 2640, - 1709.6103896103898, - 2621.2987012987014, - 1672.2077922077922, - 2596.3636363636365, - 1622.3376623376623, - 2571.4285714285716, - 1563.1168831168832, - 2537.1428571428573, - 1547.5324675324675, - 2474.805194805195, - 1525.7142857142858, - 2421.818181818182, - 1510.1298701298701, - 2359.4805194805194, - 1522.5974025974026, - 2250.3896103896104, - 1544.4155844155846, - 2200.5194805194806, - 1563.1168831168832, - 2200.5194805194806, - 1616.1038961038962, - 2178.7012987012986, - 1625.4545454545455, - 2135.064935064935, - 1631.6883116883118, - 2103.896103896104, - 1637.922077922078, - 2063.3766233766237, - 1606.753246753247, - 2054.025974025974, - 1566.2337662337663, - 2107.012987012987, - 1528.831168831169, - 2138.1818181818185, - 1500.7792207792209, - 2178.7012987012986, - 1469.6103896103896, - 2212.9870129870133, - 1450.909090909091, - 2250.3896103896104, - 1432.2077922077922, - 2265.974025974026, - 1407.2727272727273, - 2231.688311688312, - 1379.2207792207794, - 2209.87012987013, - 1329.3506493506495, - 2184.935064935065, - 1267.012987012987, - 2175.5844155844156, - 1195.3246753246754, - 2175.5844155844156, - 1142.3376623376623, - 2178.7012987012986, - 1086.2337662337663, - 2178.7012987012986, - 1055.064935064935, - 2135.064935064935, - 970.909090909091, - 2103.896103896104, - 899.2207792207793, - 2085.194805194805, - 846.2337662337662, - 2066.4935064935066, - 749.6103896103897, - 2063.3766233766237, - 730.909090909091, - 2125.714285714286, - 690.3896103896104 - ] - ], - "bbox": [ - 2054.025974025974, - 677.922077922078, - 1686.2337662337663, - 1402.5974025974026 - ], - "area": 1217755.7092258406 - } - ], - "categories": [ - { - "id": 1, - "name": "cat" - }, - { - "id": 2, - "name": "dog" - } - ] -} \ No newline at end of file diff --git a/tests/dataset/dt_dataset.json b/tests/dataset/dt_dataset.json new file mode 100644 index 0000000..752280b --- /dev/null +++ b/tests/dataset/dt_dataset.json @@ -0,0 +1,862 @@ +[ + { + "id": 21, + "iscrowd": 0, + "image_id": 1, + "category_id": 2, + "segmentation": [ + [ + 32, + 56, + 26, + 60, + 22, + 70, + 25, + 78, + 29, + 81, + 26, + 84, + 26, + 94, + 29, + 99, + 34, + 102, + 37, + 104, + 39, + 106, + 39, + 110, + 36, + 116, + 37, + 120, + 31, + 126, + 30, + 129, + 31, + 133, + 34, + 134, + 37, + 134, + 41, + 131, + 44, + 130, + 46, + 127, + 53, + 124, + 56, + 120, + 56, + 115, + 65, + 111, + 70, + 118, + 76, + 118, + 82, + 118, + 88, + 116, + 93, + 112, + 95, + 108, + 102, + 107, + 107, + 107, + 111, + 102, + 116, + 96, + 117, + 92, + 125, + 84, + 129, + 77, + 130, + 71, + 129, + 65, + 127, + 60, + 128, + 52, + 127, + 42, + 122, + 40, + 119, + 36, + 114, + 28, + 108, + 24, + 102, + 24, + 98, + 26, + 97, + 29, + 91, + 24, + 85, + 24, + 82, + 26, + 77, + 30, + 75, + 28, + 70, + 26, + 66, + 28, + 60, + 34, + 57, + 36, + 53, + 33, + 47, + 32, + 41, + 36, + 37, + 40, + 35, + 43 + ] + ], + "bbox": [ + 22, + 24, + 109, + 111 + ], + "area": 8036, + "score": 0.6333333333333333 + }, + { + "id": 22, + "iscrowd": 0, + "image_id": 1, + "category_id": 1, + "segmentation": [ + [ + 151, + 35, + 145, + 52, + 146, + 64, + 151, + 82, + 159, + 99, + 173, + 113, + 188, + 124, + 198, + 131, + 212, + 122, + 224, + 113, + 235, + 101, + 245, + 84, + 250, + 67, + 252, + 51, + 247, + 37, + 237, + 26, + 223, + 25, + 216, + 28, + 207, + 32, + 203, + 40, + 199, + 46, + 193, + 35, + 185, + 29, + 178, + 26, + 170, + 24, + 161, + 26, + 155, + 30 + ] + ], + "bbox": [ + 145, + 24, + 108, + 108 + ], + "area": 8123, + "score": 0.6666666666666666 + }, + { + "id": 23, + "iscrowd": 0, + "image_id": 1, + "category_id": 3, + "segmentation": [ + [ + 4, + 200, + 56, + 157, + 59, + 156, + 60, + 176, + 110, + 177, + 109, + 224, + 60, + 224, + 60, + 245, + 58, + 246, + 4, + 201 + ] + ], + "bbox": [ + 4, + 156, + 107, + 91 + ], + "area": 4994, + "score": 0.7 + }, + { + "id": 24, + "iscrowd": 0, + "image_id": 2, + "category_id": 1, + "segmentation": [ + [ + 32, + 56, + 26, + 60, + 22, + 70, + 25, + 78, + 29, + 81, + 26, + 84, + 26, + 94, + 29, + 99, + 34, + 102, + 37, + 104, + 39, + 106, + 39, + 110, + 36, + 116, + 37, + 120, + 31, + 126, + 30, + 129, + 31, + 133, + 34, + 134, + 37, + 134, + 41, + 131, + 44, + 130, + 46, + 127, + 53, + 124, + 56, + 120, + 56, + 115, + 65, + 111, + 70, + 118, + 76, + 118, + 82, + 118, + 88, + 116, + 93, + 112, + 95, + 108, + 102, + 107, + 107, + 107, + 111, + 102, + 116, + 96, + 117, + 92, + 125, + 84, + 129, + 77, + 130, + 71, + 129, + 65, + 127, + 60, + 128, + 52, + 127, + 42, + 122, + 40, + 119, + 36, + 114, + 28, + 108, + 24, + 102, + 24, + 98, + 26, + 97, + 29, + 91, + 24, + 85, + 24, + 82, + 26, + 77, + 30, + 75, + 28, + 70, + 26, + 66, + 28, + 60, + 34, + 57, + 36, + 53, + 33, + 47, + 32, + 41, + 36, + 37, + 40, + 35, + 43 + ] + ], + "bbox": [ + 22, + 24, + 109, + 111 + ], + "area": 8036, + "score": 0.7333333333333333 + }, + { + "id": 25, + "iscrowd": 0, + "image_id": 2, + "category_id": 4, + "segmentation": [ + [ + 83, + 173, + 116, + 174, + 100, + 202, + 116, + 225, + 84, + 228, + 65, + 253, + 44, + 227, + 12, + 228, + 27, + 201, + 10, + 174, + 44, + 174, + 64, + 147 + ] + ], + "bbox": [ + 10, + 147, + 107, + 107 + ], + "area": 5808, + "score": 0.7666666666666666 + }, + { + "id": 26, + "iscrowd": 0, + "image_id": 2, + "category_id": 2, + "segmentation": [ + [ + 132, + 154, + 133, + 176, + 144, + 200, + 154, + 213, + 166, + 226, + 178, + 231, + 185, + 237, + 203, + 228, + 223, + 205, + 232, + 188, + 236, + 172, + 238, + 158, + 232, + 142, + 224, + 133, + 211, + 131, + 205, + 132, + 194, + 139, + 188, + 148, + 185, + 151, + 180, + 143, + 174, + 136, + 167, + 133, + 154, + 130, + 141, + 138, + 137, + 143 + ] + ], + "bbox": [ + 132, + 130, + 107, + 108 + ], + "area": 8071, + "score": 0.7999999999999999 + }, + { + "id": 27, + "iscrowd": 0, + "image_id": 3, + "category_id": 1, + "segmentation": [ + [ + 154, + 34, + 148, + 38, + 144, + 48, + 147, + 56, + 151, + 59, + 148, + 62, + 148, + 72, + 151, + 77, + 156, + 80, + 159, + 82, + 161, + 84, + 161, + 88, + 158, + 94, + 159, + 98, + 153, + 104, + 152, + 107, + 153, + 111, + 156, + 112, + 159, + 112, + 163, + 109, + 166, + 108, + 168, + 105, + 175, + 102, + 178, + 98, + 178, + 93, + 187, + 89, + 192, + 96, + 198, + 96, + 204, + 96, + 210, + 94, + 215, + 90, + 217, + 86, + 224, + 85, + 229, + 85, + 233, + 80, + 238, + 74, + 239, + 70, + 247, + 62, + 251, + 55, + 252, + 49, + 251, + 43, + 249, + 38, + 250, + 30, + 249, + 20, + 244, + 18, + 241, + 14, + 236, + 6, + 230, + 2, + 224, + 2, + 220, + 4, + 219, + 7, + 213, + 2, + 207, + 2, + 204, + 4, + 199, + 8, + 197, + 6, + 192, + 4, + 188, + 6, + 182, + 12, + 179, + 14, + 175, + 11, + 169, + 10, + 163, + 14, + 159, + 18, + 157, + 21 + ] + ], + "bbox": [ + 144, + 2, + 109, + 111 + ], + "area": 8036, + "score": 0.8333333333333333 + }, + { + "id": 28, + "iscrowd": 0, + "image_id": 3, + "category_id": 4, + "segmentation": [ + [ + 112, + 149, + 150, + 148, + 169, + 120, + 176, + 120, + 194, + 149, + 238, + 149, + 218, + 183, + 237, + 211, + 236, + 215, + 196, + 214, + 172, + 246, + 151, + 215, + 108, + 214, + 126, + 180, + 109, + 151 + ] + ], + "bbox": [ + 108, + 120, + 131, + 127 + ], + "area": 8765, + "score": 0.8666666666666667 + }, + { + "id": 29, + "iscrowd": 0, + "image_id": 3, + "category_id": 1, + "segmentation": [ + [ + 14, + 177, + 8, + 181, + 4, + 191, + 7, + 199, + 11, + 202, + 8, + 205, + 8, + 215, + 11, + 220, + 16, + 223, + 19, + 225, + 21, + 227, + 21, + 231, + 18, + 237, + 19, + 241, + 13, + 247, + 12, + 250, + 13, + 254, + 16, + 255, + 19, + 255, + 23, + 252, + 26, + 251, + 28, + 248, + 35, + 245, + 38, + 241, + 38, + 236, + 47, + 232, + 52, + 239, + 58, + 239, + 64, + 239, + 70, + 237, + 75, + 233, + 77, + 229, + 84, + 228, + 89, + 228, + 93, + 223, + 98, + 217, + 99, + 213, + 107, + 205, + 111, + 198, + 112, + 192, + 111, + 186, + 109, + 181, + 110, + 173, + 109, + 163, + 104, + 161, + 101, + 157, + 96, + 149, + 90, + 145, + 84, + 145, + 80, + 147, + 79, + 150, + 73, + 145, + 67, + 145, + 64, + 147, + 59, + 151, + 57, + 149, + 52, + 147, + 48, + 149, + 42, + 155, + 39, + 157, + 35, + 154, + 29, + 153, + 23, + 157, + 19, + 161, + 17, + 164 + ] + ], + "bbox": [ + 4, + 145, + 109, + 111 + ], + "area": 8036, + "score": 0.8999999999999999 + } +] \ No newline at end of file diff --git a/tests/dataset/gt_dataset.json b/tests/dataset/gt_dataset.json new file mode 100644 index 0000000..d4c5d97 --- /dev/null +++ b/tests/dataset/gt_dataset.json @@ -0,0 +1,832 @@ +{ + "info": { + "description": "faster-coco-eval test data" + }, + "images": [ + { + "id": 1, + "width": 256, + "height": 256, + "file_name": "img_3.jpg" + }, + { + "id": 2, + "width": 256, + "height": 256, + "file_name": "img_1.jpg" + }, + { + "id": 3, + "width": 256, + "height": 256, + "file_name": "img_2.jpg" + } + ], + "annotations": [ + { + "id": 1, + "iscrowd": 0, + "image_id": 1, + "category_id": 1, + "segmentation": [ + [ + 32, + 56, + 26, + 60, + 22, + 70, + 25, + 78, + 29, + 81, + 26, + 84, + 26, + 94, + 29, + 99, + 34, + 102, + 37, + 104, + 39, + 106, + 39, + 110, + 36, + 116, + 37, + 120, + 31, + 126, + 30, + 129, + 31, + 133, + 34, + 134, + 37, + 134, + 41, + 131, + 44, + 130, + 46, + 127, + 53, + 124, + 56, + 120, + 56, + 115, + 65, + 111, + 70, + 118, + 76, + 118, + 82, + 118, + 88, + 116, + 93, + 112, + 95, + 108, + 102, + 107, + 107, + 107, + 111, + 102, + 116, + 96, + 117, + 92, + 125, + 84, + 129, + 77, + 130, + 71, + 129, + 65, + 127, + 60, + 128, + 52, + 127, + 42, + 122, + 40, + 119, + 36, + 114, + 28, + 108, + 24, + 102, + 24, + 98, + 26, + 97, + 29, + 91, + 24, + 85, + 24, + 82, + 26, + 77, + 30, + 75, + 28, + 70, + 26, + 66, + 28, + 60, + 34, + 57, + 36, + 53, + 33, + 47, + 32, + 41, + 36, + 37, + 40, + 35, + 43 + ] + ], + "bbox": [ + 22, + 24, + 109, + 111 + ], + "area": 8036 + }, + { + "id": 2, + "iscrowd": 0, + "image_id": 1, + "category_id": 2, + "segmentation": [ + [ + 151, + 35, + 145, + 52, + 146, + 64, + 151, + 82, + 159, + 99, + 173, + 113, + 188, + 124, + 198, + 131, + 212, + 122, + 224, + 113, + 235, + 101, + 245, + 84, + 250, + 67, + 252, + 51, + 247, + 37, + 237, + 26, + 223, + 25, + 216, + 28, + 207, + 32, + 203, + 40, + 199, + 46, + 193, + 35, + 185, + 29, + 178, + 26, + 170, + 24, + 161, + 26, + 155, + 30 + ] + ], + "bbox": [ + 145, + 24, + 108, + 108 + ], + "area": 8123 + }, + { + "id": 3, + "iscrowd": 0, + "image_id": 1, + "category_id": 3, + "segmentation": [ + [ + 4, + 200, + 56, + 157, + 59, + 156, + 60, + 176, + 110, + 177, + 109, + 224, + 60, + 224, + 60, + 245, + 58, + 246, + 4, + 201 + ] + ], + "bbox": [ + 4, + 156, + 107, + 91 + ], + "area": 4994 + }, + { + "id": 4, + "iscrowd": 0, + "image_id": 2, + "category_id": 1, + "segmentation": [ + [ + 32, + 56, + 26, + 60, + 22, + 70, + 25, + 78, + 29, + 81, + 26, + 84, + 26, + 94, + 29, + 99, + 34, + 102, + 37, + 104, + 39, + 106, + 39, + 110, + 36, + 116, + 37, + 120, + 31, + 126, + 30, + 129, + 31, + 133, + 34, + 134, + 37, + 134, + 41, + 131, + 44, + 130, + 46, + 127, + 53, + 124, + 56, + 120, + 56, + 115, + 65, + 111, + 70, + 118, + 76, + 118, + 82, + 118, + 88, + 116, + 93, + 112, + 95, + 108, + 102, + 107, + 107, + 107, + 111, + 102, + 116, + 96, + 117, + 92, + 125, + 84, + 129, + 77, + 130, + 71, + 129, + 65, + 127, + 60, + 128, + 52, + 127, + 42, + 122, + 40, + 119, + 36, + 114, + 28, + 108, + 24, + 102, + 24, + 98, + 26, + 97, + 29, + 91, + 24, + 85, + 24, + 82, + 26, + 77, + 30, + 75, + 28, + 70, + 26, + 66, + 28, + 60, + 34, + 57, + 36, + 53, + 33, + 47, + 32, + 41, + 36, + 37, + 40, + 35, + 43 + ] + ], + "bbox": [ + 22, + 24, + 109, + 111 + ], + "area": 8036 + }, + { + "id": 5, + "iscrowd": 0, + "image_id": 2, + "category_id": 4, + "segmentation": [ + [ + 83, + 173, + 116, + 174, + 100, + 202, + 116, + 225, + 84, + 228, + 65, + 253, + 44, + 227, + 12, + 228, + 27, + 201, + 10, + 174, + 44, + 174, + 64, + 147 + ] + ], + "bbox": [ + 10, + 147, + 107, + 107 + ], + "area": 5808 + }, + { + "id": 6, + "iscrowd": 0, + "image_id": 2, + "category_id": 2, + "segmentation": [ + [ + 132, + 154, + 133, + 176, + 144, + 200, + 154, + 213, + 166, + 226, + 178, + 231, + 185, + 237, + 203, + 228, + 223, + 205, + 232, + 188, + 236, + 172, + 238, + 158, + 232, + 142, + 224, + 133, + 211, + 131, + 205, + 132, + 194, + 139, + 188, + 148, + 185, + 151, + 180, + 143, + 174, + 136, + 167, + 133, + 154, + 130, + 141, + 138, + 137, + 143 + ] + ], + "bbox": [ + 132, + 130, + 107, + 108 + ], + "area": 8071 + }, + { + "id": 7, + "iscrowd": 0, + "image_id": 3, + "category_id": 1, + "segmentation": [ + [ + 154, + 34, + 148, + 38, + 144, + 48, + 147, + 56, + 151, + 59, + 148, + 62, + 148, + 72, + 151, + 77, + 156, + 80, + 159, + 82, + 161, + 84, + 161, + 88, + 158, + 94, + 159, + 98, + 153, + 104, + 152, + 107, + 153, + 111, + 156, + 112, + 159, + 112, + 163, + 109, + 166, + 108, + 168, + 105, + 175, + 102, + 178, + 98, + 178, + 93, + 187, + 89, + 192, + 96, + 198, + 96, + 204, + 96, + 210, + 94, + 215, + 90, + 217, + 86, + 224, + 85, + 229, + 85, + 233, + 80, + 238, + 74, + 239, + 70, + 247, + 62, + 251, + 55, + 252, + 49, + 251, + 43, + 249, + 38, + 250, + 30, + 249, + 20, + 244, + 18, + 241, + 14, + 236, + 6, + 230, + 2, + 224, + 2, + 220, + 4, + 219, + 7, + 213, + 2, + 207, + 2, + 204, + 4, + 199, + 8, + 197, + 6, + 192, + 4, + 188, + 6, + 182, + 12, + 179, + 14, + 175, + 11, + 169, + 10, + 163, + 14, + 159, + 18, + 157, + 21 + ] + ], + "bbox": [ + 144, + 2, + 109, + 111 + ], + "area": 8036 + }, + { + "id": 8, + "iscrowd": 0, + "image_id": 3, + "category_id": 2, + "segmentation": [ + [ + 73, + 144, + 84, + 140, + 94, + 132, + 103, + 126, + 109, + 117, + 122, + 101, + 130, + 82, + 134, + 66, + 133, + 55, + 134, + 45, + 127, + 35, + 122, + 27, + 109, + 21, + 94, + 25, + 83, + 34, + 78, + 43, + 75, + 47, + 68, + 35, + 62, + 28, + 52, + 22, + 38, + 21, + 28, + 24, + 20, + 36, + 16, + 45, + 14, + 56, + 16, + 71, + 19, + 84, + 21, + 92, + 26, + 101, + 36, + 113, + 45, + 123, + 56, + 133, + 71, + 144 + ] + ], + "bbox": [ + 14, + 21, + 121, + 124 + ], + "area": 10671 + }, + { + "id": 9, + "iscrowd": 0, + "image_id": 3, + "category_id": 4, + "segmentation": [ + [ + 112, + 149, + 150, + 148, + 169, + 120, + 176, + 120, + 194, + 149, + 238, + 149, + 218, + 183, + 237, + 211, + 236, + 215, + 196, + 214, + 172, + 246, + 151, + 215, + 108, + 214, + 126, + 180, + 109, + 151 + ] + ], + "bbox": [ + 108, + 120, + 131, + 127 + ], + "area": 8765 + } + ], + "categories": [ + { + "id": 1, + "name": "cloud" + }, + { + "id": 2, + "name": "heart" + }, + { + "id": 3, + "name": "arrow" + }, + { + "id": 4, + "name": "star" + } + ] +} \ No newline at end of file diff --git a/tests/dataset/img_1.jpg b/tests/dataset/img_1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3ca44482d3b2bbfa2357961b6ff26baf84845777 GIT binary patch literal 11645 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 MbI^ZtOoX5QFIy#^V*mgE literal 0 HcmV?d00001 diff --git a/tests/dataset/img_2.jpg b/tests/dataset/img_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3f455b72f443a73bc7d3aa23ea9da72c55cbd73b GIT binary patch literal 11720 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 OaeqAgr(x2Pr~VJoz%4QW literal 0 HcmV?d00001 diff --git a/tests/dataset/img_3.jpg b/tests/dataset/img_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..261cc778a785ae82add386788283f8f51cdf35c0 GIT binary patch literal 11115 zcmbVy2Ut_vw(dfDQ9zo25|rKrDJn<=HzlwEsiF5GB^2o`QKU$hu2dC}4pIWrMVfT! z5_**m0mMK;^5VH??{n^b@80jdH&@2D`pW$0SaY<05xx_a00s?Jh$=urLIPM57l5z~ z+)@c}b_4(|EkGCm04n0Ss{ko+i-frRqY-9-N5CZ#lHb37Hd1oZ-;IKdjFg;`f|ByL zP*KxTQ&G`SQBu-erlFywBQ{FvEA*G?uKeEq{gB_c|Gta(qobmv`hCU!TO)i17^!~u zif^hOVP@7O*Kqo!eHyT;DJ$1fl#BrGi> zD|h$a{YQVOsH&+$H1rJ&jiAORrgruYj!sXUUA%pK{rm$0gI=xKT${-$;fX?Qe0KirL^&4x+V3T zidi}7U3CXF&mFx(7Tc$zG_1VR%Y5kH(Efq!{|;E#{}-~qf&B{?3ZNq;Au5lQ5dZ@h zxc4!Fz~2%#`jDJi_qSw!BT-?`mj-lInExfJPu^aN5&WmzQ305BRiFIp=KpvQN!$zp zcp&6&n`vV93AaPJqSh79v@8(zlb$gk@o|*q=*g#++1NLbFLBQRQoc8@BMcv#L<5)9 zDc)&&CxBzGS>0;KqH+^`3V{QI?p3!+(UvHuXT;|*+ zRQ*z>GOp@}QgO4q@XLL}hlYk!!(+Et=#)jntuNd@QNHBSkjdpRN`bg7w65fg?V}*R z)n~X6ljVCxIplHiD_Q zj}yC4y%BYv*8M(?O9xLQHI2Uu(j2K(e{kdGE8wMY5-hH$bHfjT5B1xlK_tj^{M4ij z{q-kO8O|qrMn7|5yQM7ojlO|Q&MIec`|bhEt^njN@xo6wq6^F6rc&X#{6-tSnE zD{qW5sxaZa?wyRr>5rO*GH7c%rw`cL`{?-W+YNJEMV_VWk^E^6ao9fK{=f{Z!1NY7 zIeOkL5df;8dJ!{C^vYj9E0E z$j>w`$elHLy)CI-ogC6K)VOLy7AaXHdF`yGRJjua&YtKD4%A>wfv&?AN9!_m4lM1u zLvLb&((h~^hOd+DZY0+pL+Vh+esHxtn}SW(K7_p$YPGW+x!74aCGCghFL7iQGt)@w z)GE?Y>b=XE?_@*g;DQ;^_%E2MvOJ5}xW@ANq0tH5zmM5R;v1 z~!lCtVAkhaYH1HiRQwbtp#40&F){?v<|}dHC#f8y|>93)uJ?*&sjjnP`%J9bR{^ z8pf18s})WBg-p&7nbDSO$dFnPJKG9na=So04>9cfl>h6R-_|s8{+{Xn?5Ea(^!+Jk zmzAXLuo&UC>T=V7U`SK@gm}fSo10B=Y*uVEnU`75vs(FD1{Q-$5CMR0x|?^l2CR{q z3YD(s-<*gSe!HH5mO1Ogni3W1fV`}Mu0w=-5df!|-bTl1Us@U0XbXokQuk z{N_`>p06`faCS5_7U^-rb(*8HvDAfQxWu<%xTUQzI5xVz*l=!NQ#venC<4ZadQ*Svb#nJX4KHf;V?gK7jv{unb*3O$mxd5`JVUB&qsoL z<^-S<5q%%jJwm>Pzje6(j-n*rB`L7}7o(3?G8OkT!_=@sb#is?XG)}RNo6odji=$+ z{F%-(AIir~rKeS!^2Ve~zm&6Rz%-;FA9BXEETpHlPJ)TkONfJA04b90t{foIumEqMBbEfUYQENs2{X2VlI^=F)A{{v1l z*Py1KqKx|9`$zBZt)wLw1WoTGE#qor@}uLagnCY0gk<0-(8%#h`HFGi zvOsiJk-WD`U)^41gWZ#1!S}8CKRTs#iC)!7TK6GW2lg_2)aq~$ROc79A`&gT`AgJi z&zgMX{CatFR=EGgtgvP{XWqcft83G{8NW3x(LF-p{0~iEDaqgdt!YW7D0c3!D>OA9 zh5J8CeH4Dk{T#y?bDo8#*1_t{hcIEVPRqgAt=_b-*1!Tji~v^0rA2n)!QGZpZ_0NoVc&bj3R`Tn z1~+G^=tz0(HlP%to8C9zs?$W=1_U5Z5@&u<{qv+DdBGJ#-IEInQ(p;~iQ~)k#5UE; zLGHT)LI&ne2cR6+^W)CAFm^{xEhM(TL|YrRU1xDI>EQk=$Rh7Ydt8W#zWjEW#bePko?@BD9)Js>VTRz3>#R2bsb7wGzE6w~aFc26?kx^j&ma zea4#*Q&D?SyDzZz7}wL*LxT*IqML8*b@6wFI^52C+Hj*0&QV5tgJ zZ=NfU&c{g{?yYwPNkpv^fau*u6eS@3# zQxG*?Y66*Kkpjb>f-M4vK6c7tGe^T7|v=kkL!@9Zy=+O*6Yhlx2XlVFHutpoK5$bhcSCG z*P06V7p^MK^;t?xmQ`W>C-7b8chMGq8qu^pdYLxQshzXXlI)kPd1fa9HfgPUz(G`A zm(JGnxQV`kBRgB;E3M9Ba_Qyso_DNL+YfamFoNl|=+2&?sBoM>vAMG)?O0)Ezlqy^ z(>!dKl$%ZzFVdB z$$Mh2k2hH-bItL^cHOwu_Zjyqcg@8Vq)?2yre+SXrXbJ{ci3wMciBoQ=*3#0fWQBN z?9WjDIqHoV!OGR4-wOCk*w_#Bw=#2jqDssbOw4s$1D%9*$h)rCr7!$(Gc74Kth}6r z?0OhUvFhAZ(X#`e9B?m(DC%eVFBF~Jp<*G7L`1Cnqp#HaSN)HqZJx5iuuD_-(im(&ya~1qqvfNERQ38bI1wfZGuE|y>KWt zHaA-^UU--?JEz2*EVSxCR~c6jX{1NRy%cuYD#>4YHaJWKqv5Yt3!W%fNPWjzUjrs@ zlfx`buQ>JOv0;*X?k(4%DH?)H%zE!fr150>Cp`kx=|}-j^$~CLR-Z+V78Z}g=~Yl{ zi2RfBKG)?7$78LCBI~i5NAf*|G0$jiRMi2ekCl$?&7O)Q+Y=Xwo&6Q?sqsVbfcf~W zsDs1H2C#Hv1#%v*J_^6?p&_Sze_i3EXCAlOh4bk()&0Leb>Z9+q}Zx*#g|Oa{x}mC%Q6tDX2Ce9>c_?@B;a28kw4C~J0 zPuM@d&CZ$d>>704HXk4pi2y>Xdt!5o+#$Tlp_`!e7LQX(j78uf;#B!iF$(b`cD-6I zgHgvFwq73`&9(Gpv+LF98^7yI$py>ab-~;_-H0nrNTCs_F75cn>uZzswJFG!azs&x zfHqPgg<6LZ?yErqot#&(JSc0#R1l{u)1hJ2Gce5KrIGAYa|qq}%Zb;6N;Z5Gy7TH3 zz}ch04zxsgH`^(VXah@SB#^Jr84UwVG z<`PMLXA{s4nG4^Jd)Z!RTpTSHsF+v+z#KY_kT1iXSLhsLyXMjZt(fgR#}b9TQ&&G^ z*M^MNS8fS-7#ukH#0b7`E5F_<1Xjy-ZpHH}ZiX7GAY44%6TCA{I#u#_bMaA(i zLAJd0c-4_wi{X$y#iwuEHdU&ZY7$;tZh>xR1mO~hW7>-0#500s!Fp|2C;xVAqs)8IsUunH2_*~-1DpD&6RuiTdM`Z?;iyXc{RNB|1R|NJAsq$lyq zwu&b1ej5Q8%s@O^KPP&nGWzA)|78?OLR~iz7=fZ)vp}p-h+f#S!T7$}=lh~Fla)qx zK%-|?GD;RmceIT-O%o2!*&O29qsQ>G?dBBVC#*YF`t>01E! z4A9`5x~v!$tc2F@GGCOL_7i~1)0(cqL8d$2=Mo)61496iX$rrjl22(Ycg6hW*gS%^ z`{j(reofmcOEapLwlZ7m7vB)9+8D>Gh=}m?AzhchjJ& zM(jkx@4!yH_--o?|M)z1z&=Y+^S4dl#XtPp7W~6eRUAZuuK4Q2wlmZr z=r%u|p>i91(m!4Hn_(piwrj0PrymlD%b55%4|oZSJ_hQ+h&y~Z61D2vQxe1D$55nYEe%)*zKm?n~w)CJe@K< zwW0|%(4X^V*0qufeLFrf)*^6vc#*J20Nm)qcRqA@QRJ;W;L`UmSkS!Yuvixvsfx0& zeFYmHe#8rlnnAWs97E#7e61xX4+CD>dLFH3Ta4q|SthyMJyMrz6|NuN{d%mQS!-#P zZ}y=cOpfOd;XpfeGYo7gIGZ@Osp)}Ma-|k1!e72`BbYo1TywzTYp^pbQd^|e+xL!i(Y>I2z z9S_A?p8J8raC(P7E)09VNIQ+FzHc#e&D@^W5}&_OQT4P{xN;kq*LQC6?WrxEotc>( z3iS6EeniG_GtklRrlEl#vE26zVCQ{q6{uHW!{uCigz_oUJyNoGrK`dcy!{fH^V%-P zqL;Z~*>x1`An^>ESJ&HXLI1^XKngWK^uqMd%f4L z#QN~K8|oLw1UuvNZWbFTTSXfj20S^|h6z^gHFNpE_XJ!nXo(hYDME6fcupp-tGA)n z*|>xGoGnN62?SNXb3e-Z6M0xMFH@ZlND1E$I@FdR!4I$*HML0UtkAPQ;=DO|(7qmR zZ}{pF!`UtU$d0oDTAmU=Jr%g~n}CMo(YHUs-3!ju(t53A#~?vg-!3xv4k@F(?iOm^ zxHei8YQI)klpO1RQDsduj-L4btMCCU65AJ0WF&|+AWT2BEY<#1H%gGSG;Dywjz^p< zS;H{qqs$3N88Pg9=|=FZFUP3XV4yykYGaF3qB(i<0CuOh^@}ro@*r z2xN=KWq>70N=d+_!^J9(424a5VbYvU~M1h(XQs+!A@US13&XdbLzd%hQ`{ z6l#XnRKgm|FD@zVeC2%dfZSEJZp$FvRI5kV`9qy^g}$ZpYg^BWYG$XXDi%R48Q#fp zEt8_P@mdRA%meh|l3Fy_i9Q;-z=BrEnDM0r=iXyTZ)goqz8YZuyiK;F<1=?yIZIlq z*Cdt?>j(dmDYqB3^fQycVJrkz_ywvt$*yj~Y=4ot3ZzFw^D@w?4w^irEy#P-&Hx9w zTG6yP7i0XpOnrM&h|$nB_Xi545emB)n8?HK+l9Fs#E zzfKWO8S~thGV)tRPfEd@04}1rd|ZeCq~D-F8UgoXTgEuN$WiYp_qAZ(y+ln<K(FwZ>bb7D!ALsaUs_1V4_ce^f_jFfBFmkGx%kUz+J z+qLE|C&H!r;*UPgE#67DHHjvsWZiim5xA=_%n$PtPe#~7{xo*ej+e4@M)9&KL*fVB zH6Zf6M=-tUTcvkAM4S5~o-CeRhaZsMpj@{~!jyEs4jEw7p?#JoEwr%rfOo!P$JL|0 z3Dh3I^7(E{KCKxjOK-gdnvn(x9*xo7TXbE7olIbQPv?m*na+2d4_f6%tO9MQ-SQ%X zCH&~LC*ZY-%N;iJp+=G?_QK}X1~xq8ydrFV7>Vxo>WuD0a@XUnhQ%u_=F>*A{>Tqm zV!M=2BRL(y6+AlFQN5JJtc!A=<4A}m(k;nShaU4TYdzJ7!>EL+Ox$%|eA=wa>;#!~ zfOdL*cEvY3pg&~7Ng(j4>6nM#_$XM@w{@gPCmeLBwHOCt7q`QL!}nXj_6|?%Tc&HR zUwzb?k-UAUrrz)ouUm71lx(%t1bBw?RP}IiH~MhhC-jEOMoD131=KJ}cBHufPJ)!5 zYU52FvIw%H!NH*&#yGoYim9u|(46k;!Eb(e8Mq=joEOvOYWMtR-RJKInx6*ne2L47 z{D8h2JW)E?Sm;_fsluE5b8*n~{d1KN-E+^s@-|x{=R~m@b4CD8cP=8Nt!C*v%0#tb z1(;b#cx6VZR8EaJ1S``+B1Ubi&dnPCx@L_H@&K0r&#Mp@X%-u-z6a;O+rm5N#O5=- zhApbqQB9P%-{%=vf8~SKYkmD98OOY(@p+jhSA(BwOI1DeVQoSf^3{6^;FSxmRh7wP z-t0#rqOrX0icknc&HXjTG+R;;p$6{?9*) zt9#l5=jXyz`bb4TvpVPw00`9z%N!2(3TMF{;k^d?48MhFP{Oh&vRcM2sjmF2%N5>6-JGP#heu{~ zgH*nT7B#^hyF}n*m4_p{SYM|V309f*7@Uo(DAcG@H+cY(q@TpW6m2Yjl`rY3tZIK! zO)|WGwk{|Ldi?8pK-u1^D1`jrj*vqn2^$iV}GwdbVV6UOCt=g0s6)7+b@HQh-JQiu$C0ldGPVYOT;A6S?77s zudscOqH&%n+eC*6^&9V!?_D+S)9)0=Og~+_+DMZ6O6@Jh5dYrWUlpF1=x=2lCpm?z znW35fI%~t`?pM+!=oQ3oS~6)%S&SRGZX|wPq$O&Xr%lpjk#X-NUK3I`cH-@0n`e%7 zW120{&~{Ky>#F)hpJc+2+|N0{8FR6Rl|ppfSG_VyLanEk@MZt^-(@|>{;UP$z*bF{d+R`{FmJ6Z|?SOJaL3bHx^?+hZ^lK z+L>@pP8A62`GC-OY4%OEqfV@TL1FRFc)l>doTgGbQuv@~m#oR4h71wGs4Q27wXw#k z99BjZZ3el?>!i6d=-(kXIOg?e<&Dr)@)sSdvrn;*UpHCaxW0 zfG50MsZ8dHM2a$w1JnT`Gv8@iAIb3WIO^qK7&q@%n!WCt)R;v{}mZdIM13uLTy2vVjmw>jPK$dOJ?A2lYEHEV1yy1ECJ;t#4Fv##E ztRjK!^z%id4*`haFh_yHtHgXk%yaGukbE0aQ|)W{Y}<72o?p82OMPzj8Wf|`ohvrc z61<{0WM|xxNdWZPQigH^bq0UDUGiiGfXBoI0LbC;y=?+x1I!;yT=gp^HzyE7XFfRk z8HERjm2GaTiGv4piuGn1p%o~_;I>$^Oe+?+@D75#1?F3|^ULZ<%co^SCF6=!vb_YE zK2&T<53$Yzv4xz+;;AJG07y}R0QhyD%}w_PRDEn;O8JAfipxH+*=7;n=6VFa>}BYs zV5r=7OIt4`3${J$m7#yC!+hJvvjt>E9~l$J^EFwckMHj6qup(xwxk~L|v5wo^P;$H<jKDl89~f3qt8gQyNF z6}is|@_3fFGY6DuA6mxBzALjbb)NEs9gB-Q8r%K(DqpmVB>5q`LNd7%F?V4TYUV5R zc&8gz#CNT%p=NugV88mEqxC!0r>?6A)FPgS>BfB8ugDfsFL3slOzTvAxG)*uwA*z( z8Dg_x4KSz8H(CUMQPZbelZs+4awxWleaG<-{;yLw~plck<)qel55X02mfaoGn(* z@5%0uYRn`|_ zSHP}T)QDE%-xj1mzj@~RCgyragqLX#7cl+GE$QQLn5h`aTBVB;D@w8xpkdI`&$8V0 zaS{7aH~&EQ+*J|R_AIm0T;oPyYvJ=0JaSJRoQ-$;BwBzNC1)+nDA|#1VBS=0G)?R!7QHt1Yhvw zeIQOugm+$tjSBN)lK(+SO_X?{chK_7sxQz{om%;rSglySYVn%VTB$nsR(2D02Zf|p zs!H64>JRQI=&}5ei3oXce_~#ER4*QPKXWGU4HyaC zEh&Q!;raW|8WuR)Ud4kS&wf?N<2R=heda{us#(n$`g3(q?bgUp;aQ7ur`nc=$nB|Z z*+^r@ILP(lPP+12yK>qTr(XJ%Z~qow{Z3<4*Pc zk$Fz_%@6#7ajV26aK-6>I70eyW`4@4$xz~e8Dcr|`td6dkl+og0HWIo{=K_&N-T7| z30=1Az>*SxJ`_gn0$X*#o7nNp9g)r~J67z-vmZZL zmeOOQrYExbNi|+)uZ2Gm^J?p2Eu@_TT6FO|eiA_wif9@c>nGM>KP4_5{&%s&zaRh5 zB>K`Y(%>iawjlDvI)q3E6JsRso@$0fG#s?Gpw%V6);hX8_hlI(YDwOQ8c0?s{8F>T zO?RoiSMF4f!*KVs!RTmqZnjxPRIem{#rLj*gF@LQD()kys_*&Zxhf$)vDWym^t>Bi zr=?kuV>pAXtI$-bj$+l@lKkJ)eXW|7u0BL5acaOhdly(cnG0V#FzS{}(e!CHTQK23 zCD`_;Tv3CLPwO*-*(Git_UD2HCVSDAS@58v(6U`HhIdYrZzNGpxSqAMcqBOUOs;!@ zX`+R4#cYVvv^KL-zdEHqms)Kws(8)wa~PGiy0sEn*yT`XVz8URS=kb}TMruEXqPzb zkK014&=~4#-TROmFGKxg^t>ttxeN_2n|wbWdkT{&bsm;={;4(ta)`wT_7Z@Q7{viL z+;JlQjD?To0nyq*LdjR#1ul)Wkp!(5t2KX-$-{LQU36=qdL_8nSApe!NT1H3JnoG*$OaSk0kz zO!_6{n9WzuBrY5_`;6gw&UdTeeJw$-P*q+Y-TK&Iepaw_nTpI{UF&4!*l4q}U+@Gb tODe%cAs^MCtfdI8C_gCtsj Date: Tue, 5 Dec 2023 21:35:58 +0300 Subject: [PATCH 02/16] extra_calc functions append --- faster_coco_eval/core/cocoeval.py | 5 ++++- faster_coco_eval/core/faster_eval_api.py | 17 +++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/faster_coco_eval/core/cocoeval.py b/faster_coco_eval/core/cocoeval.py index 7d64b50..230ecfe 100644 --- a/faster_coco_eval/core/cocoeval.py +++ b/faster_coco_eval/core/cocoeval.py @@ -64,7 +64,7 @@ class COCOeval: # Code written by Piotr Dollar and Tsung-Yi Lin, 2015. # Licensed under the Simplified BSD License [see coco/license.txt] def __init__( - self, cocoGt=None, cocoDt=None, iouType="segm", print_function=logger.debug + self, cocoGt=None, cocoDt=None, iouType="segm", print_function=logger.debug, extra_calc=True, ): """ Initialize CocoEval using coco APIs for gt and dt @@ -86,6 +86,9 @@ def __init__( self._paramsEval: dict = {} # parameters for evaluation self.stats: list = [] # result summarization self.ious: dict = {} # ious between all gts and dts + + self.extra_calc = extra_calc + self.matched = False if not cocoGt is None: self.params.imgIds = sorted(cocoGt.getImgIds()) diff --git a/faster_coco_eval/core/faster_eval_api.py b/faster_coco_eval/core/faster_eval_api.py index 1a29ce6..d50c84c 100644 --- a/faster_coco_eval/core/faster_eval_api.py +++ b/faster_coco_eval/core/faster_eval_api.py @@ -162,9 +162,9 @@ def accumulate(self): ) ) assert self.ground_truth_orig_id.shape[1] == len(self.cocoGt.anns) - - self.math_matches() - self.matched = True + if self.extra_calc: + self.math_matches() + self.matched = True except Exception as e: logger.error("math_matches error: ", exc_info=True) self.matched = False @@ -183,11 +183,16 @@ def math_matches(self): continue gt_id = gt_ids[idx] - if gt_id == -1: + if gt_id <= -1: + continue + + _gt_ann = self.cocoGt.anns.get(gt_id) + if _gt_ann is None: continue - _gt_ann = self.cocoGt.anns[gt_id] - _dt_ann = self.cocoDt.anns[dt_id] + _dt_ann = self.cocoDt.anns.get(dt_id) + if _dt_ann is None: + continue if int(_gt_ann["image_id"]) != int(_dt_ann["image_id"]): continue From 98477737a9c762eee17b72aea34476064974c4ab Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Tue, 5 Dec 2023 21:36:19 +0300 Subject: [PATCH 03/16] compare new --- examples/comparison/coco_fast.py | 226 ---------- examples/comparison/comparison.ipynb | 401 +++++++----------- examples/comparison/eval_metric.py | 98 ----- examples/comparison/faster_coco_detection.py | 423 +++++++++++++++++++ examples/comparison/faster_coco_wrapper.py | 191 +++++++++ examples/comparison/mmdet_mmeval.py | 68 +++ examples/comparison/test.py | 282 ------------- 7 files changed, 828 insertions(+), 861 deletions(-) delete mode 100644 examples/comparison/coco_fast.py delete mode 100644 examples/comparison/eval_metric.py create mode 100644 examples/comparison/faster_coco_detection.py create mode 100644 examples/comparison/faster_coco_wrapper.py create mode 100644 examples/comparison/mmdet_mmeval.py delete mode 100644 examples/comparison/test.py diff --git a/examples/comparison/coco_fast.py b/examples/comparison/coco_fast.py deleted file mode 100644 index f1c918e..0000000 --- a/examples/comparison/coco_fast.py +++ /dev/null @@ -1,226 +0,0 @@ -# Copyright (c) OpenMMLab. All rights reserved. -import contextlib -import io -import itertools -import logging -import os.path as osp -import tempfile -import warnings -from collections import OrderedDict - -import mmcv -import numpy as np -from mmcv.utils import print_log -from terminaltables import AsciiTable - -from mmdet.core import eval_recalls -from mmdet.datasets.builder import DATASETS -from mmdet.datasets.coco import CocoDataset -from faster_coco_eval import COCOeval_faster - - -@DATASETS.register_module() -class FasterCocoDataset(CocoDataset): - def evaluate_det_segm(self, - results, - result_files, - coco_gt, - metrics, - logger=None, - classwise=False, - proposal_nums=(100, 300, 1000), - iou_thrs=None, - metric_items=None): - """Instance segmentation and object detection evaluation in COCO - protocol. - Args: - results (list[list | tuple | dict]): Testing results of the - dataset. - result_files (dict[str, str]): a dict contains json file path. - coco_gt (COCO): COCO API object with ground truth annotation. - metric (str | list[str]): Metrics to be evaluated. Options are - 'bbox', 'segm', 'proposal', 'proposal_fast'. - logger (logging.Logger | str | None): Logger used for printing - related information during evaluation. Default: None. - classwise (bool): Whether to evaluating the AP for each class. - proposal_nums (Sequence[int]): Proposal number used for evaluating - recalls, such as recall@100, recall@1000. - Default: (100, 300, 1000). - iou_thrs (Sequence[float], optional): IoU threshold used for - evaluating recalls/mAPs. If set to a list, the average of all - IoUs will also be computed. If not specified, [0.50, 0.55, - 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95] will be used. - Default: None. - metric_items (list[str] | str, optional): Metric items that will - be returned. If not specified, ``['AR@100', 'AR@300', - 'AR@1000', 'AR_s@1000', 'AR_m@1000', 'AR_l@1000' ]`` will be - used when ``metric=='proposal'``, ``['mAP', 'mAP_50', 'mAP_75', - 'mAP_s', 'mAP_m', 'mAP_l']`` will be used when - ``metric=='bbox' or metric=='segm'``. - Returns: - dict[str, float]: COCO style evaluation metric. - """ - if iou_thrs is None: - iou_thrs = np.linspace( - .5, 0.95, int(np.round((0.95 - .5) / .05)) + 1, endpoint=True) - if metric_items is not None: - if not isinstance(metric_items, list): - metric_items = [metric_items] - - eval_results = OrderedDict() - for metric in metrics: - msg = f'Evaluating {metric}...' - if logger is None: - msg = '\n' + msg - print_log(msg, logger=logger) - - if metric == 'proposal_fast': - if isinstance(results[0], tuple): - raise KeyError('proposal_fast is not supported for ' - 'instance segmentation result.') - ar = self.fast_eval_recall( - results, proposal_nums, iou_thrs, logger='silent') - log_msg = [] - for i, num in enumerate(proposal_nums): - eval_results[f'AR@{num}'] = ar[i] - log_msg.append(f'\nAR@{num}\t{ar[i]:.4f}') - log_msg = ''.join(log_msg) - print_log(log_msg, logger=logger) - continue - - iou_type = 'bbox' if metric == 'proposal' else metric - if metric not in result_files: - raise KeyError(f'{metric} is not in results') - try: - predictions = mmcv.load(result_files[metric]) - if iou_type == 'segm': - # Refer to https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocotools/coco.py#L331 # noqa - # When evaluating mask AP, if the results contain bbox, - # cocoapi will use the box area instead of the mask area - # for calculating the instance area. Though the overall AP - # is not affected, this leads to different - # small/medium/large mask AP results. - for x in predictions: - x.pop('bbox') - warnings.simplefilter('once') - warnings.warn( - 'The key "bbox" is deleted for more accurate mask AP ' - 'of small/medium/large instances since v2.12.0. This ' - 'does not change the overall mAP calculation.', - UserWarning) - coco_det = coco_gt.loadRes(predictions) - except IndexError: - print_log( - 'The testing results of the whole dataset is empty.', - logger=logger, - level=logging.ERROR) - break - - cocoEval = COCOeval_faster(coco_gt, coco_det, iou_type) - cocoEval.params.catIds = self.cat_ids - cocoEval.params.imgIds = self.img_ids - cocoEval.params.maxDets = list(proposal_nums) - cocoEval.params.iouThrs = iou_thrs - # mapping of cocoEval.stats - coco_metric_names = { - 'mAP': 0, - 'mAP_50': 1, - 'mAP_75': 2, - 'mAP_s': 3, - 'mAP_m': 4, - 'mAP_l': 5, - 'AR@100': 6, - 'AR@300': 7, - 'AR@1000': 8, - 'AR_s@1000': 9, - 'AR_m@1000': 10, - 'AR_l@1000': 11 - } - if metric_items is not None: - for metric_item in metric_items: - if metric_item not in coco_metric_names: - raise KeyError( - f'metric item {metric_item} is not supported') - - if metric == 'proposal': - cocoEval.params.useCats = 0 - cocoEval.evaluate() - cocoEval.accumulate() - - # Save coco summarize print information to logger - redirect_string = io.StringIO() - with contextlib.redirect_stdout(redirect_string): - cocoEval.summarize() - print_log('\n' + redirect_string.getvalue(), logger=logger) - - if metric_items is None: - metric_items = [ - 'AR@100', 'AR@300', 'AR@1000', 'AR_s@1000', - 'AR_m@1000', 'AR_l@1000' - ] - - for item in metric_items: - val = float( - f'{cocoEval.stats[coco_metric_names[item]]:.3f}') - eval_results[item] = val - else: - cocoEval.evaluate() - cocoEval.accumulate() - - # Save coco summarize print information to logger - redirect_string = io.StringIO() - with contextlib.redirect_stdout(redirect_string): - cocoEval.summarize() - print_log('\n' + redirect_string.getvalue(), logger=logger) - - if classwise: # Compute per-category AP - # Compute per-category AP - # from https://github.com/facebookresearch/detectron2/ - precisions = cocoEval.eval['precision'] - # precision: (iou, recall, cls, area range, max dets) - assert len(self.cat_ids) == precisions.shape[2] - - results_per_category = [] - for idx, catId in enumerate(self.cat_ids): - # area range index 0: all area ranges - # max dets index -1: typically 100 per image - nm = self.coco.loadCats(catId)[0] - precision = precisions[:, :, idx, 0, -1] - precision = precision[precision > -1] - if precision.size: - ap = np.mean(precision) - else: - ap = float('nan') - results_per_category.append( - (f'{nm["name"]}', f'{float(ap):0.3f}')) - - num_columns = min(6, len(results_per_category) * 2) - results_flatten = list( - itertools.chain(*results_per_category)) - headers = ['category', 'AP'] * (num_columns // 2) - results_2d = itertools.zip_longest(*[ - results_flatten[i::num_columns] - for i in range(num_columns) - ]) - table_data = [headers] - table_data += [result for result in results_2d] - table = AsciiTable(table_data) - print_log('\n' + table.table, logger=logger) - - if metric_items is None: - metric_items = [ - 'mAP', 'mAP_50', 'mAP_75', 'mAP_s', 'mAP_m', 'mAP_l' - ] - - for metric_item in metric_items: - key = f'{metric}_{metric_item}' - val = float( - f'{cocoEval.stats[coco_metric_names[metric_item]]:.3f}' - ) - eval_results[key] = val - ap = cocoEval.stats[:6] - eval_results[f'{metric}_mAP_copypaste'] = ( - f'{ap[0]:.3f} {ap[1]:.3f} {ap[2]:.3f} {ap[3]:.3f} ' - f'{ap[4]:.3f} {ap[5]:.3f}') - - return eval_results diff --git a/examples/comparison/comparison.ipynb b/examples/comparison/comparison.ipynb index 2491ab6..0d0445c 100644 --- a/examples/comparison/comparison.ipynb +++ b/examples/comparison/comparison.ipynb @@ -2,375 +2,266 @@ "cells": [ { "cell_type": "markdown", - "id": "e6c1a344-fdad-47b3-bd20-f1f90ffff2c9", "metadata": {}, "source": [ - "https://mmdetection.readthedocs.io/en/latest/tutorials/test_results_submission.html" + "## Install MMDetection" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "880b2f8f-8d5a-4d34-8cdd-6cd95495d635", + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "!pip3 install git+https://github.com/MiXaiLL76/faster_coco_eval" + "" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "9662b48e-ebd2-4cb3-a13c-1298d989937c", + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "!mkdir -pv data/coco/" + "## Download COCO VAL" ] }, { "cell_type": "code", "execution_count": null, - "id": "ac7b6b1f-4059-43f6-a6d5-64363fb5d289", "metadata": {}, "outputs": [], "source": [ - "!wget -P data/coco/ http://images.cocodataset.org/annotations/annotations_trainval2017.zip\n", - "!wget -P data/coco/ http://images.cocodataset.org/zips/val2017.zip" + "!wget -P COCO/DIR/ http://images.cocodataset.org/annotations/annotations_trainval2017.zip\n", + "!wget -P COCO/DIR/ http://images.cocodataset.org/zips/val2017.zip" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "fbcc1e4f-069c-4ad2-9c26-864bf111016a", + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "!unzip data/coco/annotations_trainval2017.zip -d data/coco/\n", - "!unzip data/coco/val2017.zip -d data/coco/" + "## Unzip COCO VAL" ] }, { "cell_type": "code", "execution_count": null, - "id": "2a1403ee-eff8-4e80-9e9a-69ba74d736f3", "metadata": {}, "outputs": [], "source": [ - "!rm -rf data/coco/*.zip" + "!unzip -qq COCO/DIR/annotations_trainval2017.zip -d COCO/DIR/" ] }, { "cell_type": "code", "execution_count": null, - "id": "54ea5c5a-d294-45b2-a858-560050d9ecf8", "metadata": {}, "outputs": [], "source": [ - "yolo3_model_path = \"https://download.openmmlab.com/mmdetection/v2.0/yolo/yolov3_d53_320_273e_coco/yolov3_d53_320_273e_coco-421362b6.pth\"\n", - "!wget -P model {yolo3_model_path}" + "!unzip -qq COCO/DIR/val2017.zip -d COCO/DIR/" ] }, { - "cell_type": "code", - "execution_count": 1, - "id": "e67a6ecb-d868-408e-8e52-661bd25df496", + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "cfg_path='configs/yolo/yolov3_d53_320_273e_coco.py'\n" - ] - } - ], "source": [ - "import os.path as osp\n", - "\n", - "_BASE_CONFIG_DIR = \"configs/\"\n", - "CONFIG_FILE = \"yolo/yolov3_d53_320_273e_coco.py\"\n", - "CHECKPOINT_FILE = \"model/yolov3_d53_320_273e_coco-421362b6.pth\"\n", - "WORK_DIR = \".\"\n", - "use_cpu = False\n", - "\n", - "cfg_path = osp.join(_BASE_CONFIG_DIR, CONFIG_FILE)\n", - "print(f\"{cfg_path=}\")" + "## Install MMEVAL" ] }, { "cell_type": "code", "execution_count": null, - "id": "e37d2b3c-72bb-4586-b379-2f1281978f05", "metadata": {}, "outputs": [], "source": [ - "_dop = \"\"\n", - "if use_cpu:\n", - " _dop += f\" --gpu-id -1 \"\n", - "\n", - "!python3 test.py \\\n", - " {cfg_path} \\\n", - " {CHECKPOINT_FILE} \\\n", - " --format-only {_dop}\\\n", - " --cfg-options data.test.ann_file=data/coco/annotations/instances_val2017.json \\\n", - " data.test.img_prefix=data/coco/val2017 \\\n", - " --out yolo_result.pkl" + "!pip3 install --quiet --upgrade mmeval==0.2.1" ] }, { - "cell_type": "code", - "execution_count": 2, - "id": "4eca90de-fd3d-4dc7-b3f4-ada1300d0b90", + "cell_type": "markdown", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "loading annotations into memory...\n", - "Done (t=0.28s)\n", - "creating index...\n", - "index created!\n", - "Data uploaded for 1.057 sec.\n", - "\n", - "Evaluating bbox...\n", - "Loading and preparing results...\n", - "DONE (t=0.47s)\n", - "creating index...\n", - "index created!\n", - "Running per image evaluation...\n", - "Evaluate annotation type *bbox*\n", - "DONE (t=16.69s).\n", - "Accumulating evaluation results...\n", - "DONE (t=3.02s).\n", - "\n", - " Average Precision (AP) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.279\n", - " Average Precision (AP) @[ IoU=0.50 | area= all | maxDets=1000 ] = 0.491\n", - " Average Precision (AP) @[ IoU=0.75 | area= all | maxDets=1000 ] = 0.283\n", - " Average Precision (AP) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.105\n", - " Average Precision (AP) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.301\n", - " Average Precision (AP) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.438\n", - " Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=100 ] = 0.395\n", - " Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=300 ] = 0.395\n", - " Average Recall (AR) @[ IoU=0.50:0.95 | area= all | maxDets=1000 ] = 0.395\n", - " Average Recall (AR) @[ IoU=0.50:0.95 | area= small | maxDets=1000 ] = 0.185\n", - " Average Recall (AR) @[ IoU=0.50:0.95 | area=medium | maxDets=1000 ] = 0.423\n", - " Average Recall (AR) @[ IoU=0.50:0.95 | area= large | maxDets=1000 ] = 0.574\n", - "\n", - "OrderedDict([('bbox_mAP', 0.279), ('bbox_mAP_50', 0.491), ('bbox_mAP_75', 0.283), ('bbox_mAP_s', 0.105), ('bbox_mAP_m', 0.301), ('bbox_mAP_l', 0.438), ('bbox_mAP_copypaste', '0.279 0.491 0.283 0.105 0.301 0.438')])\n", - "Data validate for 22.854 sec.\n", - "CPU times: user 160 ms, sys: 22.4 ms, total: 183 ms\n", - "Wall time: 26 s\n" - ] - } - ], "source": [ - "%%time\n", - "\n", - "!python3 eval_metric.py {cfg_path} yolo_result.pkl \\\n", - " --eval bbox \\\n", - " --cfg-options data.test.ann_file=data/coco/annotations/instances_val2017.json" + "## Download model" ] }, { "cell_type": "code", - "execution_count": 3, - "id": "8bda9c97-ecce-4ae2-ab1d-c36680fb3a70", + "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "loading annotations into memory...\n", - "Done (t=0.28s)\n", - "creating index...\n", - "index created!\n", - "Data uploaded for 1.065 sec.\n", + "config_file='/home/mixaill76/.local/lib/python3.10/site-packages/mmdet/.mim/configs/rtmdet/rtmdet-ins_tiny_8xb32-300e_coco.py'\n", + "model_file='https://download.openmmlab.com/mmdetection/v3.0/rtmdet/rtmdet-ins_tiny_8xb32-300e_coco/rtmdet-ins_tiny_8xb32-300e_coco_20221130_151727-ec670f7e.pth'\n", + "--2023-12-05 15:22:50-- https://download.openmmlab.com/mmdetection/v3.0/rtmdet/rtmdet-ins_tiny_8xb32-300e_coco/rtmdet-ins_tiny_8xb32-300e_coco_20221130_151727-ec670f7e.pth\n", + "Resolving download.openmmlab.com (download.openmmlab.com)... 47.246.2.173, 47.246.2.213, 47.246.2.179, ...\n", + "Connecting to download.openmmlab.com (download.openmmlab.com)|47.246.2.173|:443... connected.\n", + "HTTP request sent, awaiting response... 200 OK\n", + "Length: 22757492 (22M) [application/octet-stream]\n", + "Saving to: ‘model/rtmdet-ins_tiny_8xb32-300e_coco_20221130_151727-ec670f7e.pth’\n", "\n", - "Evaluating bbox...\n", - "Loading and preparing results...\n", - "DONE (t=0.47s)\n", - "creating index...\n", - "index created!\n", + "rtmdet-ins_tiny_8xb 100%[===================>] 21.70M 39.3MB/s in 0.6s \n", "\n", + "2023-12-05 15:22:51 (39.3 MB/s) - ‘model/rtmdet-ins_tiny_8xb32-300e_coco_20221130_151727-ec670f7e.pth’ saved [22757492/22757492]\n", "\n", - "OrderedDict([('bbox_mAP', 0.279), ('bbox_mAP_50', 0.491), ('bbox_mAP_75', 0.283), ('bbox_mAP_s', 0.105), ('bbox_mAP_m', 0.301), ('bbox_mAP_l', 0.438), ('bbox_mAP_copypaste', '0.279 0.491 0.283 0.105 0.301 0.438')])\n", - "Data validate for 8.714 sec.\n", - "CPU times: user 91.8 ms, sys: 5.82 ms, total: 97.6 ms\n", - "Wall time: 11.8 s\n" + "total 22M\n", + "drwxrwxrwx 2 mixaill76 mixaill76 4.0K Dec 5 15:22 .\n", + "drwxr-xr-x 5 mixaill76 mixaill76 4.0K Dec 5 15:22 ..\n", + "-rw-r--r-- 1 mixaill76 mixaill76 16K Dec 5 15:22 rtmdet-ins_tiny_8xb32-300e_coco.py\n", + "-rw-r--r-- 1 mixaill76 mixaill76 22M Dec 19 2022 rtmdet-ins_tiny_8xb32-300e_coco_20221130_151727-ec670f7e.pth\n" ] } ], "source": [ - "%%time\n", + "import mmdet\n", + "import mmengine\n", + "import os\n", + "import os.path as osp \n", "\n", - "!python3 eval_metric.py {cfg_path} yolo_result.pkl \\\n", - " --eval bbox \\\n", - " --cfg-options data.test.ann_file=data/coco/annotations/instances_val2017.json data.test.type='FasterCocoDataset'" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b6ce86d4-f61e-4c18-821c-676d66a10d08", - "metadata": {}, - "outputs": [], - "source": [ - "yoloact_model_path = \"https://download.openmmlab.com/mmdetection/v2.0/yolact/yolact_r50_1x8_coco/yolact_r50_1x8_coco_20200908-f38d58df.pth\"\n", - "!wget -P model {yoloact_model_path}" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "5685b448-6079-4f0a-a781-a3260b59e579", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "cfg_path='configs/yolact/yolact_r50_1x8_coco.py'\n" - ] - } - ], - "source": [ - "CONFIG_FILE = \"yolact/yolact_r50_1x8_coco.py\"\n", - "CHECKPOINT_FILE = \"model/yolact_r50_1x8_coco_20200908-f38d58df.pth\"\n", + "config_dir = osp.dirname(mmdet.__file__)\n", + "sub_config = \"configs/rtmdet/rtmdet-ins_tiny_8xb32-300e_coco.py\"\n", + "config_file = osp.join(config_dir, \".mim\", sub_config)\n", + "cfg = mmengine.Config.fromfile(config_file)\n", + "\n", + "model_file = \"https://download.openmmlab.com/mmdetection/v3.0/rtmdet/rtmdet-ins_tiny_8xb32-300e_coco/rtmdet-ins_tiny_8xb32-300e_coco_20221130_151727-ec670f7e.pth\"\n", + "\n", + "print(f\"{config_file=}\")\n", + "print(f\"{model_file=}\")\n", + "\n", + "!mkdir -p -m 777 model\n", "\n", - "cfg_path = osp.join(_BASE_CONFIG_DIR, CONFIG_FILE)\n", - "print(f\"{cfg_path=}\")" + "cfg.dump(osp.join('model', osp.basename(config_file)))\n", + "!wget -P model/ {model_file}\n", + "\n", + "!ls -lah model" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "0129cb16-65ac-4192-b933-9d38fc4d5aee", + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "_dop = \"\"\n", - "if use_cpu:\n", - " _dop += f\" --gpu-id -1 \"\n", - "\n", - "!python3 test.py \\\n", - " {cfg_path} \\\n", - " {CHECKPOINT_FILE} \\\n", - " --format-only {_dop}\\\n", - " --cfg-options data.test.ann_file=data/coco/annotations/instances_val2017.json \\\n", - " data.test.img_prefix=data/coco/val2017 \\\n", - " --out yoloact_result.pkl" + "## Validate" ] }, { "cell_type": "code", - "execution_count": 5, - "id": "91c15c82-b82a-46c2-8171-f517ab677529", + "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "Loads checkpoint by local backend from path: ./model/rtmdet-ins_tiny_8xb32-300e_coco_20221130_151727-ec670f7e.pth\n", + "12/05 15:22:56 - mmengine - \u001b[5m\u001b[4m\u001b[33mWARNING\u001b[0m - Failed to search registry with scope \"mmdet\" in the \"function\" registry tree. As a workaround, the current \"function\" registry in \"mmengine\" is used to build instance. This may cause unexpected failure when running the built modules. Please check whether \"mmdet\" is a correct scope, or whether the registry is initialized.\n", + "/home/mixaill76/.local/lib/python3.10/site-packages/mmengine/visualization/visualizer.py:196: UserWarning: Failed to add , please provide the `save_dir` argument.\n", + " warnings.warn(f'Failed to add {vis_backend.__class__}, '\n", "loading annotations into memory...\n", - "Done (t=0.28s)\n", + "Done (t=0.32s)\n", "creating index...\n", "index created!\n", - "Data uploaded for 2.235 sec.\n", + "loading annotations into memory...\n", + "Done (t=0.38s)\n", + "creating index...\n", + "index created!\n", + " 0%| | 0/5000 [00:00 None: + if not HAS_FASTER_COCOAPI: + raise RuntimeError('Failed to import `COCO` and `COCOeval` from ' + '`mmeval.utils.coco_wrapper`. ' + 'Please try to install official pycocotools by ' + '"pip install pycocotools"') + super().__init__(**kwargs) + # coco evaluation metrics + self.metrics = metric if isinstance(metric, list) else [metric] + allowed_metrics = ['bbox', 'segm'] + for metric in self.metrics: + if metric not in allowed_metrics: + raise KeyError( + "metric should be one of 'bbox' and 'segm'" + f'but got {metric}.') + + # do class wise evaluation, default False + self.classwise = classwise + + # proposal_nums used to compute recall or precision. + self.proposal_nums = list(proposal_nums) + + # iou_thrs used to compute recall or precision. + if iou_thrs is None: + iou_thrs = np.linspace( + .5, 0.95, int(np.round((0.95 - .5) / .05)) + 1, endpoint=True) + elif isinstance(iou_thrs, float): + iou_thrs = np.array([iou_thrs]) + elif is_list_of(iou_thrs, float): + iou_thrs = np.array(iou_thrs) + else: + raise TypeError( + '`iou_thrs` should be None, float, or a list of float') + + self.iou_thrs = iou_thrs + self.metric_items = metric_items + self.print_results = print_results + self.extra_calc = extra_calc + self.format_only = format_only + if self.format_only: + assert outfile_prefix is not None, 'outfile_prefix must be not' + 'None when format_only is True, otherwise the result files will' + 'be saved to a temp directory which will be cleaned up at the end.' + + self.outfile_prefix = outfile_prefix + + # if ann_file is not specified, + # initialize coco api with the converted dataset + self._coco_api: Optional[COCO] # type: ignore + if ann_file is not None: + with get_local_path( + filepath=ann_file, + backend_args=backend_args) as local_path: + self._coco_api = COCO(annotation_file=local_path) + else: + self._coco_api = None + + self.gt_mask_area = gt_mask_area + # handle dataset lazy init + self.cat_ids: list = [] + self.img_ids: list = [] + + def gt_to_coco_json(self, gt_dicts: Sequence[dict], + outfile_prefix: str) -> str: + """Convert ground truth to coco format json file. + + Args: + gt_dicts (Sequence[dict]): Ground truth of the dataset. + outfile_prefix (str): The filename prefix of the json files. If the + prefix is "somepath/xxx", the json file will be named + "somepath/xxx.gt.json". + + Returns: + str: The filename of the json file. + """ + try: + from faster_coco_wrapper import mask_util + except ImportError: + mask_util = None + + warnings.warn( + 'The area of the instance is default to use bbox area. ' + 'Compared to load annotation file evaluate way, this will ' + 'not affect the overall AP, but leads to different ' + 'small/medium/large AP results.') + + classes = self.classes + categories = [ + dict(id=id, name=name) for id, name in enumerate(classes) + ] + image_infos: list = [] + annotations: list = [] + + for idx, gt_dict in enumerate(gt_dicts): + img_id = gt_dict.get('img_id', idx) + image_info = dict( + id=img_id, + width=gt_dict['width'], + height=gt_dict['height'], + file_name='') + image_infos.append(image_info) + gt_bboxes = gt_dict['bboxes'] + gt_labels = gt_dict['labels'] + assert len(gt_bboxes) == len(gt_labels) + if 'ignore_flags' in gt_dict: + ignore_flags = gt_dict['ignore_flags'] + assert len(gt_bboxes) == len(ignore_flags) + else: + ignore_flags = np.zeros(len(gt_bboxes)) + if 'masks' in gt_dict: + gt_masks = gt_dict['masks'] + assert len(gt_masks) == len(gt_bboxes) + else: + gt_masks = [None for _ in range(len(gt_bboxes))] + + for i in range(len(gt_bboxes)): + label = gt_labels[i] + coco_bbox = self.xyxy2xywh(gt_bboxes[i]) + ignore_flag = ignore_flags[i] + mask = gt_masks[i] + annotation = dict( + id=len(annotations) + + 1, # coco api requires id starts with 1 + image_id=img_id, + bbox=coco_bbox, + iscrowd=int(ignore_flag), + category_id=int(label), + area=coco_bbox[2] * coco_bbox[3]) + if mask is not None: + if mask_util and self.gt_mask_area: + # Using mask area can reduce the gap of + # small/medium/large AP results. + area = mask_util.area(mask) + annotation['area'] = float(area) + if isinstance(mask, dict) and isinstance( + mask['counts'], bytes): + mask['counts'] = mask['counts'].decode() + annotation['segmentation'] = mask + annotations.append(annotation) + + info = dict( + date_created=str(datetime.datetime.now()), + description='Coco json file converted by mmeval CocoMetric.') + coco_json = dict( + info=info, + images=image_infos, + categories=categories, + licenses=None, + ) + if len(annotations) > 0: + coco_json['annotations'] = annotations + converted_json_path = f'{outfile_prefix}.gt.json' + with open(converted_json_path, 'w') as f: + dump(coco_json, f) + return converted_json_path + + def compute_metric(self, results: list) -> dict: + """Compute the COCO metrics. + + Args: + results (List[tuple]): A list of tuple. Each tuple is the + prediction and ground truth of an image. This list has already + been synced across all ranks. + + Returns: + dict: The computed metric. + The keys are the names of the metrics, and the values are + corresponding results. + """ + tmp_dir = None + if self.outfile_prefix is None: + tmp_dir = tempfile.TemporaryDirectory() + outfile_prefix = osp.join(tmp_dir.name, 'results') + else: + outfile_prefix = self.outfile_prefix + + classes = self.classes + # split gt and prediction list + preds, gts = zip(*results) + + if self._coco_api is None: + # use converted gt json file to initialize coco api + self.logger.info('Converting ground truth to coco format...') + coco_json_path = self.gt_to_coco_json( + gt_dicts=gts, outfile_prefix=outfile_prefix) + self._coco_api = COCO(coco_json_path) + + # handle lazy init + if len(self.cat_ids) == 0: + self.cat_ids = self._coco_api.get_cat_ids( + cat_names=classes) # type: ignore + if len(self.img_ids) == 0: + self.img_ids = self._coco_api.get_img_ids() + + # convert predictions to coco format and dump to json file + result_files = self.results2json(preds, outfile_prefix) + + eval_results: OrderedDict = OrderedDict() + table_results: OrderedDict = OrderedDict() + if self.format_only: + self.logger.info( + f'Results are saved in {osp.dirname(outfile_prefix)}') + return eval_results + + for metric in self.metrics: + self.logger.info(f'Evaluating {metric}...') + + # evaluate proposal, bbox and segm + iou_type = 'bbox' if metric == 'proposal' else metric + if metric not in result_files: + raise KeyError(f'{metric} is not in results') + try: + predictions = load(result_files[metric]) + if iou_type == 'segm': + # Refer to https://github.com/cocodataset/cocoapi/blob/master/PythonAPI/pycocotools/coco.py#L331 # noqa + # When evaluating mask AP, if the results contain bbox, + # cocoapi will use the box area instead of the mask area + # for calculating the instance area. Though the overall AP + # is not affected, this leads to different + # small/medium/large mask AP results. + for x in predictions: + x.pop('bbox') + coco_dt = self._coco_api.loadRes(predictions) + + except IndexError: + self.logger.warning('The testing results of the ' + 'whole dataset is empty.') + break + + coco_eval = COCOeval(self._coco_api, coco_dt, iou_type, extra_calc=self.extra_calc) + + coco_eval.params.catIds = self.cat_ids + coco_eval.params.imgIds = self.img_ids + coco_eval.params.maxDets = self.proposal_nums + coco_eval.params.iouThrs = self.iou_thrs + + # mapping of cocoEval.stats + coco_metric_names = { + 'mAP': 0, + 'mAP_50': 1, + 'mAP_75': 2, + 'mAP_s': 3, + 'mAP_m': 4, + 'mAP_l': 5, + f'AR@{self.proposal_nums[0]}': 6, + f'AR@{self.proposal_nums[1]}': 7, + f'AR@{self.proposal_nums[2]}': 8, + f'AR_s@{self.proposal_nums[2]}': 9, + f'AR_m@{self.proposal_nums[2]}': 10, + f'AR_l@{self.proposal_nums[2]}': 11 + } + metric_items = self.metric_items + if metric_items is not None: + for metric_item in metric_items: + if metric_item not in coco_metric_names: + raise KeyError( + f'metric item "{metric_item}" is not supported') + + coco_eval.evaluate() + coco_eval.accumulate() + # Save coco summarize print information to logger + redirect_string = io.StringIO() + with contextlib.redirect_stdout(redirect_string): + coco_eval.summarize() + self.logger.info('\n' + redirect_string.getvalue()) + if metric_items is None: + metric_items = [ + 'mAP', 'mAP_50', 'mAP_75', 'mAP_s', 'mAP_m', 'mAP_l' + ] + + results_list = [] + for metric_item in metric_items: + key = f'{metric}_{metric_item}' + val = coco_eval.stats[coco_metric_names[metric_item]] + results_list.append(f'{round(val * 100, 2):0.2f}') + eval_results[key] = float(val) + table_results[f'{metric}_result'] = results_list + + if self.classwise: # Compute per-category AP + # Compute per-category AP + # from https://github.com/facebookresearch/detectron2/ + precisions = coco_eval.eval['precision'] + # precision: (iou, recall, cls, area range, max dets) + assert len(self.cat_ids) == precisions.shape[2] + + results_per_category = [] + for idx, cat_id in enumerate(self.cat_ids): + # area range index 0: all area ranges + # max dets index -1: typically 100 per image + nm = self._coco_api.loadCats(cat_id)[0] + precision = precisions[:, :, idx, 0, -1] + precision = precision[precision > -1] + if precision.size: + ap = np.mean(precision) + else: + ap = float('nan') + results_per_category.append( + (f'{nm["name"]}', f'{round(ap * 100, 2):0.2f}')) + eval_results[f'{metric}_{nm["name"]}_precision'] = ap + + table_results[f'{metric}_classwise_result'] = \ + results_per_category + if tmp_dir is not None: + tmp_dir.cleanup() + # if the testing results of the whole dataset is empty, + # does not print tables. + if self.print_results and len(table_results) > 0: + self._print_results(table_results) + return eval_results + + def _print_results(self, table_results: dict) -> None: + """Print the evaluation results table. + + Args: + table_results (dict): The computed metric. + """ + for metric in self.metrics: + result = table_results[f'{metric}_result'] + + if metric == 'proposal': + table_title = ' Recall Results (%)' + if self.metric_items is None: + assert len(result) == 6 + headers = [ + f'AR@{self.proposal_nums[0]}', + f'AR@{self.proposal_nums[1]}', + f'AR@{self.proposal_nums[2]}', + f'AR_s@{self.proposal_nums[2]}', + f'AR_m@{self.proposal_nums[2]}', + f'AR_l@{self.proposal_nums[2]}' + ] + else: + assert len(result) == len(self.metric_items) # type: ignore # yapf: disable # noqa: E501 + headers = self.metric_items # type: ignore + else: + table_title = f' {metric} Results (%)' + if self.metric_items is None: + assert len(result) == 6 + headers = [ + f'{metric}_mAP', f'{metric}_mAP_50', + f'{metric}_mAP_75', f'{metric}_mAP_s', + f'{metric}_mAP_m', f'{metric}_mAP_l' + ] + else: + assert len(result) == len(self.metric_items) + headers = [ + f'{metric}_{item}' for item in self.metric_items + ] + table = Table(title=table_title) + console = Console() + for name in headers: + table.add_column(name, justify='left') + table.add_row(*result) + with console.capture() as capture: + console.print(table, end='') + self.logger.info('\n' + capture.get()) + + if self.classwise and metric != 'proposal': + self.logger.info( + f'Evaluating {metric} metric of each category...') + classwise_table_title = f' {metric} Classwise Results (%)' + classwise_result = table_results[f'{metric}_classwise_result'] + + num_columns = min(6, len(classwise_result) * 2) + results_flatten = list(itertools.chain(*classwise_result)) + headers = ['category', f'{metric}_AP'] * (num_columns // 2) + results_2d = itertools.zip_longest(*[ + results_flatten[i::num_columns] for i in range(num_columns) + ]) + + table = Table(title=classwise_table_title) + console = Console() + for name in headers: + table.add_column(name, justify='left') + for _result in results_2d: + table.add_row(*_result) + with console.capture() as capture: + console.print(table, end='') + self.logger.info('\n' + capture.get()) + +# Keep the deprecated metric name as an alias. +# The deprecated Metric names will be removed in 1.0.0! +COCODetectionMetric = COCODetection diff --git a/examples/comparison/faster_coco_wrapper.py b/examples/comparison/faster_coco_wrapper.py new file mode 100644 index 0000000..e6629cd --- /dev/null +++ b/examples/comparison/faster_coco_wrapper.py @@ -0,0 +1,191 @@ +# Copyright (c) MiXaill76. +from collections import defaultdict +from pathlib import Path +from faster_coco_eval import COCO as _COCO +from faster_coco_eval import COCOeval_faster as _COCOeval +import faster_coco_eval.core.mask as _mask_util +from typing import Dict, Optional, Sequence, Union + + +class COCO(_COCO): + """This class is almost the same as official pycocotools package. + + It implements some snake case function aliases. So that the COCO class has + the same interface as LVIS class. + + Args: + annotation_file (str, optional): Path of annotation file. + Defaults to None. + """ + + def __init__(self, + annotation_file: Optional[Union[str, Path]] = None) -> None: + super().__init__(annotation_file=annotation_file) + self.img_ann_map = self.imgToAnns + self.cat_img_map = self.catToImgs + + def get_ann_ids(self, + img_ids: Union[list, int] = [], + cat_ids: Union[list, int] = [], + area_rng: Union[list, int] = [], + iscrowd: Optional[bool] = None) -> list: + """Get annotation ids that satisfy given filter conditions. + + Args: + img_ids (list | int): Get annotations for given images. + cat_ids (list | int): Get categories for given images. + area_rng (list | int): Get annotations for given area range. + iscrowd (bool, optional): Get annotations for given crowd label. + + Returns: + List: Integer array of annotation ids. + """ + return self.getAnnIds(img_ids, cat_ids, area_rng, iscrowd) + + def get_cat_ids(self, + cat_names: Union[list, int] = [], + sup_names: Union[list, int] = [], + cat_ids: Union[list, int] = []) -> list: + """Get category ids that satisfy given filter conditions. + + Args: + cat_names (list | int): Get categories for given category names. + sup_names (list | int): Get categories for given supercategory + names. + cat_ids (list | int): Get categories for given category ids. + + Returns: + List: Integer array of category ids. + """ + return self.getCatIds(cat_names, sup_names, cat_ids) + + def get_img_ids(self, + img_ids: Union[list, int] = [], + cat_ids: Union[list, int] = []) -> list: + """Get image ids that satisfy given filter conditions. + + Args: + img_ids (list | int): Get images for given ids + cat_ids (list | int): Get images with all given cats + + Returns: + List: Integer array of image ids. + """ + return self.getImgIds(img_ids, cat_ids) + + def load_anns(self, ids: Union[list, int] = []) -> list: + """Load annotations with the specified ids. + + Args: + ids (list | int): Integer ids specifying annotations. + + Returns: + List[dict]: Loaded annotation objects. + """ + return self.loadAnns(ids) + + def load_cats(self, ids: Union[list, int] = []) -> list: + """Load categories with the specified ids. + + Args: + ids (list | int): Integer ids specifying categories. + + Returns: + List[dict]: loaded category objects. + """ + return self.loadCats(ids) + + def load_imgs(self, ids: Union[list, int] = []) -> list: + """Load annotations with the specified ids. + + Args: + ids (list): integer ids specifying image. + + Returns: + List[dict]: Loaded image objects. + """ + return self.loadImgs(ids) + + +class COCOPanoptic(COCO): + """This wrapper is for loading the panoptic style annotation file.""" + + def createIndex(self) -> None: + """Create index.""" + # create index + print('creating index...') + # anns stores 'segment_id -> annotation' + anns: Dict[int, list] = {} + cats: Dict[int, dict] = {} + imgs: Dict[int, dict] = {} + img_to_anns, cat_to_imgs = defaultdict(list), defaultdict(list) + if 'annotations' in self.dataset: + for ann in self.dataset['annotations']: + for seg_ann in ann['segments_info']: + # to match with instance.json + seg_ann['image_id'] = ann['image_id'] + img_to_anns[ann['image_id']].append(seg_ann) + # segment_id is not unique in coco dataset orz... + # annotations from different images but + # may have same segment_id + if seg_ann['id'] in anns.keys(): + anns[seg_ann['id']].append(seg_ann) + else: + anns[seg_ann['id']] = [seg_ann] + + # filter out annotations from other images + img_to_anns_ = defaultdict(list) + for k, v in img_to_anns.items(): + img_to_anns_[k] = [x for x in v if x['image_id'] == k] + img_to_anns = img_to_anns_ + + if 'images' in self.dataset: + for img_info in self.dataset['images']: + img_info['segm_file'] = img_info['file_name'].replace( + 'jpg', 'png') + imgs[img_info['id']] = img_info + + if 'categories' in self.dataset: + for cat in self.dataset['categories']: + cats[cat['id']] = cat + + if 'annotations' in self.dataset and 'categories' in self.dataset: + for ann in self.dataset['annotations']: + for seg_ann in ann['segments_info']: + cat_to_imgs[seg_ann['category_id']].append(ann['image_id']) + + print('index created!') + + self.anns = anns + self.imgToAnns = img_to_anns + self.catToImgs = cat_to_imgs + self.imgs = imgs + self.cats = cats + + def load_anns(self, ids: Union[list, int] = []) -> list: + """Load annotations with the specified ids. + + ``self.anns`` is a list of annotation lists instead of a + list of annotations. + + Args: + ids (Union[List[int], int]): Integer ids specifying annotations. + + Returns: + List: Loaded annotation objects. + """ + anns = [] + + if isinstance(ids, Sequence): + # self.anns is a list of annotation lists instead of + # a list of annotations + for id in ids: + anns += self.anns[id] + return anns + else: + return self.anns[ids] + + +# just for the ease of import +COCOeval = _COCOeval +mask_util = _mask_util diff --git a/examples/comparison/mmdet_mmeval.py b/examples/comparison/mmdet_mmeval.py new file mode 100644 index 0000000..a169ad9 --- /dev/null +++ b/examples/comparison/mmdet_mmeval.py @@ -0,0 +1,68 @@ +import argparse +import numpy as np +import pycocotools.mask as cocomask +import tqdm +import time +from mmeval.metrics import COCODetection # type: ignore +from faster_coco_detection import FasterCOCODetection +from mmdet.datasets import CocoDataset +from mmdet.apis import DetInferencer + + +def do_mmeval_evaluate(config_file : str, checkpoint : str): + model = DetInferencer(config_file, checkpoint, show_progress=False) + + coco_dataset = CocoDataset( + # ann_file='annotations/instances_val2017_short.json', + ann_file='annotations/instances_val2017.json', + data_prefix=dict(img='val2017/'), + data_root='./COCO/DIR' + ) + + faster_coco_metric = FasterCOCODetection( + ann_file=coco_dataset.ann_file, + metric=["bbox", "segm"], + proposal_nums=[1, 10, 100], + ) + coco_metric = COCODetection( + ann_file=coco_dataset.ann_file, + metric=["bbox", "segm"], + proposal_nums=[1, 10, 100], + ) + + faster_coco_metric.dataset_meta = { + "CLASSES": coco_dataset.METAINFO['classes'] + } + coco_metric.dataset_meta = { + "CLASSES": coco_dataset.METAINFO['classes'] + } + + for item in tqdm.tqdm(coco_dataset): + pred_results = model(item['img_path'])['predictions'][0] + pred_results['bboxes'] = np.array(pred_results['bboxes']) + pred_results['img_id'] = item['img_id'] + coco_metric.add_predictions([pred_results]) + faster_coco_metric.add_predictions([pred_results]) + + ts1 = time.time() + coco_metric.compute() + te1 = time.time() + + print(f"coco_metric.compute() : {te1-ts1:.3f}") + + ts2 = time.time() + faster_coco_metric.compute() + te2 = time.time() + + print(f"faster_coco_metric.compute() : {te2-ts2:.3f}") + + print((te2-ts2) / (te1-ts1)) + print() + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('--load', type=str, help='load a model for evaluation.', required=True) + parser.add_argument('--config', type=str, help='load a config for evaluation.', required=True) + args = parser.parse_args() + + do_mmeval_evaluate(args.config, args.load) \ No newline at end of file diff --git a/examples/comparison/test.py b/examples/comparison/test.py deleted file mode 100644 index 26d9a3f..0000000 --- a/examples/comparison/test.py +++ /dev/null @@ -1,282 +0,0 @@ -# Copyright (c) OpenMMLab. All rights reserved. -import argparse -import os -import os.path as osp -import time -import warnings - -import mmcv -import torch -from mmcv import Config, DictAction -from mmcv.cnn import fuse_conv_bn -from mmcv.runner import (get_dist_info, init_dist, load_checkpoint, - wrap_fp16_model) - -from mmdet.apis import multi_gpu_test, single_gpu_test -from mmdet.datasets import (build_dataloader, build_dataset, - replace_ImageToTensor) -from mmdet.models import build_detector -from mmdet.utils import (build_ddp, build_dp, compat_cfg, get_device, - replace_cfg_vals, setup_multi_processes, - update_data_root) - - -def parse_args(): - parser = argparse.ArgumentParser( - description='MMDet test (and eval) a model') - parser.add_argument('config', help='test config file path') - parser.add_argument('checkpoint', help='checkpoint file') - parser.add_argument( - '--work-dir', - help='the directory to save the file containing evaluation metrics') - parser.add_argument('--out', help='output result file in pickle format') - parser.add_argument( - '--fuse-conv-bn', - action='store_true', - help='Whether to fuse conv and bn, this will slightly increase' - 'the inference speed') - parser.add_argument( - '--gpu-ids', - type=int, - nargs='+', - help='(Deprecated, please use --gpu-id) ids of gpus to use ' - '(only applicable to non-distributed training)') - parser.add_argument( - '--gpu-id', - type=int, - default=0, - help='id of gpu to use ' - '(only applicable to non-distributed testing)') - parser.add_argument( - '--format-only', - action='store_true', - help='Format the output results without perform evaluation. It is' - 'useful when you want to format the result to a specific format and ' - 'submit it to the test server') - parser.add_argument( - '--eval', - type=str, - nargs='+', - help='evaluation metrics, which depends on the dataset, e.g., "bbox",' - ' "segm", "proposal" for COCO, and "mAP", "recall" for PASCAL VOC') - parser.add_argument('--show', action='store_true', help='show results') - parser.add_argument( - '--show-dir', help='directory where painted images will be saved') - parser.add_argument( - '--show-score-thr', - type=float, - default=0.3, - help='score threshold (default: 0.3)') - parser.add_argument( - '--gpu-collect', - action='store_true', - help='whether to use gpu to collect results.') - parser.add_argument( - '--tmpdir', - help='tmp directory used for collecting results from multiple ' - 'workers, available when gpu-collect is not specified') - parser.add_argument( - '--cfg-options', - nargs='+', - action=DictAction, - help='override some settings in the used config, the key-value pair ' - 'in xxx=yyy format will be merged into config file. If the value to ' - 'be overwritten is a list, it should be like key="[a,b]" or key=a,b ' - 'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" ' - 'Note that the quotation marks are necessary and that no white space ' - 'is allowed.') - parser.add_argument( - '--options', - nargs='+', - action=DictAction, - help='custom options for evaluation, the key-value pair in xxx=yyy ' - 'format will be kwargs for dataset.evaluate() function (deprecate), ' - 'change to --eval-options instead.') - parser.add_argument( - '--eval-options', - nargs='+', - action=DictAction, - help='custom options for evaluation, the key-value pair in xxx=yyy ' - 'format will be kwargs for dataset.evaluate() function') - parser.add_argument( - '--launcher', - choices=['none', 'pytorch', 'slurm', 'mpi'], - default='none', - help='job launcher') - parser.add_argument('--local_rank', type=int, default=0) - args = parser.parse_args() - if 'LOCAL_RANK' not in os.environ: - os.environ['LOCAL_RANK'] = str(args.local_rank) - - if args.options and args.eval_options: - raise ValueError( - '--options and --eval-options cannot be both ' - 'specified, --options is deprecated in favor of --eval-options') - if args.options: - warnings.warn('--options is deprecated in favor of --eval-options') - args.eval_options = args.options - return args - - -def main(): - args = parse_args() - - assert args.out or args.eval or args.format_only or args.show \ - or args.show_dir, \ - ('Please specify at least one operation (save/eval/format/show the ' - 'results / save the results) with the argument "--out", "--eval"' - ', "--format-only", "--show" or "--show-dir"') - - if args.eval and args.format_only: - raise ValueError('--eval and --format_only cannot be both specified') - - if args.out is not None and not args.out.endswith(('.pkl', '.pickle')): - raise ValueError('The output file must be a pkl file.') - - cfg = Config.fromfile(args.config) - - # replace the ${key} with the value of cfg.key - cfg = replace_cfg_vals(cfg) - - # update data root according to MMDET_DATASETS - update_data_root(cfg) - - if args.cfg_options is not None: - cfg.merge_from_dict(args.cfg_options) - - cfg = compat_cfg(cfg) - - # set multi-process settings - setup_multi_processes(cfg) - - # set cudnn_benchmark - if cfg.get('cudnn_benchmark', False): - torch.backends.cudnn.benchmark = True - - if 'pretrained' in cfg.model: - cfg.model.pretrained = None - elif 'init_cfg' in cfg.model.backbone: - cfg.model.backbone.init_cfg = None - - if cfg.model.get('neck'): - if isinstance(cfg.model.neck, list): - for neck_cfg in cfg.model.neck: - if neck_cfg.get('rfp_backbone'): - if neck_cfg.rfp_backbone.get('pretrained'): - neck_cfg.rfp_backbone.pretrained = None - elif cfg.model.neck.get('rfp_backbone'): - if cfg.model.neck.rfp_backbone.get('pretrained'): - cfg.model.neck.rfp_backbone.pretrained = None - - if args.gpu_ids is not None: - cfg.gpu_ids = args.gpu_ids[0:1] - warnings.warn('`--gpu-ids` is deprecated, please use `--gpu-id`. ' - 'Because we only support single GPU mode in ' - 'non-distributed testing. Use the first GPU ' - 'in `gpu_ids` now.') - else: - cfg.gpu_ids = [args.gpu_id] - - if cfg.gpu_ids == [-1]: - cfg.device = "cpu" - else: - cfg.device = get_device() - - # init distributed env first, since logger depends on the dist info. - if args.launcher == 'none': - distributed = False - else: - distributed = True - init_dist(args.launcher, **cfg.dist_params) - - test_dataloader_default_args = dict( - samples_per_gpu=1, workers_per_gpu=2, dist=distributed, shuffle=False) - - # in case the test dataset is concatenated - if isinstance(cfg.data.test, dict): - cfg.data.test.test_mode = True - if cfg.data.test_dataloader.get('samples_per_gpu', 1) > 1: - # Replace 'ImageToTensor' to 'DefaultFormatBundle' - cfg.data.test.pipeline = replace_ImageToTensor( - cfg.data.test.pipeline) - elif isinstance(cfg.data.test, list): - for ds_cfg in cfg.data.test: - ds_cfg.test_mode = True - if cfg.data.test_dataloader.get('samples_per_gpu', 1) > 1: - for ds_cfg in cfg.data.test: - ds_cfg.pipeline = replace_ImageToTensor(ds_cfg.pipeline) - - test_loader_cfg = { - **test_dataloader_default_args, - **cfg.data.get('test_dataloader', {}) - } - - rank, _ = get_dist_info() - # allows not to create - if args.work_dir is not None and rank == 0: - mmcv.mkdir_or_exist(osp.abspath(args.work_dir)) - timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) - json_file = osp.join(args.work_dir, f'eval_{timestamp}.json') - - # build the dataloader - dataset = build_dataset(cfg.data.test) - data_loader = build_dataloader(dataset, **test_loader_cfg) - - # build the model and load checkpoint - cfg.model.train_cfg = None - model = build_detector(cfg.model, test_cfg=cfg.get('test_cfg')) - fp16_cfg = cfg.get('fp16', None) - if fp16_cfg is not None: - print(f"fp16_cfg={fp16_cfg}") - wrap_fp16_model(model) - - checkpoint = load_checkpoint(model, args.checkpoint, map_location='cpu') - if args.fuse_conv_bn: - model = fuse_conv_bn(model) - # old versions did not save class info in checkpoints, this walkaround is - # for backward compatibility - if 'CLASSES' in checkpoint.get('meta', {}): - model.CLASSES = checkpoint['meta']['CLASSES'] - else: - model.CLASSES = dataset.CLASSES - - if not distributed: - model = build_dp(model, cfg.device, device_ids=cfg.gpu_ids) - outputs = single_gpu_test(model, data_loader, args.show, args.show_dir, - args.show_score_thr) - else: - model = build_ddp( - model, - cfg.device, - device_ids=[int(os.environ['LOCAL_RANK'])], - broadcast_buffers=False) - outputs = multi_gpu_test( - model, data_loader, args.tmpdir, args.gpu_collect - or cfg.evaluation.get('gpu_collect', False)) - - rank, _ = get_dist_info() - if rank == 0: - if args.out: - print(f'\nwriting results to {args.out}') - mmcv.dump(outputs, args.out) - kwargs = {} if args.eval_options is None else args.eval_options - if args.format_only: - dataset.format_results(outputs, **kwargs) - if args.eval: - eval_kwargs = cfg.get('evaluation', {}).copy() - # hard-code way to remove EvalHook args - for key in [ - 'interval', 'tmpdir', 'start', 'gpu_collect', 'save_best', - 'rule', 'dynamic_intervals' - ]: - eval_kwargs.pop(key, None) - eval_kwargs.update(dict(metric=args.eval, **kwargs)) - metric = dataset.evaluate(outputs, **eval_kwargs) - print(metric) - metric_dict = dict(config=args.config, metric=metric) - if args.work_dir is not None and rank == 0: - mmcv.dump(metric_dict, json_file) - - -if __name__ == '__main__': - main() From 4a8fa4d163c12cd17a39e262909b096bbb8bfd7b Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Tue, 5 Dec 2023 21:36:26 +0300 Subject: [PATCH 04/16] ignore COCO --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1f97451..97f09ce 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ build dist faster_coco_eval.egg-info *.pyc -__pycache__ \ No newline at end of file +__pycache__ +examples/comparison/COCO +examples/comparison/model \ No newline at end of file From fa647569f5682c9ae29b97769a74b3d77c4b70b2 Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Tue, 5 Dec 2023 21:39:11 +0300 Subject: [PATCH 05/16] changelog --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d10bb13..17996a0 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ cur.plot_pre_rec(plotly_backend=False) - [x] Updated pre-rec calculation method - [x] Updated required libraries - [x] Moved all matplotlib dependencies to plotly +- [x] Append new examples & mmeval test file ### v1.3.3 From 8a5f7a25059e24bedaaceaa688eabb3e5431a369 Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Wed, 6 Dec 2023 16:21:31 +0300 Subject: [PATCH 06/16] append stop on error on make --- Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 8e67478..9a2eb00 100644 --- a/Makefile +++ b/Makefile @@ -12,22 +12,22 @@ wheel: python3 -m build . --wheel docker-sdist: - bash docker/auto_build.sh "cp38-cp38" sdist + bash -e docker/auto_build.sh "cp38-cp38" sdist docker-3.7: - bash docker/auto_build.sh "cp37-cp37m" wheel + bash -e docker/auto_build.sh "cp37-cp37m" wheel docker-3.8: - bash docker/auto_build.sh "cp38-cp38" wheel + bash -e docker/auto_build.sh "cp38-cp38" wheel docker-3.9: - bash docker/auto_build.sh "cp39-cp39" wheel + bash -e docker/auto_build.sh "cp39-cp39" wheel docker-3.10: - bash docker/auto_build.sh "cp310-cp310" wheel + bash -e docker/auto_build.sh "cp310-cp310" wheel docker-3.11: - bash docker/auto_build.sh "cp311-cp311" wheel + bash -e docker/auto_build.sh "cp311-cp311" wheel pull: twine check dist/* From b53edf33bf9fca6ef8e6d480070518e384867725 Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Wed, 6 Dec 2023 16:21:50 +0300 Subject: [PATCH 07/16] format toml --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f87f944..25494dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,9 +2,9 @@ requires = [ "setuptools>=42", "wheel", + "build", "numpy", "cython", - "build>=0.10.0", "pybind11==2.11.1", ] -build-backend = 'setuptools.build_meta' \ No newline at end of file +build-backend = "setuptools.build_meta" From a1b1f95acd9a9021eeaaa58982dc3a862e0b3b52 Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Wed, 6 Dec 2023 17:32:29 +0300 Subject: [PATCH 08/16] gcc warning fix --- csrc/mask/pycocotools/_mask.pyx | 1 + setup.py | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/csrc/mask/pycocotools/_mask.pyx b/csrc/mask/pycocotools/_mask.pyx index 8fc925c..18cdb5f 100644 --- a/csrc/mask/pycocotools/_mask.pyx +++ b/csrc/mask/pycocotools/_mask.pyx @@ -1,4 +1,5 @@ # distutils: language = c +# cython: language_level=2 #************************************************************************** # Microsoft COCO Toolbox. version 2.0 diff --git a/setup.py b/setup.py index c2de4b9..357f443 100644 --- a/setup.py +++ b/setup.py @@ -134,6 +134,7 @@ def get_extensions(version_info): '-Wno-unused-function', '-std=c99', '-O3', + '-Wno-maybe-uninitialized', '-Wno-misleading-indentation', ], extra_link_args=[], @@ -170,7 +171,4 @@ def get_extensions(version_info): ], python_requires=">=3.7", install_requires=parse_requirements('requirements/runtime.txt'), - extras_require={ - 'all': parse_requirements('requirements/optional.txt'), - }, ) From 4270be8a96e4112a06b9ffa42a87fe5ab1356a56 Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Wed, 6 Dec 2023 17:32:56 +0300 Subject: [PATCH 09/16] python3 alternatives fix --- docker/Dockerfile | 7 +++++-- docker/auto_build.sh | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index f6c0ad7..c65eaf6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM quay.io/pypa/manylinux_2_28_x86_64 +FROM quay.io/pypa/manylinux_2_28_x86_64:latest LABEL maintainer="MiXaiLL76 " USER root @@ -17,8 +17,11 @@ ENV EID=${ID} ENV PATH="${PATH}:/opt/python/${PYTHON3_VERSION}/bin" +RUN alternatives --install /usr/bin/python3 python3 /opt/python/${PYTHON3_VERSION}/bin/python3 1 +RUN alternatives --set python3 /opt/python/${PYTHON3_VERSION}/bin/python3 + ### basic_config WORKDIR /tmp COPY docker/build_pipeline.sh . -ENTRYPOINT bash build_pipeline.sh +ENTRYPOINT bash -e build_pipeline.sh diff --git a/docker/auto_build.sh b/docker/auto_build.sh index 29ed2a8..afe141e 100755 --- a/docker/auto_build.sh +++ b/docker/auto_build.sh @@ -11,5 +11,6 @@ docker build -f ./docker/Dockerfile \ --tag faster_coco_eval:${PYTHON3_VERSION}_${MAKE_CONFIG} . docker_name="faster_coco_eval_${PYTHON3_VERSION//-/_}_${MAKE_CONFIG}" + docker run --name ${docker_name} -v $(pwd):/app/src faster_coco_eval:${PYTHON3_VERSION}_${MAKE_CONFIG} docker rm ${docker_name} From 0a4aa96b04714e6e759cddae01fa8f566d68a501 Mon Sep 17 00:00:00 2001 From: MiXaiLL76 Date: Wed, 6 Dec 2023 17:33:15 +0300 Subject: [PATCH 10/16] useCats fix --- examples/curve_example.ipynb | 278 ++++++++++++++++++++++++++++++++--- 1 file changed, 256 insertions(+), 22 deletions(-) diff --git a/examples/curve_example.ipynb b/examples/curve_example.ipynb index 4bb72ae..2ff820b 100644 --- a/examples/curve_example.ipynb +++ b/examples/curve_example.ipynb @@ -1258,9 +1258,9 @@ } }, "text/html": [ - "