# Object Detection using node-red-contrib-tfjs-coco-ssd

**URL:** <https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931>\
**Category:** General\
**Created:** [10 March 2020 14:41 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931 "2020-03-10T14:41:53Z")\
**Posts on this page:** 20\
**Page:** 5

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [31 March 2020 20:25 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/82 "2020-03-31T20:25:45Z")

</div>

I'd be happy to add it as an example to the node as well.

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [1 April 2020 05:42 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/83 "2020-04-01T05:42:33Z")

</div>

Yes, very interesting. To start, could you just share the code you have in "draw Rects"?

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [1 April 2020 10:09 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/84 "2020-04-01T10:09:39Z")

</div>

Very nice, working fine! This topic is so interesting and challenging!

I made a small change to your first ui-template node so now I can feed it with images directly from the example of @SuperNinja via a base64 node. Just changed one line

`image.src = "data:image/jpg;base64,"+myimag;`

Secondly I used your grabbing setup that I now trigger automatically after a short delay

Playing a bit further, using your flow examples, I made an add-on example "hijacking" images and boxes. Resulting flow is below

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/b/eb16230c51738609563aff53091dc9ef26e7b00a.png)

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/9/b9103e735d1d7a808406f800e8cde5bc4825dac4.jpeg)

```auto
[{"id":"bdfde2a1.a7e7d","type":"ui_template","z":"2d489fd9.1eedd","group":"7b6a751b.c5eb9c","name":"","order":4,"width":"1","height":"1","format":" <script>\n (function(scope) {\n scope.$watch('msg', function(msg) {\n if (msg) {\n // Do something when msg arrives\n let dataURL = document.querySelector(\"#canvasImage\").toDataURL('image/jpeg');\n scope.send({payload: dataURL});\n }\n });\n })(scope);\n </script>\n","storeOutMessages":false,"fwdInMessages":true,"templateScope":"local","x":270,"y":1300,"wires":[["7643a96c.565538"]]},{"id":"a6b62e54.11837","type":"ui_template","z":"2d489fd9.1eedd","group":"7b6a751b.c5eb9c","name":"","order":2,"width":"7","height":"7","format":"","storeOutMessages":false,"fwdInMessages":true,"templateScope":"local","x":270,"y":1480,"wires":[["1431313f.5c0fbf"]]},{"id":"d9cc2a9c.01e6a8","type":"debug","z":"2d489fd9.1eedd","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":270,"y":1600,"wires":[]},{"id":"cbce6b69.9cd1e8","type":"template","z":"2d489fd9.1eedd","name":"","field":"template","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<img width=\"320\" height=\"240\" alt=\"storepic\" src={{{payload}}} />","output":"str","x":270,"y":1420,"wires":[["a6b62e54.11837"]]},{"id":"7643a96c.565538","type":"switch","z":"2d489fd9.1eedd","name":"data:image","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"data:image","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":270,"y":1360,"wires":[["cbce6b69.9cd1e8"]]},{"id":"d4e37092.e9a51","type":"link in","z":"2d489fd9.1eedd","name":"","links":["7a793272.3245fc"],"x":105,"y":1120,"wires":[["97bf55b7.ec4198"]]},{"id":"5fea2441.2f779c","type":"image","z":"2d489fd9.1eedd","name":"","width":"240","data":"payload","dataType":"msg","thumbnail":false,"active":true,"x":660,"y":1390,"wires":[]},{"id":"1431313f.5c0fbf","type":"function","z":"2d489fd9.1eedd","name":"","func":"let p = msg.payload.split(',')[1];\nmsg.payload = p;\nreturn msg;","outputs":1,"noerr":0,"x":270,"y":1540,"wires":[["5fea2441.2f779c","d9cc2a9c.01e6a8"]]},{"id":"c2aab595.729488","type":"image","z":"2d489fd9.1eedd","name":"","width":"240","data":"image","dataType":"msg","thumbnail":false,"active":true,"x":660,"y":1120,"wires":[]},{"id":"b81d2ada.cd80e8","type":"trigger","z":"2d489fd9.1eedd","op1":"","op2":"true","op1type":"nul","op2type":"bool","duration":"0.1","extend":false,"units":"s","reset":"","bytopic":"all","name":"","x":270,"y":1240,"wires":[["bdfde2a1.a7e7d"]]},{"id":"c06dcfae.24d1b","type":"ui_template","z":"2d489fd9.1eedd","group":"7b6a751b.c5eb9c","name":"","order":2,"width":"7","height":"6","format":"<canvas id=\"canvasImage\" width=\"320\" height=\"240\" style = \"border: 3px solid yellow\">\n Your browser does not support the canvas element.\n</canvas>\n\n<script>\n (function(scope) {\n scope.$watch('msg', function (msg) {\n if (msg) {\n // Do something when msg arrives\n function squares(canvasid, squarelist, myimag) {\n let canvas = document.querySelector(canvasid);\n let ctx = canvas.getContext('2d');\n ctx.scale(1, 1);\n let image = new Image;\n image.src = \"data:image/jpg;base64,\"+myimag;\n image.onload = function () {\n ctx.drawImage(image, 0, 0, canvas.width, canvas.height);\n //ctx.drawImage(image, 0, 0, 1280, 720);\n for (const square of squarelist) {\n ctx.lineWidth = 3;\n ctx.strokeStyle = 'red';\n ctx.strokeRect(square.bbox[0], square.bbox[1], square.bbox[2], square.bbox[3]);\n //ctx.fillText(square.class,square.bbox[0],square.bbox[1]);\n ctx.font = \"italic 12px Calibri\";\n ctx.fillStyle = 'yellow';\n let width = ctx.measureText(square.class).width;\n ctx.fillRect(square.bbox[0], square.bbox[1] - 12, width, 12);\n ctx.fillStyle = '#000';\n ctx.fillText(square.class, square.bbox[0], square.bbox[1]);\n }\n };\n }\n\n let canvasid1 = \"#canvasImage\";\n let detect = msg.detect;\n let imag1 = msg.image;\n squares(canvasid1, detect, imag1);\n }\n });\n})(scope);\n</script>","storeOutMessages":false,"fwdInMessages":true,"templateScope":"local","x":270,"y":1180,"wires":[["b81d2ada.cd80e8"]]},{"id":"97bf55b7.ec4198","type":"base64","z":"2d489fd9.1eedd","name":"","action":"str","property":"image","x":270,"y":1120,"wires":[["c06dcfae.24d1b","c2aab595.729488"]]},{"id":"7b6a751b.c5eb9c","type":"ui_group","z":"","name":"NR Image tests","tab":"a0ac7d1b.a925d","disp":true,"width":"10","collapse":false},{"id":"a0ac7d1b.a925d","type":"ui_tab","z":"","name":"XXX","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

```

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [1 April 2020 11:40 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/85 "2020-04-01T11:40:04Z")

</div>

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/f/6fb252ea329bab6f86db32b8fc26197faf1a03a1.jpeg)  
Another little effort, you have to adapt the boxes to the size of the incomming image (at the top my Flow for reference) 😉

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [1 April 2020 15:07 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/86 "2020-04-01T15:07:31Z")

</div>

@krambriw, @dceejay,

Here is the server side version (tidied up) as requested...

Demo...

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/a/0a55f02429c08f59efe8e1096bb91b82b2241eb6.png)

Flow...

```auto
[{"id":"e57010c0.e2bd8","type":"inject","z":"55a254fe.14f63c","name":"test","topic":"loremflickr","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":60,"wires":[["ddb5c73b.aaadc8"]]},{"id":"ddb5c73b.aaadc8","type":"http request","z":"55a254fe.14f63c","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"https://loremflickr.com/320/240/person","tls":"","persist":false,"proxy":"","authType":"","x":330,"y":60,"wires":[["c5737ffb.a7f52"]]},{"id":"c5737ffb.a7f52","type":"tensorflowCoco","z":"55a254fe.14f63c","name":"x","model":"","scoreThreshold":"","passthru":true,"x":510,"y":60,"wires":[["e1c5f9f.2f1f208"]]},{"id":"e1c5f9f.2f1f208","type":"change","z":"55a254fe.14f63c","name":"pay to detect","rules":[{"t":"move","p":"payload","pt":"msg","to":"detect","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":60,"wires":[["fd25ec9a.7245d"]]},{"id":"fd25ec9a.7245d","type":"jimp-image","z":"55a254fe.14f63c","name":"","data":"image","dataType":"msg","ret":"img","parameter1":"200","parameter1Type":"num","parameter2":"","parameter2Type":"auto","parameter3":"RESIZE_NEAREST_NEIGHBOR","parameter3Type":"resizeMode","parameter4":"","parameter4Type":"msg","parameter5":"","parameter5Type":"msg","parameter6":"","parameter6Type":"msg","parameter7":"","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","parameterCount":0,"jimpFunction":"none","selectedJimpFunction":{"name":"none","fn":"none","description":"Just loads the image.","parameters":[]},"x":150,"y":120,"wires":[["bd9fa409.372298","b723098.853eaf8","e3da3334.1278c"]]},{"id":"bd9fa409.372298","type":"image viewer","z":"55a254fe.14f63c","name":"","width":"400","data":"payload","dataType":"msg","x":270,"y":200,"wires":[[]]},{"id":"b723098.853eaf8","type":"function","z":"55a254fe.14f63c","name":"draw Rects","func":"const LINE_WIDTH = 2;\nconst LINE_COLOR = 0xED143DFF;\n\nvar jimpImage = msg.payload;\nlet imgW = jimpImage.bitmap.width;\nlet imgH = jimpImage.bitmap.height;\n\n//create clamping functions to avoid printing outside of image\nlet clampX = (val) => clamp(val,0,imgW);\nlet clampY = (val) => clamp(val,0,imgH);\n\n//add imgBatchOps to msg for drawing text in next node \nmsg.imgBatchOps = [];\n\n\nif (msg.detect.length>0) {\n drawBoxes(jimpImage, msg.detect);\n}\n\nfunction drawBox(img, box) {\n //get box ccords\n let x = box.bbox[0];\n let y = box.bbox[1];\n let w = box.bbox[2];\n let h = box.bbox[3];\n \n scanHLine(img, x, y+h-14, w, 14, 0xfa758e22); //draw box for text\n scanRectangle(img, x, y, w, h, LINE_WIDTH, LINE_COLOR);//draw outer rect\n \n //built batch operations for next image node to draw text\n msg.imgBatchOps.push( \n {\n \"name\": \"print\",\n \"parameters\": [\n \"FONT_SANS_10_BLACK\",\n clampX(x+2),\n clampY(y+h-16),\n box.class\n]\n }\n \n ); \n}\n\nfunction drawBoxes(img, detections) {\n detections.forEach(element => drawBox(img, element))\n}\n\n\nfunction makeColorIterator(color) {\n return function (x, y, offset) {\n this.bitmap.data.writeUInt32BE(color, offset, true);\n }\n}\n\nfunction scanRectangle(image,x,y,w,h,linePX,color){\n let iterator = makeColorIterator(color);\n \n let xw, yh;\n x = clampX(x-(linePX/2));\n y = clampY(y-(linePX/2));\n w = clampX(w);\n h = clampY(h);\n xw = clampX(x+w);\n yh = clampY(y+h);\n\n \n if(y+linePX <= imgH){\n image.scan(x, y, w, linePX, iterator);// scan linePX height line - TOP\n }\n if(yh+linePX <= imgH){\n image.scan(x, yh, w, linePX, iterator);// scan linePX height line - BOTTOM\n }\n if(x+linePX <= imgW){\n image.scan(x, y, linePX, h, iterator);// scan linePX width line - LEFT\n }\n if(xw+linePX <= imgW){\n image.scan(xw, y, linePX, h, iterator);// scan linePX width line - RIGHT\n }\n \n}\n\n\nfunction scanHLine(image,x,y,length,linePX,color){\n let iterator = makeColorIterator(color);\n x = clampX(x);\n y = clampY(y);\n length = clampX(length);\n if(y+linePX <= imgH){\n image.scan(x, y, length, linePX, iterator);// \n }\n}\n\nfunction scanVLine(image,x,y,height,linePX,color){\n let iterator = makeColorIterator(color);\n x = clampX(x);\n y = clampY(y);\n height = clampY(y+height);\n if(x+linePX <= imgW){\n image.scan(x, y, linePX, height, iterator);// \n }\n}\n\n\n//scanCircle(jimpImage, 92, 170, 43, 0x000000FF);\n//scanCircle(jimpImage, 92, 170, 42, 0xFFCC00FF);\n\nfunction clamp(value, min, max) {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction scanCircle(image, x, y, radius, color) {\n let iterator = makeColorIterator(color);\n return image.scan(x - radius, y - radius, radius*2, radius*2, function (pixX, pixY, idx) {\n if (Math.pow(pixX - x, 2) + Math.pow(pixY - y, 2) < radius*radius) {\n iterator.call(this, pixX, pixY, idx);\n }\n });\n}\n\n \n\nreturn msg;","outputs":1,"noerr":0,"x":410,"y":160,"wires":[["58bb5b3e.f919f4"]]},{"id":"8be04a7a.8f2ad8","type":"image viewer","z":"55a254fe.14f63c","name":"","width":"400","data":"payload","dataType":"msg","x":710,"y":200,"wires":[[]]},{"id":"58bb5b3e.f919f4","type":"jimp-image","z":"55a254fe.14f63c","name":"add text","data":"payload","dataType":"msg","ret":"img","parameter1":"imgBatchOps","parameter1Type":"msg","parameter2":"","parameter2Type":"msg","parameter3":"","parameter3Type":"msg","parameter4":"","parameter4Type":"msg","parameter5":"","parameter5Type":"msg","parameter6":"","parameter6Type":"msg","parameter7":"","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","parameterCount":1,"jimpFunction":"batch","selectedJimpFunction":{"name":"batch","fn":"batch","description":"apply one or more functions","parameters":[{"name":"options","type":"json","required":true,"hint":"an object or an array of objects containing {\"name\" : \"function_name\", \"parameters\" : [x,y,z]}. Refer to info on side panel}"}]},"x":560,"y":160,"wires":[["8be04a7a.8f2ad8","c06c130b.3795a"]]},{"id":"c06c130b.3795a","type":"jimp-image","z":"55a254fe.14f63c","name":"Save as image_with_annotations.jpg","data":"payload","dataType":"msg","ret":"img","parameter1":"image_with_annotations.jpg","parameter1Type":"str","parameter2":"","parameter2Type":"msg","parameter3":"","parameter3Type":"msg","parameter4":"","parameter4Type":"msg","parameter5":"","parameter5Type":"msg","parameter6":"","parameter6Type":"msg","parameter7":"","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","parameterCount":1,"jimpFunction":"write","selectedJimpFunction":{"name":"write","fn":"write","description":"Write to file. NOTE: You can specify an alternative file extension type to change the type. Currently support types are jpg, png, bmp.","parameters":[{"name":"filename","type":"str","required":true,"hint":"Name of the file","defaultType":"str"}]},"x":810,"y":160,"wires":[[]]},{"id":"e3da3334.1278c","type":"jimp-image","z":"55a254fe.14f63c","name":"Save as image_without_annotations.jpg","data":"payload","dataType":"msg","ret":"img","parameter1":"image_without_annotations.jpg","parameter1Type":"str","parameter2":"","parameter2Type":"msg","parameter3":"","parameter3Type":"msg","parameter4":"","parameter4Type":"msg","parameter5":"","parameter5Type":"msg","parameter6":"","parameter6Type":"msg","parameter7":"","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","parameterCount":1,"jimpFunction":"write","selectedJimpFunction":{"name":"write","fn":"write","description":"Write to file. NOTE: You can specify an alternative file extension type to change the type. Currently support types are jpg, png, bmp.","parameters":[{"name":"filename","type":"str","required":true,"hint":"Name of the file","defaultType":"str"}]},"x":820,"y":120,"wires":[[]]}]

```

NOTES

- Uses [node-red-contrib-image-tools](https://flows.nodered.org/node/node-red-contrib-image-tools) for drawing on image
- For anyone wondering why I seemingly duplicated efforts - I did it as a POC about 4 days - I needed to get annotated images purely server-side (i.e. headless / no browser required). Essentially I am detecting people outside the house & send annotated image to Telegram/Pushbullet) - so i needed it to run headless. This is a cut down demo.

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [1 April 2020 15:37 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/87 "2020-04-01T15:37:07Z")

</div>

Great, that is nice to have as well, many options around.

You are correct, the one previously is client-sided, I think it only works the whole way if I have the browser with the views in focus

Your server-sided solved it nicely, drawing on top of the image. I never had a clue how to do it in javascript so I desperately installed opencv and opencv4nodejs. It did work but the process of installing was very time consuming. Only advantage maybe, you could do it with less code lines 😉

And my oldest solution doing the same is still written in Python and also using opencv

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [1 April 2020 15:47 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/88 "2020-04-01T15:47:56Z")

</div>

Yes, you are right, it looks awful if the picture has any other size than 320x240

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [1 April 2020 15:58 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/89 "2020-04-01T15:58:58Z")

</div>

**Intermediate score:** 🎰  
**Steve-Mcl** is at the head of a point  
**Andrei** follows behind and will bring us something good ...  
**krambriw** will he go back up or throw in the towel?  
🤣

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [1 April 2020 17:12 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/90 "2020-04-01T17:12:56Z")

</div>

Instead of cancelled formula one's and, sadly, cancelled Wimbledon....most likely cancelled French Open  
Very much OT, yes

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [1 April 2020 17:16 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/91 "2020-04-01T17:16:57Z")

</div>

(Yes, and Roland Garros postponed to the end of September)

---

<div class="post-metadata">

**Author:** ![Andrei](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/andrei/32/10446_2.png) [@Andrei](https://discourse.nodered.org/u/Andrei)\
**Post date:** [2 April 2020 15:13 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/92 "2020-04-02T15:13:47Z")

</div>

> [@Steve-Mcl](#):
>
> I needed to get annotated images purely server-side (i.e. headless / no browser required). Essentially I am detecting people outside the house & send annotated image to Telegram/Pushbullet) - so i needed it to run headless.

Hi Steve, I find that your approach for the use case and contrib-node are great. I plan to improve my home surveillance system in a near future and will certainly take the same approach (run headless and send notifications via Telegram). I just installed the contrib node to start playing with the nodes but strangely the viewer node is not appearing in the palette. I will check later today. Thank you for bringing jimp.js to Node-RED with your contrib.

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [2 April 2020 15:18 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/93 "2020-04-02T15:18:15Z")

</div>

Hi Andrei, you are most welcome. I've gained so much from node-red, seems only fair to contribute right?

Could you tell me what browser you're using please

Also, could you do a quick test - hold `ctrl` and click somewhere inside node-red (get the quick add node pop-up list) and type `viewer`. See if its there.

Lastly, what OS and Node Version please.

---

<div class="post-metadata">

**Author:** ![Andrei](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/andrei/32/10446_2.png) [@Andrei](https://discourse.nodered.org/u/Andrei)\
**Post date:** [2 April 2020 15:30 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/94 "2020-04-02T15:30:52Z")

</div>

Not a big concern about image viewer as I will be mainly using the jimp-image.

I am using Chrome (latest version).

Runtime environment:

Node-RED version: v1.0.3  
Node.js version: v8.11.1  
Windows\_NT 10.0.18363 x64 LE  
Dashboard version 2.19.2 started at /ui

Viewer is not showing up in the quick mode. I tried also searching by "image"

![im-03](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/3/4/34dd09ea8c9a2f68954e468cc29a94c507aea53a.png)

This is what manage palette shows me.

![im-01](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/7/97c341c2dd08528d5a1e227ec54978a4c9c5d9df.png)

and this is the log after the install.

I restart node-red after installation (just in case).

 ![im-02](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/f/0fc8067670c288c1900c2b8a88d4e51cbb519403.png)

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [2 April 2020 15:47 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/95 "2020-04-02T15:47:50Z")

</div>

Hmmm

Could be node v8 thing.

3 questions,

- Is there any errors or warnings in browser devtools?
- are you able to update to node V10 or 12?
- Is the other separate image preview node installed? (Might conflict)

---

<div class="post-metadata">

**Author:** ![Andrei](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/andrei/32/10446_2.png) [@Andrei](https://discourse.nodered.org/u/Andrei)\
**Post date:** [2 April 2020 15:56 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/96 "2020-04-02T15:56:09Z")

</div>

Hi Steve, you nailed it !

I started by uninstalling `node-red-contrib-image-output` and voila ! The viewer node is now available.

Good catch. Probably some conflict.

![im-04](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/a/da542d959f85cb116cbc8ca1179072b3c1517acd.png)

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [2 April 2020 18:30 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/97 "2020-04-02T18:30:31Z")

</div>

So here all together; Steve's, Andrei's and SuperNinja's contributions "hacked" and put together, showing the same image, works fine!!!

Sending the image via Telegram requires images to be binary buffers. (for Steve''s solution, the image needs to be converted as such, I suspect it is a jimp formatted image???)

EDIT: Easy enough, thanks to Steve's image node, coverting back to buffer from jimp, so easy. Now immages from Steve's solution is sent quickly via Telegram

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/e/1e7e51c6ea765ab49142e09c5b0238551101c7a8.png)

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [3 April 2020 01:24 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/98 "2020-04-03T01:24:18Z")

</div>

4 posts were split to a new topic: [How to manage the image-output / image-tools node conflict (split topic)](https://discourse.nodered.org/t/how-to-manage-the-image-output-image-tools-node-conflict-split-topic/24122)

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [3 April 2020 10:20 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/99 "2020-04-03T10:20:48Z")

</div>

In case you need it, I just thought I should share how I configured the things so that images from Steve's solution can be sent via Telegram

1. Install nodes that supports Telegram, I used node-red-contrib-telegrambot

2. Configure your Telegram bot with your token

3. Add some additional nodes to your flow, example in picture below

- Add an image node that captures the analyzed image data (as shown in the preview)
- Since the image is in jimp format, we configure the node to give us base64 back
- Next we can decide to show the image also on a webpage, not necessary, you may skip the ui\_template node
- A split and switch node is then used so that just the base64 image data is sent further down the line
- Telegram wants binary buffer for images so this is taken care of by the base64 node
- Finally, the function node is composing the msg that is sent to the Telegram sender node

Personally, I decided to add the required chatId in the msg. So my code in the function node looks like this (my chatId is of course something different):

```auto
var m = { content:'', type:'', chatId:''};
m.content = msg.payload;
m.type = 'photo';
m.chatId = 123456789;
msg.payload = m;
return msg;

```

Happy messaging!

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/6/f668e1a43d4a75aad80882237feabd108dbc69af.png)

---

<div class="post-metadata">

**Author:** ![krambriw](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/krambriw/32/5429_2.png) [@krambriw](https://discourse.nodered.org/u/krambriw)\
**Post date:** [9 April 2020 10:09 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/100 "2020-04-09T10:09:12Z")

</div>

Now scaling etc is working the same for both variants, also for larger images 😇

Happy Easter!

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/6/1604b8e003417bc55c070e3367453fc17bb4af55.jpeg)

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [11 April 2020 07:13 UTC](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931/101 "2020-04-11T07:13:48Z")

</div>

super improvement ! can you share your flow ? 🙂

[Previous page](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931.md?page=4)

[Next page](https://discourse.nodered.org/t/object-detection-using-node-red-contrib-tfjs-coco-ssd/22931.md?page=6)
