Can I use RPI camera for scanning barcodes on node-RED?

Hi!
I am looking for a way to scan barcodes using RPI camera with minimal to none Python coding.
Please note that I am not looking for QR but barcode scanning.
Could anyone help? If so, and would be willing to, please share your flow for it.
Thanks for any help

Did toy try a google search? Try
Rpi camera barcodes node-red
And see what you find

Update: Although the post below mentions QR code scanning, the underlying tool also supports bar codes !

I am doing real-time QR scanning in the browser using the camera of the device where my browser client is running.
For this I have made use of

I have used the mui_template node of the node-red-contrib-mdashboard but it will also work when you use the ui_template node of the node-red-dashboard.

Main points:

  1. it runs in the browser (and therefore uses the camera of the device where your browser client is running).
  2. it is resource incentive if you keep it running (you can stop the QR scanning). So if you do the scanning in the browser of your mobile phone it might drain its battery rather quickly
  3. Chrome browser (and maybe same for other browser) don't allow to access your camera via http:// sites. So you will see a blank template in that case. I am accessing the dashboard via https:// and then it is working fine.

Here below I you can see the relevant part of my flow.
I have deleted a big part of it as it is too big for this forum, but this deleted part you can also find here:

[
    {
        "id": "2f0ca624.c9275a",
        "type": "mui_template",
        "z": "afa6119e.fa298",
        "group": "ec6dcfca.89668",
        "name": "QR scanner",
        "order": 1,
        "width": "8",
        "height": "8",
        "format": "<!DOCTYPE html>\n<html>\n<head>\n    <title>Html-Qrcode Demo</title>\n<script>\n// copy pasted from https://raw.githubusercontent.com/mebjas/html5-qrcode/master/minified/html5-qrcode.min.js\nfunction getLazarSoftScanner(){var e={};function t(e,t){this.count=e,this.dataCodewords=t,this.__defineGetter__(\"Count\",function(){return this.count}),this.__defineGetter__(\"DataCodewords\",function(){return this.dataCodewords})}function n(e,t,n){this.ecCodewordsPerBlock=e,this.ecBlocks=n?new Array(t,n):new Array(t),this.__defineGetter__(\"ECCodewordsPerBlock\",function(){return this.ecCodewordsPerBlock}),this.__defineGetter__(\"TotalECCodewords\",function(){return this.ecCodewordsPerBlock*this.NumBlocks}),this.__defineGetter__(\"NumBlocks\",function(){for(var e=0,t=0;t<this.ecBlocks.length;t++)e+=this.ecBlocks[t].length;return e}),this.getECBlocks=function(){return this.ecBlocks}}function r(e,t,n,r,i,a){this.versionNumber=e,this.alignmentPatternCenters=t,this.ecBlocks=new Array(n,r,i,a);for(var o=0,s=n.ECCodewordsPerBlock,h=n.getECBlocks(),w=0;w<h.length;w++){var f=h[w];o+=f.Count*(f.DataCodewords+s)}this.totalCodewords=o,this.__defineGetter__(\"VersionNumber\",function(){return this.versionNumber}),this.__defineGetter__(\"AlignmentPatternCenters\",function(){return 
....
document.addEventListener(\"DOMContentLoaded\", fn);\n        }\n    }\n\n    docReady(function () {\n        var resultContainer = document.getElementById('qr-reader-results');\n        var lastResult, countResults = 0;\n        function onScanSuccess(qrCodeMessage) {\n            if (qrCodeMessage !== lastResult) {\n                ++countResults;\n                lastResult = qrCodeMessage;\n                //resultContainer.innerHTML\n                //    += `<div>[${countResults}] - ${qrCodeMessage}</div>`;\n                theScope.send({payload: qrCodeMessage});\n            }\n        }\n        \n        const html5QrCode = new Html5Qrcode(\"qr-reader\");\n        \n        (function(scope) {\n          scope.$watch('msg', function(msg) {\n            if (msg.payload == 'start' ) {\n              // start scanner ( prefer back camera )\n              html5QrCode.start({ facingMode: \"environment\" }, { fps: 10, qrbox: 350 }, onScanSuccess);\n            } else if  ( msg.payload == 'stop' ) {\n              // stop\n              html5QrCode.stop();\n            }\n          });\n        })(theScope);\n\n        /*  old scanner code\n        var html5QrcodeScanner = new Html5QrcodeScanner(\n            \"qr-reader\", { fps: 10, qrbox: 350 });\n        html5QrcodeScanner.render(onScanSuccess);\n        */\n    });\n</script>\n</body>\n\n</html>",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "templateScope": "local",
        "x": 330,
        "y": 460,
        "wires": [
            [
                "b872facf.d9a3b8",
                "d63c6e34.68ae9"
            ]
        ]
    },
    {
        "id": "b872facf.d9a3b8",
        "type": "debug",
        "z": "afa6119e.fa298",
        "name": "QR code",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 360,
        "y": 420,
        "wires": []
    },
    {
        "id": "2f516d93.e38da2",
        "type": "mui_button",
        "z": "afa6119e.fa298",
        "name": "",
        "group": "9bfb0d76.50b33",
        "order": 1,
        "width": "4",
        "height": "1",
        "passthru": false,
        "label": "start scanning",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "icon": "",
        "payload": "start",
        "payloadType": "str",
        "topic": "",
        "x": 100,
        "y": 480,
        "wires": [
            [
                "dadafc669d098eb9"
            ]
        ]
    },
    {
        "id": "5026c7d7.483b28",
        "type": "mui_button",
        "z": "afa6119e.fa298",
        "name": "",
        "group": "9bfb0d76.50b33",
        "order": 2,
        "width": "4",
        "height": "1",
        "passthru": false,
        "label": "stop scanning",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "icon": "",
        "payload": "stop",
        "payloadType": "str",
        "topic": "",
        "x": 100,
        "y": 440,
        "wires": [
            [
                "dadafc669d098eb9"
            ]
        ]
    },
    {
        "id": "dadafc669d098eb9",
        "type": "junction",
        "z": "afa6119e.fa298",
        "x": 220,
        "y": 460,
        "wires": [
            [
                "2f0ca624.c9275a"
            ]
        ]
    },
    {
        "id": "ec6dcfca.89668",
        "type": "mui_group",
        "name": "scanner",
        "tab": "2f112c80.eac414",
        "order": 1,
        "disp": false,
        "width": "8",
        "collapse": false
    },
    {
        "id": "9bfb0d76.50b33",
        "type": "mui_group",
        "name": "bottom",
        "tab": "2f112c80.eac414",
        "order": 5,
        "disp": false,
        "width": "8",
        "collapse": false
    },
    {
        "id": "2f112c80.eac414",
        "type": "mui_tab",
        "name": "QR scanner",
        "icon": "dashboard",
        "order": 1,
        "disabled": false,
        "hidden": false
    }
]
1 Like

If you need to do this without a browser running then node-red-contrib-image-tools also decodes barcodes.

There is a built in demo (CTRL-I --> examples --> node-red-contrib-image-tools)

Thank you for the replies.
I've started going in the node-red-contrib-image-tools direction but for some reason it won't read my custom images only the one(s) in the example.
Any advice?

can you provide a few sample images?

This is the "custom" (first one from the internet) barcode I wanted it to read.


And this is my flow so far

I'd like to remove the load image later with a (kind of real time) 'take picture' node and that would be the ideal flow

Why are you running though the "clean up image" - that was for tarting up a bad pic in the demo! (your image is clean!)

Also, it works for me...

image

[{"id":"eb4adc7a54fa2b33","type":"jimp-image","z":"4c5ad8c7caa80822","name":"load image","data":"c:/temp/image.jpg","dataType":"str","ret":"img","parameter1":"190","parameter1Type":"num","parameter2":"255","parameter2Type":"num","parameter3":"true","parameter3Type":"bool","parameter4":"","parameter4Type":"msg","parameter5":"","parameter5Type":"msg","parameter6":"","parameter6Type":"msg","parameter7":"","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","sendProperty":"payload","sendPropertyType":"msg","parameterCount":0,"jimpFunction":"none","selectedJimpFunction":{"name":"none","fn":"none","description":"Just loads the image.","parameters":[]},"x":1530,"y":440,"wires":[["83abed247ea068fd"]]},{"id":"0a6ec9fbb0820ec1","type":"inject","z":"4c5ad8c7caa80822","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1340,"y":440,"wires":[["eb4adc7a54fa2b33"]]},{"id":"408252b3d66b03a7","type":"image viewer","z":"4c5ad8c7caa80822","name":"","width":160,"data":"payload","dataType":"msg","active":true,"x":1330,"y":500,"wires":[["80987d6e08bfd1ff"]]},{"id":"80987d6e08bfd1ff","type":"Barcode Decoder","z":"4c5ad8c7caa80822","name":"","data":"payload","dataType":"msg","tryharder":"true","tryharderType":"bool","QR_CODE":false,"DATA_MATRIX":false,"PDF_417":true,"EAN_8":true,"EAN_13":true,"CODE_39":true,"CODE_128":true,"ITF":true,"RSS_14":true,"x":1550,"y":500,"wires":[["25471d262afcac61"]]},{"id":"25471d262afcac61","type":"debug","z":"4c5ad8c7caa80822","name":"debug 107","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1730,"y":500,"wires":[]},{"id":"83abed247ea068fd","type":"jimp-image","z":"4c5ad8c7caa80822","name":"","data":"c:/temp/image.jpg","dataType":"str","ret":"img","parameter1":"300","parameter1Type":"num","parameter2":"","parameter2Type":"auto","parameter3":"RESIZE_BEZIER","parameter3Type":"resizeMode","parameter4":"150","parameter4Type":"num","parameter5":"","parameter5Type":"msg","parameter6":"","parameter6Type":"msg","parameter7":"","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","sendProperty":"payload","sendPropertyType":"msg","parameterCount":3,"jimpFunction":"resize","selectedJimpFunction":{"name":"resize","fn":"resize","description":"resize the image. One of the w or h parameters can be set to automatic (\"Jimp.AUTO\" or -1).","parameters":[{"name":"w","type":"num|auto","required":true,"hint":"the width to resize the image to (or \"Jimp.AUTO\" or -1)"},{"name":"h","type":"num|auto","required":true,"hint":"the height to resize the image to (or \"Jimp.AUTO\" or -1)"},{"name":"mode","type":"resizeMode","required":false,"hint":"a scaling method (e.g. Jimp.RESIZE_BEZIER)"}]},"x":1710,"y":440,"wires":[["408252b3d66b03a7"]]}]

Lastly, since you replied to the thread (and not to my comment) I had no idea you had replied (i dont get a notification unless you use the Reply button next to my comment - not the reply button at the bottom of the thread)

Look at the flows library (link at the top of forum) and search the forum - grabbing a picture from a camera has been covered many many times.

Yes I've seen them just wanted to paint the full picture

It worked with the clean image but if I wanted to read for example a cocoa cola barcode sadly it no longer works for me
This is why I needed the clean up node

Then why did you send a clean image????

Are you wanting to scan many different type in different orientations / different surfaces? The underlying decode library is not ideal in this regard. So unless you can get repeatable images fed in, this is not going to be easy & you would probably be better off buying a cheap barcode scanner that interfaces with the PI to feed results to node-red.

Because it was the fastest way to get a barcode
Anyway, thanks for the help

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