HTTP endpoint for image payloads

Hi All,
Sorry if this came up already, I've searched thoroughly :slight_smile:

I'm trying to get the image buffer payload in the debug node, from a template node ("image"). I'm using the "get (form)->post" method below. It works only when uploading a file and not by passing an image url as in the http request node. So, if I need to pass an image url, do some html5 manipulations in the template node and display the payload on the debugger - I can't. Any idea how to solve it? Thanks!

[{"id":"47d27633.d3d2a8","type":"tab","label":"Image_Payload","disabled":false,"info":""},{"id":"1c452e89.35c2d1","type":"http in","z":"47d27633.d3d2a8","name":"","url":"/image_payload","method":"get","upload":false,"swaggerDoc":"","x":120,"y":40,"wires":[["8f1ecb85.c39518"]]},{"id":"8f1ecb85.c39518","type":"template","z":"47d27633.d3d2a8","name":"image","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<center>\n\n<img src=\"https://www.w3schools.com/html/pic_trulli.jpg\" alt=\"Trulli\" width=\"500\" height=\"333\">\n\n<form action=\"/payload_post\" method=\"POST\" enctype=\"multipart/form-data\">\n    <input type=\"file\" name=\"myFile\"/>\n    <input type=\"submit\" value=\"Analyze File\">\n</form>\n\n</center>\n","output":"str","x":290,"y":40,"wires":[["27490f43.e6e7c"]]},{"id":"27490f43.e6e7c","type":"http response","z":"47d27633.d3d2a8","name":"","statusCode":"","headers":{},"x":410,"y":40,"wires":[]},{"id":"58949c54.02b47c","type":"http in","z":"47d27633.d3d2a8","name":"","url":"/payload_post","method":"post","upload":true,"swaggerDoc":"","x":110,"y":120,"wires":[["35370570.d632ea","f1fe18f1.271458"]]},{"id":"f1fe18f1.271458","type":"change","z":"47d27633.d3d2a8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"req.files[0].buffer","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":140,"wires":[["8f488946.2633d8","c09ff4f1.201d78"]]},{"id":"c09ff4f1.201d78","type":"image viewer","z":"47d27633.d3d2a8","name":"","width":160,"data":"payload","dataType":"msg","x":510,"y":160,"wires":[[]]},{"id":"8f488946.2633d8","type":"function","z":"47d27633.d3d2a8","name":"Save Picture Buffer","func":"if (msg.req.files[0].mimetype.includes('image')) {\n    msg.mypic = `<img src=\"data:image/gif;base64,${msg.payload.toString('base64')}\">`;\n} else {\n    msg.payload = msg.payload.toString();\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":550,"y":120,"wires":[["771ce36c.58c1fc","35607f02.aeea6"]]},{"id":"35370570.d632ea","type":"debug","z":"47d27633.d3d2a8","name":"","active":true,"tosidebar":true,"console":false,"complete":"req.files","x":330,"y":100,"wires":[]},{"id":"35607f02.aeea6","type":"http response","z":"47d27633.d3d2a8","name":"","statusCode":"","headers":{},"x":710,"y":160,"wires":[]},{"id":"771ce36c.58c1fc","type":"debug","z":"47d27633.d3d2a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":670,"y":80,"wires":[]}]```

What are you sending to these endpoints?

What are you trying to achieve?

What image URL? And what http request node? I don't see a request node in that screen shot.

Thanks Steve,
What I'm trying to achieve is background removal for people images in the browser with TensorFlow.js and ml5js using person and body-part segmentation. The "/image_payload" endpoint does that OK and segments out an image into pixels that are (and are not) part of a person’s body. You can find the URL in the template node, line 13, derived from the injection node:

img = loadImage('{{{flow.person}}}');

and the flow:

[{"id":"27490f43.e6e7c","type":"http response","z":"47d27633.d3d2a8","name":"","statusCode":"","headers":{},"x":510,"y":100,"wires":[]},{"id":"e629870d.aff128","type":"template","z":"47d27633.d3d2a8","name":"remove background","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<center>\n\n  <script src='https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js'></script>\n<script src='https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/addons/p5.dom.min.js'></script>\n<script src='https://unpkg.com/ml5@0.6.1/dist/ml5.min.js'></script>\n      <script id=\"rendered-js\" >\nlet bodypix;\nlet segmentation;\nlet img;\n\nfunction preload() {\n  \n  img = loadImage('{{{flow.person}}}');\n  bodypix = ml5.bodyPix();\n\n}\n\nfunction setup() {\n  createCanvas(img.width, img.height);\n  background(0);\n  image(img, 0, 0);\n  bodypix.segment(img, gotResults);\n}\n\nfunction gotResults(err, result) {\n  if (err) {\n    console.log(err);\n    return;\n  }\n\n  segmentation = result;\n\n  background(255);\n  image(segmentation.backgroundMask, 0, 0, width, height);\n\n}\n\n    </script>\n\n</center>","output":"str","x":320,"y":100,"wires":[["27490f43.e6e7c"]]},{"id":"1c452e89.35c2d1","type":"http in","z":"47d27633.d3d2a8","name":"","url":"/image_payload","method":"get","upload":false,"swaggerDoc":"","x":100,"y":100,"wires":[["e629870d.aff128"]]},{"id":"c494651d.615b38","type":"inject","z":"47d27633.d3d2a8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Pierre-Person.jpg/300px-Pierre-Person.jpg","payloadType":"str","x":90,"y":40,"wires":[["f1ca840f.0f0c88"]]},{"id":"f1ca840f.0f0c88","type":"change","z":"47d27633.d3d2a8","name":"","rules":[{"t":"set","p":"person","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":240,"y":40,"wires":[[]]}]

However, I'm unable to get the msg.payload as a buffer from the template node. So, I tried to post it to /payload_post as in the following flow, but no luck.... here's the full flow:

[{"id":"47d27633.d3d2a8","type":"tab","label":"Image_Payload","disabled":false,"info":""},{"id":"1c452e89.35c2d1","type":"http in","z":"47d27633.d3d2a8","name":"","url":"/image_payload","method":"get","upload":false,"swaggerDoc":"","x":100,"y":100,"wires":[["e629870d.aff128"]]},{"id":"27490f43.e6e7c","type":"http response","z":"47d27633.d3d2a8","name":"","statusCode":"","headers":{},"x":510,"y":100,"wires":[]},{"id":"58949c54.02b47c","type":"http in","z":"47d27633.d3d2a8","name":"","url":"/payload_post","method":"post","upload":true,"swaggerDoc":"","x":130,"y":220,"wires":[["35370570.d632ea","f1fe18f1.271458"]]},{"id":"f1fe18f1.271458","type":"change","z":"47d27633.d3d2a8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"req.files[0].buffer","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":340,"y":240,"wires":[["8f488946.2633d8","c09ff4f1.201d78"]]},{"id":"8f488946.2633d8","type":"function","z":"47d27633.d3d2a8","name":"Save Picture Buffer","func":"if (msg.req.files[0].mimetype.includes('image')) {\n    msg.mypic = `<img src=\"data:image/gif;base64,${msg.payload.toString('base64')}\">`;\n} else {\n    msg.payload = msg.payload.toString();\n}\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":530,"y":200,"wires":[["771ce36c.58c1fc","35607f02.aeea6"]]},{"id":"35370570.d632ea","type":"debug","z":"47d27633.d3d2a8","name":"","active":true,"tosidebar":true,"console":false,"complete":"req.files","x":310,"y":180,"wires":[]},{"id":"35607f02.aeea6","type":"http response","z":"47d27633.d3d2a8","name":"","statusCode":"","headers":{},"x":690,"y":240,"wires":[]},{"id":"771ce36c.58c1fc","type":"debug","z":"47d27633.d3d2a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":690,"y":160,"wires":[]},{"id":"c09ff4f1.201d78","type":"image viewer","z":"47d27633.d3d2a8","name":"","width":160,"data":"payload","dataType":"msg","x":510,"y":260,"wires":[[]]},{"id":"e629870d.aff128","type":"template","z":"47d27633.d3d2a8","name":"remove background","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<center>\n\n  <script src='https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js'></script>\n<script src='https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/addons/p5.dom.min.js'></script>\n<script src='https://unpkg.com/ml5@0.6.1/dist/ml5.min.js'></script>\n      <script id=\"rendered-js\" >\nlet bodypix;\nlet segmentation;\nlet img;\n\nfunction preload() {\n  \n  img = loadImage('{{{flow.person}}}');\n  bodypix = ml5.bodyPix();\n\n}\n\nfunction setup() {\n  createCanvas(img.width, img.height);\n  background(0);\n  image(img, 0, 0);\n  bodypix.segment(img, gotResults);\n}\n\nfunction gotResults(err, result) {\n  if (err) {\n    console.log(err);\n    return;\n  }\n\n  segmentation = result;\n\n  background(255);\n  image(segmentation.backgroundMask, 0, 0, width, height);\n\n}\n\n    </script>\n    \n    <form action=\"/payload_post\" method=\"POST\" enctype=\"multipart/form-data\">\n    <input type=\"image\" name=\"myFile\"/>\n\n</form>\n\n\n</center>","output":"str","x":320,"y":100,"wires":[["27490f43.e6e7c"]]},{"id":"c494651d.615b38","type":"inject","z":"47d27633.d3d2a8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Pierre-Person.jpg/300px-Pierre-Person.jpg","payloadType":"str","x":90,"y":40,"wires":[["f1ca840f.0f0c88"]]},{"id":"f1ca840f.0f0c88","type":"change","z":"47d27633.d3d2a8","name":"","rules":[{"t":"set","p":"person","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":240,"y":40,"wires":[[]]}]

Appreciate any help:)

Hi, firstly, as you are not using dashboard (you are pretty much building a website from endpoints) you have to include html/head/body tags)

Ok, so since this is all client side, you need to post the data back to your 2nd endpoint. for this I simply used fetch. Also, as that P5 library generates its results on a canvas, you need to call .toDataURL() on the canvas to get the base64 data.

If you want to save this as an actual image, you should convert the base64 to binary. NOTE: Image tools has a write function to take the worry out of the format etc.

anyhow, here you go...

The flow...

[{"id":"1c452e89.35c2d1","type":"http in","z":"47d27633.d3d2a8","name":"","url":"/image_payload","method":"get","upload":false,"swaggerDoc":"","x":130,"y":160,"wires":[["e629870d.aff128"]]},{"id":"27490f43.e6e7c","type":"http response","z":"47d27633.d3d2a8","name":"","statusCode":"","headers":{},"x":540,"y":160,"wires":[]},{"id":"58949c54.02b47c","type":"http in","z":"47d27633.d3d2a8","name":"","url":"/payload_post","method":"post","upload":false,"swaggerDoc":"","x":130,"y":220,"wires":[["6322a969.c2a578"]]},{"id":"35607f02.aeea6","type":"http response","z":"47d27633.d3d2a8","name":"","statusCode":"","headers":{},"x":870,"y":220,"wires":[]},{"id":"c09ff4f1.201d78","type":"image viewer","z":"47d27633.d3d2a8","name":"","width":160,"data":"payload.base64","dataType":"msg","x":490,"y":220,"wires":[["b0736bda.d97868"]]},{"id":"e629870d.aff128","type":"template","z":"47d27633.d3d2a8","name":"remove background","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<html>\n\n<head>\n  <script src='https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js'></script>\n  {{!-- <script src='https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/addons/p5.dom.min.js'></script> --}}\n  <script src='https://unpkg.com/ml5@0.6.1/dist/ml5.min.js'></script>\n</head>\n\n<body>\n\n<script id=\"rendered-js\" >\n      let bodypix;\n      let segmentation;\n      let img;\n      \n      function preload() {\n        \n        img = loadImage('{{{flow.person}}}');\n        bodypix = ml5.bodyPix();\n\n      }\n\n      function setup() {\n        createCanvas(img.width, img.height);\n        background(0);\n        image(img, 0, 0);\n        bodypix.segment(img, gotResults);\n      }\n\n      function gotResults(err, result) {\n        if (err) {\n          console.log(err);\n          return;\n        }\n\n        segmentation = result;\n\n        background(255);\n        image(segmentation.backgroundMask, 0, 0, width, height);\n      }\n  </script>\n  <script>\n    function upload() {\n      var c = document.getElementsByClassName(\"p5Canvas\")[0]; \n      var payload = {\n        base64: c.toDataURL(),\n        width: c.width,\n        height: c.height\n      }\n      fetch(\"/payload_post\", { method: 'POST', body: JSON.stringify(payload) });\n    }\n  </script>\n\n  <button onclick=\"upload()\">Send to node-red</button>\n\n</body>\n</html>","output":"str","x":350,"y":160,"wires":[["27490f43.e6e7c"]]},{"id":"c494651d.615b38","type":"inject","z":"47d27633.d3d2a8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Pierre-Person.jpg/300px-Pierre-Person.jpg","payloadType":"str","x":120,"y":100,"wires":[["f1ca840f.0f0c88"]]},{"id":"f1ca840f.0f0c88","type":"change","z":"47d27633.d3d2a8","name":"","rules":[{"t":"set","p":"person","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":270,"y":100,"wires":[[]]},{"id":"6322a969.c2a578","type":"json","z":"47d27633.d3d2a8","name":"","property":"payload","action":"","pretty":false,"x":310,"y":220,"wires":[["3a688b54.e4ec44","c09ff4f1.201d78"]]},{"id":"3a688b54.e4ec44","type":"debug","z":"47d27633.d3d2a8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":290,"y":280,"wires":[]},{"id":"b0736bda.d97868","type":"change","z":"47d27633.d3d2a8","name":"","rules":[{"t":"set","p":"statusCode","pt":"msg","to":"200","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":220,"wires":[["35607f02.aeea6"]]}]
1 Like

Thanks a lot Steve! that does the trick :slight_smile:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.