{"info":{"_postman_id":"6aa162c5-cc7e-4789-81c6-aa551fc0cb62","name":"Visualize the MobileNet Model🖼️","description":"<html><head></head><body><p>In this collection we will be using an API I created specially for this workspace. This API for a given image shows what the convolution layers in the MobileNet model [1] identify by implementing GradCam [2] and visualizes those with the Postman Visualizer. This API runs the MobileNet model and implements GradCam using TensorFlow under the hood as shown in greater details in the upcoming sections.</p>\n<h2 id=\"about-the-api📝\">About the API📝</h2>\n<p>This API was deployed on GCP Cloud Functions and is extremely easy to deploy your own such API. All the code required to build this API is open-sourced by me and can be found <a href=\"https://gist.github.com/Rishit-dagli/cb0577d79a2e3c98606b63b934157760\">here</a>. You can simply download this and deploy it to your own Cloud Function with this command:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-sh\">gcloud functions deploy conv_vis --runtime python38 --memory 8196MB --trigger-http --allow-unauthenticated\n</code></pre>\n<p>Or even do this with the Google Cloud GUI.</p>\n<h4 id=\"under-the-hood⚙️\">Under the Hood⚙️</h4>\n<p>Though you already have  the source code, I will quickly show what happens under the hood when you call this API I built:</p>\n<ul>\n<li>Identify query parameters you passed</li>\n<li>Take the image from the query parameters, resize it to <code>(224, 224)</code> and convert it to an array</li>\n<li>Load the MobileNet model and populate it with pre-trained weights on ImageNet</li>\n<li>Implement GradCam in TensorFlow to visualize convolution layers</li>\n<li>Place generated GradCam outputs on top of the original image</li>\n<li>Save this updated image to a Google Cloud bucket with the file name passed in query params</li>\n<li>Return the output image in JSON format</li>\n</ul>\n<h2 id=\"using-the-api✅\">Using the API✅</h2>\n<h4 id=\"endpoint-url\">Endpoint URL</h4>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code>https://us-central1-sound-fastness-257416.cloudfunctions.net\n</code></pre><p>GET <code>/postmanhack</code></p>\n<h4 id=\"request-params\">Request Params</h4>\n<blockquote>\n<p>Be sure to change the collection level variable if you want to try this out with your own image and not directly the request parameter to allow Postman Visualizer to use the image.</p>\n</blockquote>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>image</td>\n<td>URL of the image you put in the model</td>\n</tr>\n<tr>\n<td>destination</td>\n<td>File name of the destination image, remember to use extension (.png , .jpg etc)</td>\n</tr>\n</tbody>\n</table>\n</div><h4 id=\"just-want-to-test-out\">Just want to test out?</h4>\n<p>I got you covered, I have added an example image as the default value for you to try out here are the default values:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Key</th>\n<th>Default Value</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>image</td>\n<td><a href=\"https://i.imgur.com/taUKyu1.jpg\">https://i.imgur.com/taUKyu1.jpg</a></td>\n</tr>\n<tr>\n<td>destination</td>\n<td>A random string</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"using-the-postman-visualizer🎨\">Using the Postman Visualizer🎨</h2>\n<p>Since the API sends us back an image we can easily use the Postman Visualizer to visualize and make sense of the returned image.</p>\n<p><img src=\"https://i.imgur.com/EiYs5N7.png\" alt=\"\"></p>\n<h2 id=\"references📑\">References📑</h2>\n<p>[1] Howard, Andrew G., et al. “MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications.” ArXiv:1704.04861 [Cs], Apr. 2017. arXiv.org, <a href=\"http://arxiv.org/abs/1704.04861\">http://arxiv.org/abs/1704.04861</a>.</p>\n<p>[2] Selvaraju, Ramprasaath R., et al. “Grad-CAM: Visual Explanations from Deep Networks via Gradient-Based Localization.” International Journal of Computer Vision, vol. 128, no. 2, Feb. 2020, pp. 336–59. arXiv.org, doi:<a href=\"https://link.springer.com/article/10.1007/s11263-019-01228-7\">10.1007/s11263-019-01228-7</a>.</p>\n<p>[3] Russakovsky, Olga, et al. “ImageNet Large Scale Visual Recognition Challenge.” ArXiv:1409.0575 [Cs], Jan. 2015. arXiv.org, <a href=\"http://arxiv.org/abs/1409.0575\">http://arxiv.org/abs/1409.0575</a>.</p>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"15031376","collectionId":"6aa162c5-cc7e-4789-81c6-aa551fc0cb62","publishedId":"TzsWtA3q","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"EF5B25"},"publishDate":"2021-07-20T12:12:33.000Z"},"item":[{"name":"Receive Visualizations","event":[{"listen":"test","script":{"id":"252ee11a-3762-436b-b8b2-31659f6a050b","exec":["pm.test(\"Status code is 200\", () => {\r","    pm.response.to.have.status(200);\r","});\r","\r","pm.test(\"Function-Execution-Id header is present\", () => {\r","  pm.response.to.have.header(\"Function-Execution-Id\");\r","});\r","\r","pm.test(\"Make sure reponse was from GCF\", () => {\r","  pm.expect(pm.response.headers.get('Server')).to.eql('Google Frontend');\r","});\r","\r","const schema = {\r","  properties: {\r","    output_image: {type: \"string\"}\r","  }\r","};\r","\r","pm.test('Schema is valid', function() {\r","  pm.response.to.have.jsonSchema(schema);\r","});\r","\r","let final = pm.collectionVariables.get(\"Image URL\")\r","\r","let template = `\r","<html>\r","<head>\r","<style type=\"text/css\">\r","body {\r","  font-family: helvetica, arial, sans-serif;\r","  margin: 2em;\r","  color: #3D3D3D;\r","}\r","\r","h1 {\r","  font-style: italic;\r","  color: #FF6F00;\r","}\r","\r","section {\r","  opacity: 1;\r","  transition: opacity 500ms ease-in-out;\r","}\r","\r",".tg {\r","  border-collapse: collapse;\r","  border-spacing: 0;\r","}\r","\r",".tg td {\r","  border-color: black;\r","  border-style: solid;\r","  border-width: 1px;\r","  font-family: Arial, sans-serif;\r","  font-size: 14px;\r","  overflow: hidden;\r","  padding: 10px 5px;\r","  word-break: normal;\r","}\r","\r",".tg th {\r","  border-color: black;\r","  border-style: solid;\r","  border-width: 1px;\r","  font-family: Arial, sans-serif;\r","  font-size: 14px;\r","  font-weight: normal;\r","  overflow: hidden;\r","  padding: 10px 5px;\r","  word-break: normal;\r","}\r","\r",".tg .tg-0pky {\r","  border-color: inherit;\r","  text-align: left;\r","  vertical-align: top\r","}\r","\r","body {\r","  font-family: helvetica, arial, sans-serif;\r","  margin: 2em;\r","  color: #3D3D3D;\r","}\r","\r","h1 {\r","  font-style: italic;\r","  color: #FF6F00;\r","}\r","\r","section {\r","  opacity: 1;\r","  transition: opacity 500ms ease-in-out;\r","}\r","\r",".tg {\r","  border-collapse: collapse;\r","  border-spacing: 0;\r","}\r","\r",".tg td {\r","  border-color: black;\r","  border-style: solid;\r","  border-width: 1px;\r","  font-family: Arial, sans-serif;\r","  font-size: 14px;\r","  overflow: hidden;\r","  padding: 10px 5px;\r","  word-break: normal;\r","}\r","\r",".tg th {\r","  border-color: black;\r","  border-style: solid;\r","  border-width: 1px;\r","  font-family: Arial, sans-serif;\r","  font-size: 14px;\r","  font-weight: normal;\r","  overflow: hidden;\r","  padding: 10px 5px;\r","  word-break: normal;\r","}\r","\r",".tg .tg-0pky {\r","  border-color: inherit;\r","  text-align: left;\r","  vertical-align: top\r","}\r","\r","thead {\r","  background-color: #F5F5F5;\r","  border\r","}\r","\r","th, th:first-child, th:last-child, td, td:first-child, td:last-child {\r","  padding: 12px 15px;\r","}\r","\r","</style>\r","</head>\r","\r","<body>\r","<div>\r","<h1>Visualize an ML Model</h1>\r","</div>\r","\r","<p>Here we will be passing in an image to the API I built which runs the MobileNet model and implements GradCam with\r","   TensorFlow to allow us to see how this Deep Learning model learns or produce \"visual explanations\". And then uuse \r","   Postman Visualizer to do so. Take a look at the results below🔽</p>\r","\r","<table class=\"tg\">\r","<thead>\r","  <tr>\r","    <th class=\"tg-0pky\"><span style=\"font-weight:bold;color:#FF6F00;text-align:center\">Original Image</span></th>\r","    <th class=\"tg-0pky\"><span style=\"font-weight:bold;color:#FF6F00;text-align:center\">API + Postman Visualizer\r","        </span></th>\r","  </tr>\r","</thead>\r","<tbody>\r","  <tr>\r","    <td class=\"tg-0pky\"><img src = \"{{fin}}\"\r","     width = \"224\"\r","     height = \"224\" /></td>\r","    <td class=\"tg-0pky\"><img src = \"{{res.output_image}}\"\r","     width = \"224\"\r","     height = \"224\" /></td>\r","  </tr>\r","</tbody>\r","</table>\r","</body>\r","</html>\r","`\r","\r","pm.visualizer.set(template, { \r","    res: pm.response.json(),\r","    fin: final\r","})"],"type":"text/javascript"}}],"id":"7d348557-99a6-4977-86d2-3c0b596252ce","protocolProfileBehavior":{"disableBodyPruning":true,"disabledSystemHeaders":{"host":true,"user-agent":true,"accept":true}},"request":{"method":"GET","header":[],"url":"https://us-central1-sound-fastness-257416.cloudfunctions.net/postmanhack?image=https://i.imgur.com/taUKyu1.jpg","description":"<p>To see the comparison visualization between the original and new one, for custom image be sure to change the variable \"Image URL\" with your custom image URL.</p>\n<p>Note: This API is quite compute intensive and since is a personal project, it might take some time to run usually 8 - 15 seconds. Since this is quite intensive and run as a hobby project it may sometimes fail to process a request due to excessive load, please try again.</p>\n","urlObject":{"host":["https://us-central1-sound-fastness-257416.cloudfunctions.net/postmanhack"],"query":[{"description":{"content":"<p>The Image you put in the model</p>\n","type":"text/plain"},"key":"image","value":"https://i.imgur.com/taUKyu1.jpg"},{"disabled":true,"description":{"content":"<p>File name of the destination image, be sure to append it with the extension (.png, .jpg or others)</p>\n","type":"text/plain"},"key":"destination","value":"test-image-yourname.png"}],"variable":[]}},"response":[{"id":"61859b6d-4a50-4dfe-9bf9-816471759550","name":"Receive Visualizations","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://us-central1-sound-fastness-257416.cloudfunctions.net/postmanhack?image=https://i.imgur.com/taUKyu1.jpg","host":["https://us-central1-sound-fastness-257416.cloudfunctions.net/postmanhack"],"query":[{"key":"image","value":"https://i.imgur.com/taUKyu1.jpg","description":"The Image you put in the model"},{"key":"destination","value":"test-image-yourname.png","description":"File name of the destination image, be sure to append it with the extension (.png, .jpg or others)","disabled":true}]}},"status":"OK","code":200,"_postman_previewlanguage":"html","header":[{"key":"Content-Type","value":"text/html; charset=utf-8"},{"key":"Function-Execution-Id","value":"cjxj03h26ugo"},{"key":"X-Cloud-Trace-Context","value":"602c9bff16907b05a684bf0f8e4e7865;o=1"},{"key":"Date","value":"Mon, 26 Jul 2021 06:16:33 GMT"},{"key":"Server","value":"Google Frontend"},{"key":"Content-Length","value":"74"},{"key":"Alt-Svc","value":"h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\""}],"cookie":[],"responseTime":null,"body":"{\"output_image\": \"https://storage.googleapis.com/postmanhack/opnQIZQ.png\"}"}],"_postman_id":"7d348557-99a6-4977-86d2-3c0b596252ce"}],"event":[{"listen":"prerequest","script":{"id":"06c89df0-e863-49de-bfc6-f09cd2c36034","type":"text/javascript","exec":[""]}},{"listen":"test","script":{"id":"a6606fbd-b1be-49bc-98ae-5c2eefc198cb","type":"text/javascript","exec":[""]}}],"variable":[{"key":"Destination File","value":"test-image-yourname.png"},{"key":"Image URL","value":"https://i.imgur.com/taUKyu1.jpg"},{"key":"Hosted Model API","value":"https://us-central1-sound-fastness-257416.cloudfunctions.net/postmanhack"}]}