{"id":2265,"date":"2020-11-20T12:00:00","date_gmt":"2020-11-20T20:00:00","guid":{"rendered":"https:\/\/live-cometml.pantheonsite.io\/blog\/custom-visualizations-to-debug-object-detection-models\/"},"modified":"2020-11-20T12:00:00","modified_gmt":"2020-11-20T20:00:00","slug":"custom-visualizations-to-debug-object-detection-models","status":"publish","type":"post","link":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/","title":{"rendered":"Using Custom Visualizations to Debug Object Detection Models"},"content":{"rendered":"\n<p>In this post, we will showcase a Custom Panel dedicated to debugging object detection models.<\/p>\n\n\n\n<p>We will use the Penn-Fudan Pedestrian Detection dataset, along with a Faster-RCNN model, with a Resnet50 backbone, that has been pre-trained on the <a href=\"https:\/\/cocodataset.org\/\">MS COCO<\/a> dataset.<\/p>\n\n\n\n<p>All code for this post can be found in this <a href=\"https:\/\/colab.research.google.com\/drive\/17EA84SjonXcENr7zxYYimkSUas3sdRMa?authuser=1#scrollTo=u9vo2fWyoLlX\">Colab Notebook<\/a>. The logged experiments can be found <a href=\"https:\/\/www.comet.com\/team-comet-ml\/object-detection\/view\/McCPFN4CWxc18US233X1T05a7\">here<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Loading the Data and Setting up the Model<\/h2>\n\n\n\n<p>Let&#8217;s start by downloading the data<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># download the Penn-Fudan dataset\n!wget https:\/\/www.cis.upenn.edu\/~jshi\/ped_html\/PennFudanPed.zip .\n# extract it in the current folder\n!unzip PennFudanPed.zip<\/code><\/pre>\n\n\n\n<p>Now let&#8217;s define a dataset class that will allow us to easily load the images in the dataset<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport numpy as np\nimport torch\nimport torch.utils.data\nfrom PIL import Image\n\nclass PennFudanDataset(torch.utils.data.Dataset):\n    def __init__(self, root, transforms=None):\n        self.root = root\n        self.transforms = transforms\n        # load all image files, sorting them to\n        # ensure that they are aligned\n        self.imgs = list(sorted(os.listdir(os.path.join(root, \"PNGImages\"))))\n        self.masks = list(sorted(os.listdir(os.path.join(root, \"PedMasks\"))))\n\n    def __getitem__(self, idx):\n        # load images ad masks\n        img_path = os.path.join(self.root, \"PNGImages\", self.imgs[idx])\n        mask_path = os.path.join(self.root, \"PedMasks\", self.masks[idx])\n        img = Image.open(img_path).convert(\"RGB\")\n        # note that we haven't converted the mask to RGB,\n        # because each color corresponds to a different instance\n        # with 0 being background\n        mask = Image.open(mask_path)\n\n        mask = np.array(mask)\n        # instances are encoded as different colors\n        obj_ids = np.unique(mask)\n        # first id is the background, so remove it\n        obj_ids = obj_ids[1:]\n\n        # split the color-encoded mask into a set\n        # of binary masks\n        masks = mask == obj_ids[:, None, None]\n\n        # get bounding box coordinates for each mask\n        num_objs = len(obj_ids)\n        boxes = []\n        for i in range(num_objs):\n            pos = np.where(masks[i])\n            xmin = np.min(pos[1])\n            xmax = np.max(pos[1])\n            ymin = np.min(pos[0])\n            ymax = np.max(pos[0])\n            boxes.append([xmin, ymin, xmax, ymax])\n\n        boxes = torch.as_tensor(boxes, dtype=torch.float32)\n        # there is only one class\n        labels = torch.ones((num_objs,), dtype=torch.int64)\n        masks = torch.as_tensor(masks, dtype=torch.uint8)\n\n        image_id = torch.tensor([idx])\n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n        # suppose all instances are not crowd\n        iscrowd = torch.zeros((num_objs,), dtype=torch.int64)\n\n        target = {}\n        target[\"boxes\"] = boxes\n        target[\"labels\"] = labels\n        target[\"masks\"] = masks\n        target[\"image_id\"] = image_id\n        target[\"area\"] = area\n        target[\"iscrowd\"] = iscrowd\n\n        if self.transforms is not None:\n            img = self.transforms(img)\n\n        return img, target\n\n    def __len__(self):\n        return len(self.imgs)<\/code><\/pre>\n\n\n\n<p>Next, we&#8217;ll define some basic preprocessing operations that will turn our image data into Torch Tensors:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import torch, torchvision\nfrom torchvision import datasets, transforms\n\npreprocess = transforms.Compose([\n  transforms.ToTensor(),\n])\ndataset = PennFudanDataset('.\/PennFudanPed', transforms=preprocess)<\/code><\/pre>\n\n\n\n<p>Finally, lets load in our model and start making predictions. Every time we make a prediction, we&#8217;re going to log the image to Comet. You will find these images under the Graphics tab of the experiment.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True)\nmodel.eval()\n\nimg_ids = [i for i in range(5)]\nlabels = []\npredictions = []\n\nfor img_id in img_ids:\n  img, label = dataset[img_id]\n\n  labels.append(label)\n  with torch.no_grad():\n    prediction = model([img])\n    predictions.append(prediction[0])\n\n  experiment.log_image(image_data=transforms.ToPILImage()(img), name=str(img_id))<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Logging Bounding Box Predictions<\/h2>\n\n\n\n<p>In order to use the Bounding Box panel, we will need to log our predictions in a particular format as a JSON file. The following snippet will convert a list of image ids, predictions, and labels into the required JSON format for plotting.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>def format_predictions_and_labels(img_ids, predictions, labels, label_map):\n  data = {}\n\n  for idx, img_id in enumerate(img_ids):\n      prediction = predictions[idx]\n      label = labels[idx]\n\n      predicted_boxes = prediction[\"boxes\"].numpy().tolist()\n      predicted_scores = prediction[\"scores\"].numpy().tolist()\n      predicted_classes = prediction[\"labels\"].numpy().tolist()\n\n      label_boxes =  label[\"boxes\"].numpy().tolist()\n\n      data.setdefault(img_id, [])\n      for label_box in label_boxes:\n        x, y, x2, y2 = label_box\n        data[img_id].append({\n            \"label\": \"ground-truth\",\n            \"score\": 100,\n            \"box\": {\"x\": x, \"y\": y, \"x2\": x2, \"y2\": y2},\n        })\n\n      for predicted_box, predicted_score, predicted_class in zip(predicted_boxes, predicted_scores, predicted_classes):\n        x, y, x2, y2 = predicted_box\n        data[img_id].append({\n            \"label\": label_map[predicted_class - 1],\n            \"box\": {\"x\": x, \"y\": y, \"x2\": x2, \"y2\": y2},\n            \"score\": predicted_score * 100\n        })\n\n  return data<\/code><\/pre>\n\n\n\n<p>Lets format our predictions, and log them to Comet:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>metadata = format_predictions_and_labels(img_ids, predictions, labels)\nexperiment.log_asset_data(data, \"image-metadata.json\")<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Viewing Model Predictions in the Custom Panel<\/h2>\n\n\n\n<p>You can find the &#8216;Bounding Boxes&#8217; custom panel in the Public Panels Galley. Once added, it becomes easy to view predictions from the model, as well as filter predictions out based on the confidence scores.<\/p>\n\n\n\n<p>You can explore this Panel below<\/p>\n\n\n\n<p><iframe loading=\"lazy\" style=\"border: 1px solid #343D4E;\" src=\"https:\/\/www.comet.com\/embedded\/?instanceId=fyXCeEQk8rVtis82rx1b6gh6o&amp;projectId=98601877c81b46a5a94a1db8969cf3b8&amp;templateId=iYymacTAePCdFkhyOSnAMAgKr&amp;viewId=McCPFN4CWxc18US233X1T05a7\" width=\"100%\" height=\"600\" frameborder=\"0\"><\/iframe><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-3844\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/06\/Screen-Shot-2020-11-20-at-11.25.35-AM-1024x500-1.png\" alt=\"\" \/>\n<figcaption>Figure 1. Adding Custom Bounding Boxes Panel<\/figcaption>\n<\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-3841\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/06\/Screen-Shot-2020-11-20-at-10.36.36-AM-2-1024x539-1.png\" alt=\"\" \/>\n<figcaption>Figure 2. Custom Panel for Object Detection (<a href=\"https:\/\/www.comet.com\/team-comet-ml\/object-detection\/view\/McCPFN4CWxc18US233X1T05a7\">link to experiment<\/a>)<\/figcaption>\n<\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" class=\"wp-image-3605\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/06\/Screen-Shot-2020-11-16-at-12.58.11-PM-1024x536-1.png\" alt=\"\" \/>\n<figcaption>Figure 3. Filtered Bounding Box Predictions (<a href=\"https:\/\/www.comet.com\/team-comet-ml\/object-detection\/view\/McCPFN4CWxc18US233X1T05a7\">link to experiment<\/a>)<\/figcaption>\n<\/figure>\n\n\n\n<p>The custom panel allows filtering the detected objects by label, as well as by confidence scores.<\/p>\n\n\n\n<p>Try out other custom panels in Comet&#8217;s <a href=\"https:\/\/www.comet.com\/team-comet-ml\/object-detection\/view\/McCPFN4CWxc18US233X1T05a7#select-panel?gallery-tab=Public\">Panel Gallery<\/a>. Panels are highly customizable, so if you can&#8217;t find the exact visualization that you are looking for, Comet provides the tooling to help you build it yourself! Check out the Panel&#8217;s <a href=\"https:\/\/www.comet.com\/docs\/user-interface\/panels\/\">Documentation<\/a> for more information.<\/p>\n\n\n<hr class=\"wp-block-separator\" \/>\n\n\n<h2 class=\"wp-block-heading\"><em>Want to stay in the loop?\u00a0<a href=\"https:\/\/info.comet.ml\/newsletter-signup\/?utm_campaign=tensorboard-integration&amp;utm_source=blog&amp;utm_medium=CTA\">Subscribe to the Comet Newsletter<\/a>\u00a0for weekly insights and perspective on the latest ML news, projects, and more.<\/em><\/h2>\n","protected":false},"excerpt":{"rendered":"<p>Check out Comet&#8217;s Custom Panel to debug Object Detection Models<\/p>\n","protected":false},"author":1,"featured_media":2269,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"customer_name":"","customer_description":"","customer_industry":"","customer_technologies":"","customer_logo":"","footnotes":""},"categories":[8,9],"tags":[],"coauthors":[128],"class_list":["post-2265","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-comet-community-hub","category-product"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using Custom Visualizations to Debug Object Detection Models - Comet<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using Custom Visualizations to Debug Object Detection Models\" \/>\n<meta property=\"og:description\" content=\"Check out Comet&#039;s Custom Panel to debug Object Detection Models\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/\" \/>\n<meta property=\"og:site_name\" content=\"Comet\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/cometdotml\" \/>\n<meta property=\"article:published_time\" content=\"2020-11-20T20:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/06\/Screen-Shot-2020-11-17-at-10.33.54-AM-1024x493-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"493\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Dhruv Nair\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@Cometml\" \/>\n<meta name=\"twitter:site\" content=\"@Cometml\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Dhruv Nair\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Using Custom Visualizations to Debug Object Detection Models - Comet","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/","og_locale":"en_US","og_type":"article","og_title":"Using Custom Visualizations to Debug Object Detection Models","og_description":"Check out Comet's Custom Panel to debug Object Detection Models","og_url":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/","og_site_name":"Comet","article_publisher":"https:\/\/www.facebook.com\/cometdotml","article_published_time":"2020-11-20T20:00:00+00:00","og_image":[{"width":1024,"height":493,"url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/06\/Screen-Shot-2020-11-17-at-10.33.54-AM-1024x493-1.png","type":"image\/png"}],"author":"Dhruv Nair","twitter_card":"summary_large_image","twitter_creator":"@Cometml","twitter_site":"@Cometml","twitter_misc":{"Written by":"Dhruv Nair","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/#article","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/"},"author":{"name":"engineering@atre.net","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/550ac35e8e821db8064c5bd1f0a04e6b"},"headline":"Using Custom Visualizations to Debug Object Detection Models","datePublished":"2020-11-20T20:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/"},"wordCount":370,"publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/#primaryimage"},"thumbnailUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/06\/Screen-Shot-2020-11-17-at-10.33.54-AM-1024x493-1.png","articleSection":["Comet Community Hub","Product"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/","url":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/","name":"Using Custom Visualizations to Debug Object Detection Models - Comet","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/#primaryimage"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/#primaryimage"},"thumbnailUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/06\/Screen-Shot-2020-11-17-at-10.33.54-AM-1024x493-1.png","datePublished":"2020-11-20T20:00:00+00:00","breadcrumb":{"@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/#primaryimage","url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/06\/Screen-Shot-2020-11-17-at-10.33.54-AM-1024x493-1.png","contentUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2022\/06\/Screen-Shot-2020-11-17-at-10.33.54-AM-1024x493-1.png","width":1024,"height":493,"caption":"model predictions in the custom panel"},{"@type":"BreadcrumbList","@id":"https:\/\/www.comet.com\/site\/blog\/custom-visualizations-to-debug-object-detection-models\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.comet.com\/site\/"},{"@type":"ListItem","position":2,"name":"Using Custom Visualizations to Debug Object Detection Models"}]},{"@type":"WebSite","@id":"https:\/\/www.comet.com\/site\/#website","url":"https:\/\/www.comet.com\/site\/","name":"Comet","description":"Build Better Models Faster","publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.comet.com\/site\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.comet.com\/site\/#organization","name":"Comet ML, Inc.","alternateName":"Comet","url":"https:\/\/www.comet.com\/site\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/","url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","contentUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","width":310,"height":310,"caption":"Comet ML, Inc."},"image":{"@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/cometdotml","https:\/\/x.com\/Cometml","https:\/\/www.youtube.com\/channel\/UCmN63HKvfXSCS-UwVwmK8Hw"]},{"@type":"Person","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/550ac35e8e821db8064c5bd1f0a04e6b","name":"engineering@atre.net","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/image\/027c18177377edf459980f0cfb83706c","url":"https:\/\/secure.gravatar.com\/avatar\/d002a459a297e0d1779329318029aee19868c312b3e1f3c9ec9b3e3add2740de?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d002a459a297e0d1779329318029aee19868c312b3e1f3c9ec9b3e3add2740de?s=96&d=mm&r=g","caption":"engineering@atre.net"},"sameAs":["https:\/\/live-cometml.pantheonsite.io"],"url":"https:\/\/www.comet.com\/site\/blog\/author\/engineeringatre-net\/"}]}},"_links":{"self":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/2265","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/comments?post=2265"}],"version-history":[{"count":0,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/2265\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/media\/2269"}],"wp:attachment":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/media?parent=2265"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/categories?post=2265"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/tags?post=2265"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/coauthors?post=2265"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}