Towards-Realtime-MOT/visualise_embeddings.ipynb

1210 lines
53 MiB
Plaintext
Raw Permalink Normal View History

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Visualise embeddings of the JDE model\n",
"\n",
"This notebook embeds images from the training data using the JDE model. It then collects all embeddings and projects them using different techniques (e.g. UMAP, PCA). These projections are plotted; try to hover the plot to see the source detection.\n",
"\n",
"In a second step these images are drawn onto a canvas using the projected points."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"import glob\n",
"import pickle\n",
"from typing import TypedDict\n",
"from tqdm.auto import tqdm\n",
"\n",
"import os\n",
"import numpy as np\n",
"\n",
"import logging\n",
"import argparse\n",
"logger = logging.getLogger(__name__)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"from track import eval_seq\n",
"\n",
"from utils.parse_config import parse_model_cfg\n",
"from utils.utils import mkdir_if_missing\n",
"import utils.datasets as datasets\n",
"from utils.log import logger as trmlog # we need to override this...\n",
"\n",
"\n",
"trmlog.setLevel(logging.INFO)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"import umap # should provide better results than t-SNE\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
2023-04-13 13:12:50 +02:00
"<style>\n",
" .bk-notebook-logo {\n",
" display: block;\n",
" width: 20px;\n",
" height: 20px;\n",
" background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAOkSURBVDiNjZRtaJVlGMd/1/08zzln5zjP1LWcU9N0NkN8m2CYjpgQYQXqSs0I84OLIC0hkEKoPtiH3gmKoiJDU7QpLgoLjLIQCpEsNJ1vqUOdO7ppbuec5+V+rj4ctwzd8IIbbi6u+8f1539dt3A78eXC7QizUF7gyV1fD1Yqg4JWz84yffhm0qkFqBogB9rM8tZdtwVsPUhWhGcFJngGeWrPzHm5oaMmkfEg1usvLFyc8jLRqDOMru7AyC8saQr7GG7f5fvDeH7Ej8CM66nIF+8yngt6HWaKh7k49Soy9nXurCi1o3qUbS3zWfrYeQDTB/Qj6kX6Ybhw4B+bOYoLKCC9H3Nu/leUTZ1JdRWkkn2ldcCamzrcf47KKXdAJllSlxAOkRgyHsGC/zRday5Qld9DyoM4/q/rUoy/CXh3jzOu3bHUVZeU+DEn8FInkPBFlu3+nW3Nw0mk6vCDiWg8CeJaxEwuHS3+z5RgY+YBR6V1Z1nxSOfoaPa4LASWxxdNp+VWTk7+4vzaou8v8PN+xo+KY2xsw6une2frhw05CTYOmQvsEhjhWjn0bmXPjpE1+kplmmkP3suftwTubK9Vq22qKmrBhpY4jvd5afdRA3wGjFAgcnTK2s4hY0/GPNIb0nErGMCRxWOOX64Z8RAC4oCXdklmEvcL8o0BfkNK4lUg9HTl+oPlQxdNo3Mg4Nv175e/1LDGzZen30MEjRUtmXSfiTVu1kK8W4txyV6BMKlbgk3lMwYCiusNy9fVfvvwMxv8Ynl6vxoByANLTWplvuj/nF9m2+PDtt1eiHPBr1oIfhCChQMBw6Aw0UulqTKZdfVvfG7VcfIqLG9bcldL/+pdWTLxLUy8Qq38heUIjh4XlzZxzQm19lLFlr8vdQ97rjZVOLf8nclzckbcD4wxXMidpX30sFd37Fv/GtwwhzhxGVAprjbg0gCAEeIgwCZyTV2Z1REEW8O4py0wsjeloKoMr6iCY6dP92H6Vw/oTyICIthibxjm/DfN9lVz8IqtqKYLUXfoKVMVQVVJOElGjrnnUt9T9wbgp8AyYKaGlqingHZU/uG2NTZSVqwHQTWkx9hxjkpWDaCg6Ckj5qebgBVbT3V3NNXMSiWSDdGV3hrtzla7J+duwPOToIg42ChPQOQjspnSlp1V+Gjdged7+8UN5CRAV7a5EdFNwCjEaBR27b3W890TE7g24NAP/mMDXRWrGoFPQI9ls/MWO2dWFAar/xcOIImbbpA3zgAAAABJRU5ErkJggg==);\n",
" }\n",
" </style>\n",
" <div>\n",
" <a href=\"https://bokeh.org\" target=\"_blank\" class=\"bk-notebook-logo\"></a>\n",
" <span id=\"p1002\">Loading BokehJS ...</span>\n",
" </div>\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"(function(root) {\n",
" function now() {\n",
" return new Date();\n",
" }\n",
"\n",
" const force = true;\n",
"\n",
" if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
" root._bokeh_onload_callbacks = [];\n",
" root._bokeh_is_loading = undefined;\n",
" }\n",
"\n",
"const JS_MIME_TYPE = 'application/javascript';\n",
" const HTML_MIME_TYPE = 'text/html';\n",
" const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
" const CLASS_NAME = 'output_bokeh rendered_html';\n",
"\n",
" /**\n",
" * Render data to the DOM node\n",
" */\n",
" function render(props, node) {\n",
" const script = document.createElement(\"script\");\n",
" node.appendChild(script);\n",
" }\n",
"\n",
" /**\n",
" * Handle when an output is cleared or removed\n",
" */\n",
" function handleClearOutput(event, handle) {\n",
" const cell = handle.cell;\n",
"\n",
" const id = cell.output_area._bokeh_element_id;\n",
" const server_id = cell.output_area._bokeh_server_id;\n",
" // Clean up Bokeh references\n",
" if (id != null && id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
"\n",
" if (server_id !== undefined) {\n",
" // Clean up Bokeh references\n",
" const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
" cell.notebook.kernel.execute(cmd_clean, {\n",
" iopub: {\n",
" output: function(msg) {\n",
" const id = msg.content.text.trim();\n",
" if (id in Bokeh.index) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
" }\n",
" }\n",
" });\n",
" // Destroy server and session\n",
" const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
" cell.notebook.kernel.execute(cmd_destroy);\n",
" }\n",
" }\n",
"\n",
" /**\n",
" * Handle when a new output is added\n",
" */\n",
" function handleAddOutput(event, handle) {\n",
" const output_area = handle.output_area;\n",
" const output = handle.output;\n",
"\n",
" // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
" if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
" return\n",
" }\n",
"\n",
" const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
"\n",
" if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
" toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
" // store reference to embed id on output_area\n",
" output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
" }\n",
" if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
" const bk_div = document.createElement(\"div\");\n",
" bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
" const script_attrs = bk_div.children[0].attributes;\n",
" for (let i = 0; i < script_attrs.length; i++) {\n",
" toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
" toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n",
" }\n",
" // store reference to server id on output_area\n",
" output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
" }\n",
" }\n",
"\n",
" function register_renderer(events, OutputArea) {\n",
"\n",
" function append_mime(data, metadata, element) {\n",
" // create a DOM node to render to\n",
" const toinsert = this.create_output_subarea(\n",
" metadata,\n",
" CLASS_NAME,\n",
" EXEC_MIME_TYPE\n",
" );\n",
" this.keyboard_manager.register_events(toinsert);\n",
" // Render to node\n",
" const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
" render(props, toinsert[toinsert.length - 1]);\n",
" element.append(toinsert);\n",
" return toinsert\n",
" }\n",
"\n",
" /* Handle when an output is cleared or removed */\n",
" events.on('clear_output.CodeCell', handleClearOutput);\n",
" events.on('delete.Cell', handleClearOutput);\n",
"\n",
" /* Handle when a new output is added */\n",
" events.on('output_added.OutputArea', handleAddOutput);\n",
"\n",
" /**\n",
" * Register the mime type and append_mime function with output_area\n",
" */\n",
" OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
" /* Is output safe? */\n",
" safe: true,\n",
" /* Index of renderer in `output_area.display_order` */\n",
" index: 0\n",
" });\n",
" }\n",
"\n",
" // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
" if (root.Jupyter !== undefined) {\n",
" const events = require('base/js/events');\n",
" const OutputArea = require('notebook/js/outputarea').OutputArea;\n",
"\n",
" if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
" register_renderer(events, OutputArea);\n",
" }\n",
" }\n",
" if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
" root._bokeh_timeout = Date.now() + 5000;\n",
" root._bokeh_failed_load = false;\n",
" }\n",
"\n",
" const NB_LOAD_WARNING = {'data': {'text/html':\n",
" \"<div style='background-color: #fdd'>\\n\"+\n",
" \"<p>\\n\"+\n",
" \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
" \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
" \"</p>\\n\"+\n",
" \"<ul>\\n\"+\n",
" \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
" \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
" \"</ul>\\n\"+\n",
" \"<code>\\n\"+\n",
" \"from bokeh.resources import INLINE\\n\"+\n",
" \"output_notebook(resources=INLINE)\\n\"+\n",
" \"</code>\\n\"+\n",
" \"</div>\"}};\n",
"\n",
" function display_loaded() {\n",
" const el = document.getElementById(\"p1002\");\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS is loading...\";\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
" }\n",
" } else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(display_loaded, 100)\n",
" }\n",
" }\n",
"\n",
" function run_callbacks() {\n",
" try {\n",
" root._bokeh_onload_callbacks.forEach(function(callback) {\n",
" if (callback != null)\n",
" callback();\n",
" });\n",
" } finally {\n",
" delete root._bokeh_onload_callbacks\n",
" }\n",
" console.debug(\"Bokeh: all callbacks have finished\");\n",
" }\n",
"\n",
" function load_libs(css_urls, js_urls, callback) {\n",
" if (css_urls == null) css_urls = [];\n",
" if (js_urls == null) js_urls = [];\n",
"\n",
" root._bokeh_onload_callbacks.push(callback);\n",
" if (root._bokeh_is_loading > 0) {\n",
" console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
" return null;\n",
" }\n",
" if (js_urls == null || js_urls.length === 0) {\n",
" run_callbacks();\n",
" return null;\n",
" }\n",
" console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
" root._bokeh_is_loading = css_urls.length + js_urls.length;\n",
"\n",
" function on_load() {\n",
" root._bokeh_is_loading--;\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n",
" run_callbacks()\n",
" }\n",
" }\n",
"\n",
" function on_error(url) {\n",
" console.error(\"failed to load \" + url);\n",
" }\n",
"\n",
" for (let i = 0; i < css_urls.length; i++) {\n",
" const url = css_urls[i];\n",
" const element = document.createElement(\"link\");\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\n",
" element.rel = \"stylesheet\";\n",
" element.type = \"text/css\";\n",
" element.href = url;\n",
" console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
" document.body.appendChild(element);\n",
" }\n",
"\n",
" for (let i = 0; i < js_urls.length; i++) {\n",
" const url = js_urls[i];\n",
" const element = document.createElement('script');\n",
" element.onload = on_load;\n",
" element.onerror = on_error.bind(null, url);\n",
" element.async = false;\n",
" element.src = url;\n",
" console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" document.head.appendChild(element);\n",
" }\n",
" };\n",
"\n",
" function inject_raw_css(css) {\n",
" const element = document.createElement(\"style\");\n",
" element.appendChild(document.createTextNode(css));\n",
" document.body.appendChild(element);\n",
" }\n",
"\n",
" const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.1.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.1.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.1.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.1.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.1.0.min.js\"];\n",
" const css_urls = [];\n",
"\n",
" const inline_js = [ function(Bokeh) {\n",
" Bokeh.set_log_level(\"info\");\n",
" },\n",
"function(Bokeh) {\n",
" }\n",
" ];\n",
"\n",
" function run_inline_js() {\n",
" if (root.Bokeh !== undefined || force === true) {\n",
" for (let i = 0; i < inline_js.length; i++) {\n",
" inline_js[i].call(root, root.Bokeh);\n",
" }\n",
"if (force === true) {\n",
" display_loaded();\n",
" }} else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(run_inline_js, 100);\n",
" } else if (!root._bokeh_failed_load) {\n",
" console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
" root._bokeh_failed_load = true;\n",
" } else if (force !== true) {\n",
" const cell = $(document.getElementById(\"p1002\")).parents('.cell').data().cell;\n",
" cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
" }\n",
" }\n",
"\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
" run_inline_js();\n",
" } else {\n",
" load_libs(css_urls, js_urls, function() {\n",
" console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
" run_inline_js();\n",
" });\n",
" }\n",
"}(window));"
],
"application/vnd.bokehjs_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n const force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n const NB_LOAD_WARNING = {'data': {'text/html':\n \"<div style='background-color: #fdd'>\\n\"+\n \"<p>\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"</p>\\n\"+\n \"<ul>\\n\"+\n \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n \"<li>use INLINE resources instead, as so:</li>\\n\"+\n \"</ul>\\n\"+\n \"<code>\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"</code>\\n\"+\n \"</div>\"}};\n\n function display_loaded() {\n const el = document.getElementById(\"p1002\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error(url) {\n console.error(\"failed to load \" + url);\n }\n\n for (let i = 0; i < css_urls.length; i++) {\n const url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n for (let i = 0; i < js_urls.length; i++) {\n const url = js_urls[i];\n const element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error.bind(null, url);\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.1.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.1.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.1.0.min.js\", \"https://cdn.bokeh.org
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# import matplotlib.pyplot as plt\n",
"\n",
"from bokeh.io import curdoc, output_notebook\n",
"from bokeh.models import ColumnDataSource\n",
"from bokeh.layouts import column, row, gridplot\n",
"from bokeh.plotting import figure, show\n",
"from bokeh.models import (PanTool, SaveTool,\n",
" ResetTool,\n",
" HoverTool, WheelZoomTool, BoxZoomTool)\n",
"\n",
"# load bokeh\n",
"output_notebook()\n"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"# p1 = figure(plot_width=250, plot_height=250)\n",
"# r1 = p1.circle([1,2,3],[3,2,1], size=20)\n",
"\n",
"# t = show(p1, notebook_handle=True)"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"img_seqs = [\n",
" \"MOT16/test/MOT16-01/\",\n",
" \"MOT16/test/MOT16-03/\",\n",
" \"MOT16/test/MOT16-06/\",\n",
" \"MOT16/test/MOT16-07/\",\n",
" \"MOT16/test/MOT16-08/\",\n",
" \"MOT16/test/MOT16-12/\",\n",
" \"MOT16/test/MOT16-14/\",\n",
" \"MOT16/train/MOT16-02/\",\n",
" \"MOT16/train/MOT16-04/\",\n",
" \"MOT16/train/MOT16-05/\",\n",
" \"MOT16/train/MOT16-09/\",\n",
" \"MOT16/train/MOT16-10/\",\n",
" \"MOT16/train/MOT16-11/\",\n",
" \"MOT16/train/MOT16-13/\",\n",
" \"CaltechPedestrians/data/images/\",\n",
" \"PRW/images/\",\n",
" \"CUHK-SYSU/images/\",\n",
" \"CityScapes/leftImg8bit/test/*\",\n",
" \"CityScapes/leftImg8bit/train/*\",\n",
" \"CityScapes/leftImg8bit/val/*\",\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"# Data types\n",
"\n",
"from dataclasses import dataclass\n",
"from pathlib import Path\n",
"\n",
"\n",
"Tlwh = list[float, float, float, float] #top left width height\n",
"Embedding = np.array\n",
"TrackerFrameEmbedding = list[Tlwh, Embedding]\n",
"\n",
"@dataclass\n",
"class FrameEmbedding():\n",
" pcl_filename: str\n",
" tlwh: Tlwh\n",
" embedding: Embedding\n",
" umap: Embedding = None\n",
" pca: Embedding = None\n",
" \n",
" @classmethod\n",
" def from_tracker_embedding(cls, pcl_filename: str | Path, tfe: TrackerFrameEmbedding):\n",
" return cls(pcl_filename=pcl_filename, tlwh=tfe[0], embedding=tfe[1])\n",
" \n",
" @property\n",
" def img_filename(self):\n",
" return self.pcl_filename[:-4] + '.jpg'\n",
" \n"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"# load options; quick'n'dirty copy from track.py (as the Namespace object is used in the multitracker)\n",
"\n",
"parser = argparse.ArgumentParser(prog='visualise_embeddings.py')\n",
"parser.add_argument('--cfg', type=str, default='cfg/yolov3_1088x608.cfg', help='cfg file path')\n",
"parser.add_argument('--weights', type=str, default='jde.1088x608.uncertainty.pt', help='path to weights file')\n",
"parser.add_argument('--iou-thres', type=float, default=0.5, help='iou threshold required to qualify as detected')\n",
"parser.add_argument('--conf-thres', type=float, default=0.5, help='object confidence threshold')\n",
"parser.add_argument('--nms-thres', type=float, default=0.4, help='iou threshold for non-maximum suppression')\n",
"parser.add_argument('--min-box-area', type=float, default=200, help='filter out tiny boxes')\n",
"parser.add_argument('--track-buffer', type=int, default=30, help='tracking buffer')\n",
"parser.add_argument('--dataset-dir', type=str, default=\"/datasets\", help='Path to directory with datasets')\n",
"parser.add_argument('--experiment-name', type=str, default=\"embedding_test\", help=\"name to prefix output directory with\")\n",
"parser.add_argument('--output-dir', type=str, default=\"./OUT\", help=\"directory for results\")\n",
" \n",
"# we're running in notebook, so default to empty\n",
"opt = parser.parse_args([])\n",
"\n",
"logger.setLevel(logging.INFO)\n",
"result_path = os.path.join(opt.output_dir, opt.experiment_name)\n",
"mkdir_if_missing(result_path)\n",
"data_type = 'mot'\n",
"\n",
"# Read config\n",
"cfg_dict = parse_model_cfg(opt.cfg)\n",
"# set img_size in opt, so it is passed on to JDETracker\n",
"opt.img_size = [int(cfg_dict[0]['width']), int(cfg_dict[0]['height'])]\n"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"from ipywidgets import __version__\n",
"## version > 7.7.2 doesn't work properly with vscode: https://github.com/microsoft/vscode-jupyter/issues/8552\n",
"assert __version__ == \"7.7.2\"\n",
"\n",
"# import time\n",
"# for i in tqdm(range(10)):\n",
"# time.sleep(1)"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {},
"outputs": [
{
"ename": "SyntaxError",
"evalue": "invalid syntax (1020855487.py, line 5)",
"output_type": "error",
"traceback": [
"\u001b[0;36m Cell \u001b[0;32mIn[46], line 5\u001b[0;36m\u001b[0m\n\u001b[0;31m tqdm.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n"
]
}
],
"source": [
" # run tracking on all img_seqs\n",
"\n",
"for pattern in tqdm(img_seqs):\n",
" for seq in glob.glob(os.path.join(opt.dataset_dir, pattern)):\n",
" logger.debug('start seq: {}'.format(seq))\n",
" if os.path.exists(os.path.join(seq, 'img1')):\n",
" seq_dir = os.path.join(seq, 'img1')\n",
" else:\n",
" seq_dir = seq\n",
" dataloader = datasets.LoadImages(seq_dir, opt.img_size)\n",
" # result_filename = os.path.join(result_path, '{}.txt'.format(seq))\n",
" try:\n",
" meta_info = open(os.path.join(seq, 'seqinfo.ini')).read() \n",
" frame_rate = int(meta_info[meta_info.find('frameRate')+10:meta_info.find('\\nseqLength')])\n",
" except FileNotFoundError as e:\n",
" logger.debug(f\"No ini file for {seq}. Note, these are only for MOT\")\n",
" frame_rate = 25\n",
" p = str(Path(seq).relative_to(opt.dataset_dir))\n",
" nf, ta, tc = eval_seq(opt, dataloader, data_type, None,\n",
" save_dir=os.path.join(result_path, p), save_figures=True, save_img=False, show_image=False, frame_rate=frame_rate)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Project embeddings"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"result_path = os.path.join(opt.output_dir, opt.experiment_name)\n",
"transformed_embedding_pcl = os.path.join(result_path, 'transformed_embeddings.pcl')\n",
"orig_embedding_pcl = os.path.join(result_path, 'orig_embeddings.pcl')\n",
"umap_pcl = os.path.join(result_path, 'reducer_umap.pcl')\n",
"pca_pcl = os.path.join(result_path, 'reducer_pca.pcl')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Load all pre-calculated embeddings from disk and project them. Save this collection of embeddings and their projections for easier working at a later stages."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2023-04-21 14:56:22 [INFO]: loaded 587540 transformed embeddings\n"
]
}
],
"source": [
"from sklearn import decomposition\n",
"\n",
"frame_embeddings: list[FrameEmbedding] = []\n",
"\n",
2023-04-13 13:12:50 +02:00
"if os.path.exists(transformed_embedding_pcl):\n",
" with open(transformed_embedding_pcl, 'rb') as fp:\n",
" frame_embeddings = pickle.load(fp)\n",
" logger.info(f'loaded {len(frame_embeddings)} transformed embeddings')\n",
"else:\n",
2023-04-13 13:12:50 +02:00
" if os.path.exists(orig_embedding_pcl):\n",
" with open(orig_embedding_pcl, 'rb') as fp:\n",
" frame_embeddings = pickle.load(fp)\n",
" logger.info(f'loaded {len(frame_embeddings)} embeddings')\n",
" else:\n",
" for pattern in tqdm(img_seqs):\n",
" for seq_path in glob.glob(os.path.join(result_path, pattern)):\n",
" for i, frame_path in tqdm(enumerate(glob.iglob(f\"{seq_path}/*-*.pcl\"))):\n",
" # if i%2 == 1:\n",
" # # TODO skip 50% for now\n",
" # continue\n",
" with open(frame_path, 'rb') as fp:\n",
" tracker_embedding = pickle.load(fp)\n",
" fe = FrameEmbedding.from_tracker_embedding(frame_path, tracker_embedding)\n",
" frame_embeddings.append(fe)\n",
"\n",
" logger.info(f'loaded {len(frame_embeddings)} embeddings')\n",
"\n",
" with open(orig_embedding_pcl, 'wb') as fp:\n",
" logger.info(f'saved all loaded embeddings embeddings')\n",
" pickle.dump(frame_embeddings, fp)\n",
"\n",
" \n",
" logger.info(f'transform using PCA')\n",
" pca = decomposition.PCA(n_components=2)\n",
" pca_embeddings = pca.fit_transform([e.embedding for e in frame_embeddings])\n",
" \n",
" with open(pca_pcl, 'wb') as fp:\n",
" pickle.dump(pca, fp)\n",
" logger.info(f'saved PCA reducer {pca_pcl=}')\n",
" \n",
" for i, e in enumerate(pca_embeddings):\n",
" frame_embeddings[i].pca = e\n",
"\n",
" \n",
" logger.info(f'transform using UMAP')\n",
" reducer = umap.UMAP(n_components=2)\n",
" umap_embeddings = reducer.fit_transform([e.embedding for e in frame_embeddings])\n",
" with open(umap_pcl, 'wb') as fp:\n",
" pickle.dump(reducer, fp)\n",
" logger.info(f'saved umap reducer {umap_pcl=}')\n",
" \n",
" for i, e in enumerate(umap_embeddings):\n",
" frame_embeddings[i].umap = e\n",
" \n",
2023-04-13 13:12:50 +02:00
" with open(transformed_embedding_pcl, 'wb') as fp:\n",
" logger.info(f'saved transformed embeddings')\n",
" pickle.dump(frame_embeddings, fp)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"\n",
"# print(embeddings)\n",
"umap_embeddings = np.array([e.umap for e in frame_embeddings])\n",
"pca_embeddings = np.array([e.pca for e in frame_embeddings])\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
"\n",
"import base64\n",
"import cv2\n",
"\n",
"\n",
"def b64_image_files(frame_embeddings: list[FrameEmbedding]):\n",
" urls = []\n",
" for i, fe in enumerate(frame_embeddings):\n",
" im = cv2.imread(fe.img_filename)\n",
" pic_width = int(im.shape[1] * .3)\n",
" pic_height = int(im.shape[0] * .3)\n",
" new_dimension = (pic_width, pic_height)\n",
" try:\n",
" im = cv2.resize(im, new_dimension)\n",
" _, byte_data = cv2.imencode('.png', im) \n",
" except Exception as e:\n",
" print(i, fe.img_filename, e)\n",
" \n",
" url = 'data:image/png;base64,' + base64.b64encode(byte_data).decode('utf-8')\n",
" urls.append(url)\n",
" return urls"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
" \n",
"# source = ColumnDataSource(data={'x': embeddings[:, 0], 'y': embeddings[:, 1], 'b64': b64_image_files(frame_embeddings), 'fn': [e.img_filename for e in frame_embeddings] })\n",
"source = ColumnDataSource(data={\n",
" 'x': umap_embeddings[:, 0], 'y': umap_embeddings[:, 1], \n",
" 'pca_x': pca_embeddings[:, 0], 'pca_y': pca_embeddings[:, 1],\n",
" 'fn': [e.img_filename for e in frame_embeddings]\n",
" })\n"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"# umap_subset = np.random.choice(umap_embeddings, int(len(umap_embeddings) * .1))\n",
"# pca_subset = np.random.choice(pca_embeddings, int(len(pca_embeddings) * .1))\n",
"# chosen_idx = np.random.choice(len(umap_embeddings), replace=False, size=50)\n",
"# df_trimmed = source.iloc[chosen_idx]\n"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"\n",
"\n",
"# thanks to https://github.com/jni/blob-explorer/blob/bd9fa676a2a23317e2ea84bdf48b19e71b9e75d4/picker.py#L24\n",
"# who uses base64 encoding, but in VScode we can just use the _path_ to the file\n",
"tooltip = \"\"\"\n",
" <img height=100 src='@fn'>\n",
" \"\"\"\n",
" \n",
"tools1 = [BoxZoomTool(), PanTool(), WheelZoomTool(), ResetTool(), SaveTool()\n",
" #HoverTool(tooltips=tooltip)\n",
" ]\n",
"tools2 = [BoxZoomTool(), PanTool(), WheelZoomTool(), ResetTool(), SaveTool()\n",
" #HoverTool(tooltips=tooltip)\n",
" ]\n"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"\n",
"p_umap = figure(width=800, height=800, title='UMAP projection', \n",
" tools=tools1\n",
" )\n",
"r_umap = p_umap.circle(source=source, size=3, color=\"navy\", alpha=0.01)"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [],
"source": [
"p_pca = figure(width=800, height=800, title='PCA projection', \n",
" tools=tools2\n",
" )\n",
"r_pca = p_pca.circle('pca_x', 'pca_y', source=source, size=5, color=\"red\", alpha=0.01)"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
" <div id=\"ee2388a9-fa32-4933-b000-5deb43dc502e\" data-root-id=\"p1150\" style=\"display: contents;\"></div>\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"(function(root) {\n",
" function embed_document(root) {\n",
" const docs_json = {\"097aec9f-c60c-4475-bb60-8376c641b5c0\":{\"version\":\"3.1.0\",\"title\":\"Bokeh Application\",\"defs\":[],\"roots\":[{\"type\":\"object\",\"name\":\"GridPlot\",\"id\":\"p1150\",\"attributes\":{\"rows\":null,\"cols\":null,\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"p1149\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"ToolProxy\",\"id\":\"p1144\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1006\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1007\",\"attributes\":{\"syncable\":false,\"level\":\"overlay\",\"visible\":false,\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"bottom_units\":\"canvas\",\"top_units\":\"canvas\",\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5}}}},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1012\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1013\",\"attributes\":{\"syncable\":false,\"level\":\"overlay\",\"visible\":false,\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"bottom_units\":\"canvas\",\"top_units\":\"canvas\",\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5}}}}]}},{\"type\":\"object\",\"name\":\"ToolProxy\",\"id\":\"p1145\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1008\"},{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1014\"}]}},{\"type\":\"object\",\"name\":\"ToolProxy\",\"id\":\"p1146\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1009\"},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1015\"}]}},{\"type\":\"object\",\"name\":\"ToolProxy\",\"id\":\"p1147\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1010\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1016\"}]}},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"p1148\"}]}},\"children\":[[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"p1018\",\"attributes\":{\"width\":800,\"height\":800,\"x_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"p1019\"},\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"p1020\"},\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1032\"},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1034\"},\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"p1021\",\"attributes\":{\"text\":\"UMAP projection\"}},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1063\",\"attributes\":{\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1003\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1004\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1005\"},\"data\":{\"type\":\"map\",\"entries\":[[\"x\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"be47QY4D4EANlEJB/OQ7QZ7pREGJoN9AqAM/QV9xP0H+aaBAj6fFQB3FPkHLzYZBG5w1Qd6KqMCeVyzAeeFMwJYUMcARLDpB8/5gQb59Uj5XAS3Am5HTQOjNw0AZvttAClVMwBBYOUGlWAI/eoZDQXLIOUFDNkNB8dnoQG5KP0HPPTlBYt8xQZThQUEXGkNBjsemwC9bq0CVij1B7dVBwM+tCcCSdTjA5STgwLL/jEHAeDlBgWc7QXk7y0BRv9/AK5hBwObZ6EA3QT9BjEasQOTpm0BpyVA+43EpwIzLNkEYUThBII9FQUwtQkGTM5tAun7JQAWWLkEr3jtBSzw4QTJ+4UDsED1B4C1CQaqOQ0G69D5BNTuOQd6FPUHDNT9BIORAQXcygT6jITBBp57hQHMEOkEGRS9BVjc9QS5boEATPI5BeF42Qbn2OUEmzS5BrKk5QQ0iL0GGIDlBrgFBQVlmMkHY4ptAbfovwI8pqcCnBUFBikKmwAxaMkEKg0JB4VJDQX8dP0G50aBAXz2OQS3vej7ini/A0y44QQ9ZMEGsKzlBFVgKwP1axkA3EJ1AoSkvQex54EDMfjDA1pCgQAZtQkGl0QnAe5o4QQVGOUGK2O3Api05QVVkM0EDXTtBkcyGQfmqQkFQzTtB2ttJvyCRQUHYmTlBU5lLwPOB4EBie0JB9mo7QVMhP0GYIZBAZTsDP6owMEHf0d1A9go5QfG/P0FakuFAaCo/QQw3PUE2k+BAv/hRwBOyKcC1vd/AsvE3QVcLrECCw2I93c/WwHy/4EDe66pAY3sFQahEkEBK6zlBm/M8Qc/cLMDXICzAIJFBQdZnPUGAVQrAFpRgQXFUOUG+kD9B7BY/QTwnK8BuUT9BSLMGQdHFhkG92y9B+tpBQXP7QUHusptAlmXVQBhzMkEn5e3A/3cpQeF7dj5Ch0NB
" const render_items = [{\"docid\":\"097aec9f-c60c-4475-bb60-8376c641b5c0\",\"roots\":{\"p1150\":\"ee2388a9-fa32-4933-b000-5deb43dc502e\"},\"root_ids\":[\"p1150\"],\"notebook_comms_target\":\"p1176\"}];\n",
" root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" embed_document(root);\n",
" } else {\n",
" let attempts = 0;\n",
" const timer = setInterval(function(root) {\n",
" if (root.Bokeh !== undefined) {\n",
" clearInterval(timer);\n",
" embed_document(root);\n",
" } else {\n",
" attempts++;\n",
" if (attempts > 100) {\n",
" clearInterval(timer);\n",
" console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
" }\n",
" }\n",
" }, 10, root)\n",
" }\n",
"})(window);"
],
"application/vnd.bokehjs_exec.v0+json": ""
},
"metadata": {
"application/vnd.bokehjs_exec.v0+json": {
"id": "p1150"
}
},
"output_type": "display_data"
}
],
"source": [
"handle = show(gridplot([[p_umap, p_pca]]), notebook_handle=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Generate a grid images out of the projections\n",
"\n",
"Now that there are individual points, we can perheaps better make sense of patterns if we see all points at once. As this is virtually impossible, we can try rendering a grid, with images on it. For each field on the grid, try to find the point closest to the center, and draw that image."
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [],
"source": [
"from scipy import spatial"
]
},
{
"cell_type": "code",
"execution_count": 36,
2023-04-13 13:12:50 +02:00
"metadata": {},
"outputs": [],
"source": [
"\n",
"class GridPosition(TypedDict):\n",
" pos: tuple[int,int]\n",
" distance: float\n",
" frame_embedding: FrameEmbedding"
]
},
{
"cell_type": "code",
"execution_count": 37,
2023-04-13 13:12:50 +02:00
"metadata": {},
"outputs": [],
"source": [
"import cv2\n",
"# resize and pad from https://stackoverflow.com/a/44724368 (alkasm)\n",
2023-04-13 13:12:50 +02:00
"def resizeAndPad(img, size, padColor=0):\n",
" \n",
2023-04-13 13:12:50 +02:00
" h, w = img.shape[:2]\n",
" sh, sw = size\n",
"\n",
" # interpolation method\n",
" if h > sh or w > sw: # shrinking image\n",
" interp = cv2.INTER_AREA\n",
" else: # stretching image\n",
" interp = cv2.INTER_CUBIC\n",
"\n",
" # aspect ratio of image\n",
" aspect = w/h # if on Python 2, you might need to cast as a float: float(w)/h\n",
"\n",
" # compute scaling and pad sizing\n",
" if aspect > 1: # horizontal image\n",
" new_w = sw\n",
" new_h = np.round(new_w/aspect).astype(int)\n",
" pad_vert = (sh-new_h)/2\n",
" pad_top, pad_bot = np.floor(pad_vert).astype(int), np.ceil(pad_vert).astype(int)\n",
" pad_left, pad_right = 0, 0\n",
" elif aspect < 1: # vertical image\n",
" new_h = sh\n",
" new_w = np.round(new_h*aspect).astype(int)\n",
" pad_horz = (sw-new_w)/2\n",
" pad_left, pad_right = np.floor(pad_horz).astype(int), np.ceil(pad_horz).astype(int)\n",
" pad_top, pad_bot = 0, 0\n",
" else: # square image\n",
" new_h, new_w = sh, sw\n",
" pad_left, pad_right, pad_top, pad_bot = 0, 0, 0, 0\n",
"\n",
" # set pad color\n",
" if len(img.shape) == 3 and not isinstance(padColor, (list, tuple, np.ndarray)): # color image but only one color provided\n",
" padColor = [padColor]*3\n",
"\n",
" # scale and pad\n",
" scaled_img = cv2.resize(img, (new_w, new_h), interpolation=interp)\n",
" scaled_img = cv2.copyMakeBorder(scaled_img, pad_top, pad_bot, pad_left, pad_right, borderType=cv2.BORDER_CONSTANT, value=padColor)\n",
"\n",
" return scaled_img"
]
},
{
"cell_type": "code",
"execution_count": 38,
2023-04-13 13:12:50 +02:00
"metadata": {},
"outputs": [],
"source": [
"def projection_to_grid(grid_items, points, frame_embeddings: list[FrameEmbedding]):\n",
" # create a KDTree for fast searching of nearest points\n",
" spatial_tree = spatial.KDTree(points)\n",
"\n",
" min_x = min(points[:,0])\n",
" max_x = max(points[:,0])\n",
" min_y = min(points[:,1])\n",
" max_y = max(points[:,1])\n",
" \n",
" print(f\"axes from x={min_x}-{max_x} and y={min_y}-{max_y}\")\n",
2023-04-13 13:12:50 +02:00
"\n",
" #initialize empty\n",
" # grid = [None]*(grid_items * grid_items)\n",
" grid: list[GridPosition] = []\n",
"\n",
"\n",
" # find the points closest to the grid centroids\n",
" for ix in range(grid_items):\n",
" embedding_x = (ix+0.5) / grid_items * (max_x - min_x) + min_x\n",
"\n",
" for iy in range(grid_items):\n",
" embedding_y = (iy+0.5) / grid_items * (max_y - min_y) + min_y\n",
"\n",
" distance, index = spatial_tree.query([embedding_x, embedding_y])\n",
" # print(distance, frame_embeddings[index].img_filename)\n",
" grid_index = ix * grid_items + iy\n",
" gp = GridPosition(pos=(ix, iy), distance=distance, frame_embedding=frame_embeddings[index])\n",
" grid.append(gp)\n",
"\n",
"\n",
" print(f'{len(grid)} items. Sort')\n",
" grid.sort(key=lambda k: k['distance']) \n",
" \n",
" # remove duplicate closest points based on distance\n",
" drawn_embeddings = set()\n",
" items_to_draw: list[GridPosition] = []\n",
" for point in grid:\n",
" if point['frame_embedding'].img_filename not in drawn_embeddings:\n",
" drawn_embeddings.add(point['frame_embedding'].img_filename)\n",
" items_to_draw.append(point)\n",
"\n",
" return items_to_draw"
]
},
{
"cell_type": "code",
"execution_count": 39,
2023-04-13 13:12:50 +02:00
"metadata": {},
"outputs": [],
"source": [
"\n",
"bgcolors = [\n",
" ('MOT16', [255, 0, 0]),\n",
" ('CaltechPedestrians', [0, 255, 0]),\n",
" ('PRW', [0, 0, 255]),\n",
" ('CUHK-SYSU', [255, 255, 0]),\n",
" ('CityScapes', [0, 255, 255]),\n",
"]\n",
"\n",
"def draw_grid(grid_size, items_to_draw: list[GridPosition], colored=True):\n",
2023-04-13 13:12:50 +02:00
" grid_items = max([max(p['pos']) for p in items_to_draw])+1\n",
" canvas = np.zeros((grid_size * grid_items, grid_size*grid_items, 3), np.uint8)\n",
" for point in items_to_draw:\n",
" if colored:\n",
" try:\n",
" color_idx = [k[0] in point['frame_embedding'].img_filename for k in bgcolors].index(True)\n",
" color = bgcolors[color_idx][1]\n",
" except ValueError:\n",
" color = [0,0,0]\n",
" else:\n",
" color = [0,0,0]\n",
" \n",
2023-04-13 13:12:50 +02:00
" img = cv2.imread(point['frame_embedding'].img_filename)\n",
" img = resizeAndPad(img, (grid_size, grid_size), color)\n",
2023-04-13 13:12:50 +02:00
" iy = point['pos'][1]\n",
" ix = point['pos'][0]\n",
"\n",
" y = grid_size*iy\n",
" x = grid_size*ix\n",
" canvas[x:x+grid_size,y:y+grid_size] = img\n",
" return canvas"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [],
"source": [
2023-04-13 13:12:50 +02:00
"from matplotlib import pyplot as plt\n",
"from PIL import Image\n",
"\n",
"def show_and_save(cv_img, fn):\n",
" # Convert for consumption by matplotlib or Pillow\n",
" image = cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB)\n",
"\n",
" # Converts from one colour space to the other. this is needed as RGB\n",
" # is not the default colour space for OpenCV\n",
" plt.imshow(image)\n",
" plt.show()\n",
" im = Image.fromarray(image)\n",
" # im = im.resize((1500,1500))\n",
2023-04-13 14:21:33 +02:00
" im.save(fn)\n",
" im.resize((1000, 1000)).save(fn[:-4] + '-small.png')"
2023-04-13 13:12:50 +02:00
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"PCA reduces dimensions in a linear fasion. Thus this should stay truer to the values as they are embedded."
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"axes from x=-0.7404562273373906-0.8220491850139571 and y=-0.7506800859090537-0.7937380525198489\n",
"22500 items. Sort\n"
]
}
],
"source": [
"\n",
"grid_points = projection_to_grid(150, pca_embeddings, frame_embeddings)"
]
},
{
"cell_type": "code",
2023-04-13 14:21:33 +02:00
"execution_count": 98,
"metadata": {},
"outputs": [
2023-04-13 13:12:50 +02:00
{
"name": "stdout",
"output_type": "stream",
"text": [
"22500 items. Sort\n"
]
},
{
"data": {
2023-04-13 13:12:50 +02:00
"image/png": "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
"text/plain": [
2023-04-13 13:12:50 +02:00
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
2023-04-13 13:12:50 +02:00
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"\n",
"# print(['CUHK-SYSU' in p['frame_embedding'].img_filename for p in grid_points])\n",
"canvas = draw_grid(60, grid_points, False)\n",
"show_and_save(canvas, os.path.join(result_path, 'pca_plain.png'))\n",
"\n",
"canvas = draw_grid(60, grid_points, True)\n",
"for i, k in enumerate(bgcolors):\n",
" dataset, color = k\n",
" cv2.putText(canvas, dataset, (100, 100*i+100), cv2.FONT_HERSHEY_DUPLEX, 2, color, 2)\n",
"show_and_save(canvas, os.path.join(result_path, 'pca_color.png'))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Large versions are saved [without colors](OUT/embedding_test/pca_plain.png) and [with colors](OUT/embedding_test/pca_color.png). [Note, these are _big_ image files]"
]
},
{
2023-04-13 13:12:50 +02:00
"cell_type": "markdown",
"metadata": {},
"source": [
2023-04-13 13:12:50 +02:00
"UMAP is a clustering algorithm ,which tries to confirm to local and global structures. Being similar to T-SNE it is a visualisation/exploratory method, and thus it shoul not be interpreted too strict."
]
},
{
"cell_type": "code",
2023-04-13 14:21:33 +02:00
"execution_count": 99,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
2023-04-13 13:12:50 +02:00
"22500 items. Sort\n"
]
2023-04-13 13:12:50 +02:00
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAbIAAAGiCAYAAACCpUOHAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOy9dbgl53Em/nb36cN4mXlm7jCjmNmSLKPMbMewjr3JxpvEIf/Wu3HsgO2sE5PMlkmymDUajYY0zHcuMx/m0/D7o6q/c++cGUtOvLLGOfU8euaqu0/31193V31V9dZbkmmaJspSlrKUpSxluURF/n0PoCxlKUtZylKW/4yUDVlZylKWspTlkpayIStLWcpSlrJc0lI2ZGUpS1nKUpZLWsqGrCxlKUtZynJJS9mQlaUsZSlLWS5pKRuyspSlLGUpyyUtZUNWlrKUpSxluaSlbMjKUpaylKUsl7SUDVlZylKWspTlkpbXtSH7+te/jra2NjidTmzduhUHDhz4fQ+pLGUpS1nK8jqT160hu//++/GZz3wGf/VXf4XDhw9j7dq1uOmmmzAzM/P7HlpZylKWspTldSTS65U0eOvWrdi8eTO+9rWvAQAMw0BzczM++clP4s/+7M9+z6MrS1nKUpayvF7E9vsewIUkn8/j0KFD+NznPie2ybKM66+/Hnv37r3gb3K5HHK5nPh/wzAQDodRWVkJSZL+n4+5LGUpS1nK8rsT0zSRSCTQ0NAAWf7NwcPXpSGbm5uDruuora1dtL22thZnz5694G+++MUv4m/+5m9ei+GVpSxlKUtZXiMZHR1FU1PTbzzmdZsj+23lc5/7HGKxmPhvZGTk9z2ksrxO5aYrtwMArt6yBlWVVRc8xuV04KYrd9Bxl22B2+2+4HFOpxPr1q0HAKxauRwAoKp2bN28BQDw1je9CwAQ8IfQ3Egf41vf+n4AQG1dLRxOJwBg3aaNFx1vVXUNWtrbYbOr8Hi9Fz3u/R98P9asWY2rr78F6zZsXbRPURQsX07jW7fm4te69uqr0NhYDwC48Q1vBACEqmouevxCuWzzStgUUinNrZ0AgPe9+wOv6rdlKcvFxOfzveIxr0tDVlVVBUVRMD09vWj79PQ06urqLvgbh8MBv98v/gsEAq/FUMtyCUp7azMAoKGpCU77hYMSPq8H73vTLQCAj77zLvh9ngse5/F4cOVllwMAaisrAAAOuwqfgwzUhm7aJkkmDEMHAKh++jBb27vg5/e0oXPFRcfrD1UhGY/D4XAjGKy+6HHf+dZ3cPz4Cex85nEcPbx/0T5JVuB2qACAo8cPXfQc6XQa0VgCADA7MQYAiMy9OoDVR95+F1SV5nN0uB8A0F5z4QVAWcryauXVpIZel4bMbrdj48aNePbZZ8U2wzDw7LPPYvv27b/HkZXlUhWf1w2HnRQ5HC4AwFwmD/08qJPT6QAA5PIFDE+GAQA9gzO4GCZKURQ0tpKnVdnSAADQdR2RdBwA8MyBUQBAQTOQyuQBALJCvy0U8jAMOm9NFRk0t9tV8uGmEnHoJqDIgKbnS8ZQU/PKHpMiSUhm9Ivud7toTtauW4GO9hYAQHtLHd/jq8tADM9GYEKCLElwu8iQnx6Yf1W/DQYuvupWbTYxJ94LeMYe74UXGWX5ryOvS0MGAJ/5zGfwzW9+E9/73vdw5swZfOxjH0MqlcL73ve+3/fQynIJyh3XXYGNq8nr2by6GwDw3DMvYOq8co6bbroFkiQhnc7AlO0AAJ/bhRh7KedLNBpFYxV5XXUgsJEkSagO0bYXdj4CAEinE4jFyDDKw2cAAIoiQ9fJuGSz9Nub77odPv9ipT4zNY5YJIxEPI6ZqYlF+2w2G376q4de8f5z+RwGBs5ddP9b3/xmGu+L+zE0RMb3icefBgAsXbEakvTKqmJpcwO0QgEVQR/+1598BADwy4d/8Yq/A4C//O9/fNF9G9atQEUoCAD47Mc/VrL/fR8r3VaW/1ryujVkb33rW/EP//AP+PznP49169bh6NGjeOKJJ0oAIGUpy6uRiVga05EYAGDnyy8DALRCAaZhLDrO6yKPzDBNeF3kweUKOoyLeGSmaSKSSgMA1qy7AgAgScDp0z0ACIFrHWd5dXtP9ohr2GwKX4PG4XK7ASz2yEzTBPj353uGhmni0QefelVzUCgULrovZdC9arqJgqYBANKZDACgvqYCsvzK4Z3p+ShMk8KYLS1NfM1SD/JCMjiZuui+eFqH3U6LioRW+hw++sH3v6prlOUPV163hgwAPvGJT2B4eBi5XA779+/H1q1bX/lHZfkvLy2tnbh8BwE1brxiGwBgYHgM4XAUAOBS/XRcc6vI6dxy3XUAgIOHD8M0TRiGgWNDlKP9/s8fgcbK3ZKbrr8RAIW8f/0geURnBsjTyuXySBUyFx3f5h00pqGBASQT5On1nqC81bGDh5HNLv5tc2srGhobLniuD77//XjLW28FAHzmk58q2b9h42YAQF1DAzZs3nDRMdVzaNM0DdhVMhrrN6wDAMRTxbKWpa2tAIC2hsaSczgVA7JNQTKVxjd/8uBFr2WJIsuoqqwEAAT9tIBwOF3w+2ksO7ZfBgCYnppANEqLEBfoOVx59Q5UVAYBAA8+9MtXvFZZ/rDldW3IylKW/4isWNaJa66gRY+/th0AMDI4iEg0CgBoriVDVh2sEvUpOzYSoq/nXC8A8oKsnNaZc6dhnOe5herpvLqu4xnO5W7sXAoA0HQd83Phi47vzIsvAQDCc3PIstdz8shR+vfoCeRzi72YuroatFZfGOTU0FKLX/zsUQDA8nWrSvZXVBA4pKO5FVdcefH8cpi9VVmSyKUEsP1yArEEA37YbOSx6TkyJMoF0m2NDY1QJAmZbA6PP/vSRa8lRJJgs1NuzmcnT8vtcMDlojzYnddtorGFI8hkswAAp5dCtstWrERdHRn3xpbuV75WWf6gpWzIynJJi93hgJch6da/AZ9DgAMq/AQ6kGWFlDSAI72ktHVI0BntcbCHtnk8ReCAz0fK21KsC0U3i5+Ow07exGS+9HMKMirRZrPB4aDjGrde3DO6kFRXhZAzNSiKgqqK4KJ9L+8/jtU7yAiv3bCl5LdVFXT9WDqBkdP9F71Glg11KOiFyuFOF4cTHU4bDJP3N1PIsLqrU/zWxcCOSE4vAapYQBRZltHQsNirNE0gr9F5T42TQZdtqgifPr53qGScI+OEpNRyWeElV/psPA7XRe/vdy1evw92fp5l+f1L2ZCV5ZKWy7ddjj/7LIXUdlxxAwBg157DePK5XQCA73z/BwCAQCAEj4cM0rquEACgYBgwWUFv7KZtN95wk1DGCUb5vfn2W0uuW+MmJSZJEtauI88hk46UHPf+9xA4qbqmDt0rVwIANq1Z/9vd4441aGurRUtjLT505xsW7Xvfu94Jt0afsXkBfgNdp3s5c+o0Hnry4rm0B+//EQDA4XDDzShAnQ1DOJyAk5W2xCE+NU2GR1EUbN68DgAwEgnj/AzW//nSlwGQV/fnf/6Xi/aZpgE3lz90VJLx9Lk9kBVaQOze+WjJOLsaKUf+/e/9GL3sPT/wcwLU3H7nna/IAPG7kne+5y3oXr36NblWWV5ZyoasLJe0NDUEkIwRUGBFK4XRXE4bKoLkiVirdnMBgKJnJEp/GAZMhr+fGKBQoM+tiuPsrBTnY6UgicF4is8LJLK03yjkSo5T2Ftz2FUoCinrZPLiwIYLyeTkPLwS/fZaNoaWfPcHP8RDjz8JANh1gXBeNk9AFMMwoJ8XHl0oBQal5DJpuN1kyDw8Z411FcJAzWp0r3HD2mKioSYIAJiIaOfjVPDrX9PYkqk0fvXw44v2maaJgk5jskodbDBgVy3gyeK8JACMz1NZg67pwnNLpem3BS3zmtHRjY3NoJC9eB60LK+tlA1ZWS5p2bP/EF7cR/ybZ3qJvmxmdg4HDh5ddJwiS7AAfz72ppwuJyxUuZ/DYyvXNMHhILBDJUO+w5FJcZ4rtxNQY1kFeSsSgA0r2gAAU/OlhcOPPUxAEKOQg5Yjo2Jxgra1tZVA7e98y91Y0t0Nm82GG26
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
2023-04-13 13:12:50 +02:00
"grid_points = projection_to_grid(150, umap_embeddings, frame_embeddings)\n",
"canvas = draw_grid(60, grid_points, False)\n",
"show_and_save(canvas, os.path.join(result_path, 'umap_plain.png'))\n",
"\n",
"canvas = draw_grid(60, grid_points, True)\n",
"for i, k in enumerate(bgcolors):\n",
" dataset, color = k\n",
" cv2.putText(canvas, dataset, (100, 100*i+100), cv2.FONT_HERSHEY_DUPLEX, 2, color, 2)\n",
"show_and_save(canvas, os.path.join(result_path, 'umap_color.png'))"
]
},
2023-04-13 13:12:50 +02:00
{
"cell_type": "markdown",
2023-04-13 13:12:50 +02:00
"metadata": {},
"source": [
"Large versions are saved [without colors](OUT/embedding_test/umap_plain.png) and [with colors](OUT/embedding_test/umap_color.png). [Note, these are _big_ image files]"
]
2023-04-13 13:12:50 +02:00
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "trm",
"language": "python",
"name": "trm"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.8"
},
"vscode": {
"interpreter": {
"hash": "dc02836f3be4f05ab358b62045dee0ee510294e31b25a582b38257a3269c0c99"
}
}
},
"nbformat": 4,
"nbformat_minor": 4
}