Test node-opencv flow

using https://github.com/akshonesports/node-opencv and opencv 3 This is a basic motion detection (with a mask image), a rework of a python program. You will need a '/home/pi/mask.png' at 640x480 - areas covered with green will not be considered for motion. I'll leave the rest for your investigation.

[{"id":"9976f30b.f9164","type":"inject","z":"160657d4.0b6df8","name":"","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"x":90,"y":60,"wires":[["7429233b.a4775c"]]},{"id":"e87246ba.e7e708","type":"function","z":"160657d4.0b6df8","name":"GetImage","func":"\nif (msg.payload === 0){\n    var vid = flow.get('cvvid');\n    if (vid){\n        node.warn(util.inspect(vid));\n        vid.release();\n        flow.set('cvvid', null);\n        delete vid;\n    }\n}\n\n\nif (msg.payload === 1){\n    try{\n        flow.set('start', null);\n        flow.set('count', null);\n        flow.set('last_s', null);\n\n        var cv = flow.get('cv');\n        var vid = new cv.VideoCapture(0);\n        node.warn(vid);\n        flow.set('cvvid', vid);\n    } catch (e){\n        node.warn(e);\n    }\n}\n\nif ((msg.payload !== 0) && (msg.payload !== 1)){\n    var vid = flow.get('cvvid');\n    \n    if (vid){\n        try{\n            //vid.grab(function(err, im)\n            {\n                //node.warn(\"grabbed \" + util.inspect(err) + \" \"+util.inspect(im));\n                vid.read(function(err, im){\n                    try{\n                        //node.warn(\"read \" + util.inspect(err) + \" \"+util.inspect(im));\n                        if (err) return;\n                        //im = im[0];\n                        //node.warn(util.inspect(im));\n                        //if (im.size()[0] > 0 && im.size()[1] > 0)\n                        {\n                            \n                            msg.img = im;\n                            msg.timestamp = msg.payload;\n                            node.send(msg);\n                        }\n                    } catch(e){\n                        node.warn(e);\n                    }\n                });\n                \n            }\n            //);\n\n        } catch (e){\n            node.warn(e);\n        }\n    }\n}\n","outputs":1,"noerr":0,"x":380,"y":60,"wires":[["1fff581b.4bde48"]]},{"id":"a13554e8.b2cf68","type":"debug","z":"160657d4.0b6df8","name":"","active":false,"console":"false","complete":"true","x":950,"y":100,"wires":[]},{"id":"9bde0579.c57fa8","type":"inject","z":"160657d4.0b6df8","name":"","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"x":90,"y":220,"wires":[["e87246ba.e7e708"]]},{"id":"118b6763.b77189","type":"file","z":"160657d4.0b6df8","name":"","filename":"","appendNewline":false,"createDir":false,"overwriteFile":"true","x":1170,"y":240,"wires":[]},{"id":"48fbf063.5e865","type":"inject","z":"160657d4.0b6df8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":100,"y":20,"wires":[["e87246ba.e7e708"]]},{"id":"7a46df27.2a26c","type":"function","z":"160657d4.0b6df8","name":"ReleaseImages","func":"if (msg.img){\n    //msg.payload = msg.img.toBuffer();\n    \n    //msg.img.release();\n    msg.gray.release();\n    msg.masked.release();\n    \n}\n\nreturn msg;","outputs":1,"noerr":0,"x":640,"y":540,"wires":[["a41685d2.95e268"]]},{"id":"2cfee3ee.0a053c","type":"function","z":"160657d4.0b6df8","name":"SetFilename","func":"\nmsg.filename = '/home/pi/' + msg.timestamp + '.jpg';\n\nreturn msg;","outputs":1,"noerr":0,"x":1170,"y":200,"wires":[[]]},{"id":"a41685d2.95e268","type":"function","z":"160657d4.0b6df8","name":"","func":"var count = flow.get('count') || 0;\ncount++;\nflow.set('count', count);\n\nvar start = flow.get('start');\n\nif ((start === undefined) || (start === null))\n    start = (new Date()).valueOf();\nflow.set('start', start);\n\nvar now = (new Date()).valueOf();\n\nvar s = now - start;\nvar fps = (((count/(s/1000))*100)>>0)/100;\n\nvar last_s = flow.get('last_s');\n\nif ((s/1000)>>0 !== (last_s/1000)>>0){\n    node.warn(\"count \"+count+\" fps \"+fps+\" t \"+s/1000);\n}\n\nflow.set('last_s', s);\n\nvar newmsg = { payload: (new Date()).valueOf() };\nreturn newmsg;","outputs":1,"noerr":0,"x":270,"y":420,"wires":[["e87246ba.e7e708"]]},{"id":"7edf07e0.359938","type":"function","z":"160657d4.0b6df8","name":"AddText","func":"if (msg.img){\n    var text = 'Hello';\n    msg.img.putText(text, 10, 20,\n            \"HERSEY_SIMPLEX\", [0, 0, 0], 0.5, 3);\n    msg.img.putText(text, 10, 20,\n            \"HERSHEY_SIMPLEX\", [255, 255, 255], 0.5, 1);\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":1000,"y":200,"wires":[["2cfee3ee.0a053c"]]},{"id":"936359ad.d48278","type":"function","z":"160657d4.0b6df8","name":"LoadCV","func":"var require = global.get('require');\nvar cv = require.main.require('opencv');\n\nvar cvdesc = util.inspect(cv);\nnode.send([null, {payload:cvdesc}]);\n\nflow.set('cv', cv);\n\nreturn msg;","outputs":"2","noerr":0,"x":140,"y":140,"wires":[["5cf6e327.ca5d8c"],[]]},{"id":"5cf6e327.ca5d8c","type":"function","z":"160657d4.0b6df8","name":"GetMask","func":"var cv = flow.get('cv');\n\ncv.readImage(\"/home/pi/mask.png\", function(err, img){\n    try {\n        if (err){\n            node.warn(err);\n            return;\n        }\n    \n        img = img.resize({width:640, height:480});\n        \n        \n        node.warn(util.inspect(img));\n        node.warn('before not')\n\n        var lower = [0,250,0];\n        var upper = [0,255,0];\n\n        img.inRange(lower, upper);\n        \n        \n        img.bitwiseNot(img);\n        node.warn('notted')\n        \n        node.warn('resized');\n        \n        var notmask = flow.get('mask');\n        if (notmask) notmask.release();\n        flow.set('notmask', img);\n        \n        node.send(msg);    \n        node.warn(\"sent mask\");\n    } catch (e) {\n        node.warn(e);\n    }\n});\n\n","outputs":1,"noerr":0,"x":180,"y":180,"wires":[["e87246ba.e7e708"]]},{"id":"920386ac.a58f48","type":"function","z":"160657d4.0b6df8","name":"MaskImage","func":"\nvar cv = flow.get('cv');\nvar mask = flow.get('notmask');\n\ntry{\n    //node.warn(msg.img.width());\n    //node.warn(mask.width());\n    var resized = msg.img.resize({width:640, height:480});\n    \n    var newimg = new cv.Matrix(resized.width(), resized.height());\n    //var newimg = msg.img.resize({width:640, height:480});\n    //msg.img = resized;\n    resized.copyWithMask(newimg, mask);\n    resized.release();\n    //msg.img.release();\n    \n    msg.masked = newimg;\n    \n    //msg.img.bitwiseAnd(msg.img, msg.img, mask);\n    return msg;\n} catch (e) {\n    node.warn(e)\n}\n\n","outputs":1,"noerr":0,"x":610,"y":120,"wires":[["1f33ca57.83ff96"]]},{"id":"889fdd83.0309e","type":"catch","z":"160657d4.0b6df8","name":"","scope":null,"x":80,"y":520,"wires":[["3a72b51a.44e24a"]]},{"id":"3a72b51a.44e24a","type":"debug","z":"160657d4.0b6df8","name":"","active":true,"console":"false","complete":"false","x":270,"y":520,"wires":[]},{"id":"d048fc1f.980fc","type":"function","z":"160657d4.0b6df8","name":"AddGreyScale","func":"var cv = flow.get('cv');\n\nmsg.gray = msg.masked.copy();\n\n\ntry{\n    msg.gray.convertGrayscale();\n} catch (e){\n    node.warn(e);\n}\n//node.warn(\"greyscaled\");\n\nreturn msg;","outputs":1,"noerr":0,"x":620,"y":160,"wires":[["cb4d6b4b.4713f8"]]},{"id":"d0e81c8f.c4306","type":"function","z":"160657d4.0b6df8","name":"blur","func":"\ntry{\n    msg.gray.gaussianBlur([21, 21], 0)\n} catch (e){\n    node.warn(e);\n}\n//node.warn(\"blurred\");\nreturn msg;","outputs":1,"noerr":0,"x":590,"y":200,"wires":[["97dbc938.6b8748"]]},{"id":"50c81625.5e2668","type":"function","z":"160657d4.0b6df8","name":"average","func":"var cv = flow.get('cv');\n\nvar avg = flow.get('avg');\navg = avg || null\n\ntry {\n    if (!avg){\n        avg = msg.gray.copy();\n        flow.set('avg', avg);\n    }\n} catch(e) {\n    node.warn(e);\n}\n//node.warn(\"copied\");\n\n\ntry{\n    var result = new cv.Matrix(msg.gray.width(), msg.gray.height());\n    result.addWeighted(avg, 0.7, msg.gray, 0.3);\n    avg.release();\n    avg = result;\n    flow.set('avg', avg);\n    msg.avg = avg;\n} catch(e) {\n    node.warn(e);\n}\n//node.warn(\"add Weighted\");\n\n\n\nreturn msg;","outputs":1,"noerr":0,"x":600,"y":240,"wires":[["cd872b16.f51ea8"]]},{"id":"1faa8aed.e55ef5","type":"function","z":"160657d4.0b6df8","name":"get diff","func":"var cv = flow.get('cv');\n\ntry{\n    var result = new cv.Matrix(msg.gray.width(), msg.gray.height());\n    \n    result.absDiff(msg.avg, msg.gray);\n\n    msg.diff = result;\n    //node.warn(\"got diff\");\n} catch(e) {\n    node.warn(e);\n}\n\n\nreturn msg;","outputs":1,"noerr":0,"x":590,"y":280,"wires":[["5f105302.00c12c"]]},{"id":"969608f0.bb8128","type":"function","z":"160657d4.0b6df8","name":"getContours","func":"var cv = flow.get('cv');\n\ntry{\n    minthresh = flow.get(\"minthresh\");\n\n    var thresh = msg.diff.threshold(minthresh, 255, 'Binary');    \n    //node.warn('got thresh ' + util.inspect (thresh));\n    thresh.dilate( 2 );\n    //node.warn('dilated thresh ' + util.inspect (thresh));\n    var cnts = thresh.findContours(cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);\n    msg.cnts = cnts;\n    //node.warn(\"got cnts\");\n} catch(e) {\n    node.warn(e);\n}\n\nreturn msg;\n","outputs":1,"noerr":0,"x":610,"y":320,"wires":[["ef1d7197.fc387"]]},{"id":"f56d3f08.0e4af","type":"function","z":"160657d4.0b6df8","name":"loop over contours","func":"\nvar numcnts = msg.cnts.size();\nvar area = flow.get(\"area\");\n\nvar movementfound = false;\n\nfor (var c = 0; c < numcnts; c++){\n    if (msg.cnts.area(c) > area){\n        var bounding = msg.cnts.boundingRect(c);\n        node.error(bounding);\n        msg.img.rectangle([bounding.x, bounding.y], [bounding.width, bounding.height], [0, 0, 255], 2);\n        movementfound = true;\n    }\n}\n\nmsg.movement = movementfound;\n\nvar prevmv = flow.get('prevmv');\nif(movementfound){\n    if (!prevmv){\n        node.send([null, {payload:1}]);\n        node.warn(\"movement\");\n    }\n} else {\n    if (prevmv){\n        node.send([null, {payload:0}]);\n        node.warn(\"no movement\");\n    }\n}\nflow.set('prevmv', movementfound);\n\nreturn msg;\n","outputs":"2","noerr":0,"x":630,"y":360,"wires":[["d5899f37.0b0f8"],["868aa259.67e48"]],"outputLabels":["","movement"]},{"id":"1ab7e8d3.368717","type":"function","z":"160657d4.0b6df8","name":"SetDiff","func":"if (msg.diff){\n    var diff = flow.get('diff');\n    if (diff)\n        diff.release();\n    flow.set(\"diff\", msg.diff);\n}\n","outputs":1,"noerr":0,"x":750,"y":300,"wires":[[]]},{"id":"3f7d198f.f6ae56","type":"http in","z":"160657d4.0b6df8","name":"","url":"/diff","method":"get","upload":false,"swaggerDoc":"","x":1040,"y":580,"wires":[["bffa24ab.25c5b8"]]},{"id":"bffa24ab.25c5b8","type":"function","z":"160657d4.0b6df8","name":"","func":"var diff = flow.get('diff');\n//node.warn(diff);\nif (diff)\n    msg.payload = diff.toBuffer();\nelse\n    msg.payload = '';\n\nreturn msg;","outputs":1,"noerr":0,"x":1190,"y":580,"wires":[["a9962507.9870a8"]]},{"id":"a9962507.9870a8","type":"http response","z":"160657d4.0b6df8","name":"","statusCode":"","headers":{"content-type":"image/jpeg"},"x":1350,"y":580,"wires":[]},{"id":"5f105302.00c12c","type":"function","z":"160657d4.0b6df8","name":"asyncsplit","func":"setTimeout(function(){node.send([msg, null])}, 0);\nsetTimeout(function(){node.send([null, msg])}, 0);\n","outputs":"2","noerr":0,"x":440,"y":320,"wires":[["1ab7e8d3.368717"],["969608f0.bb8128"]]},{"id":"29055bd9.2202e4","type":"http in","z":"160657d4.0b6df8","name":"","url":"/diffs","method":"get","upload":false,"swaggerDoc":"","x":1040,"y":620,"wires":[["c522c1bf.5d4fb"]]},{"id":"49abef4b.b65e2","type":"http response","z":"160657d4.0b6df8","name":"","statusCode":"","headers":{},"x":1390,"y":620,"wires":[]},{"id":"c522c1bf.5d4fb","type":"template","z":"160657d4.0b6df8","name":"listtemplate","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<html>\n<head>\n<meta http-equiv=\"refresh\" content=\"0.1\" >    \n</head>\n<body>\n    <img src=\"\\diff\"></img>\n</body>\n</html>\n","output":"str","x":1230,"y":620,"wires":[["49abef4b.b65e2"]]},{"id":"be77b7ce.167cc8","type":"http in","z":"160657d4.0b6df8","name":"","url":"/avg","method":"get","upload":false,"swaggerDoc":"","x":1040,"y":480,"wires":[["57bb065a.cce028"]]},{"id":"57bb065a.cce028","type":"function","z":"160657d4.0b6df8","name":"","func":"var avg = flow.get('avg');\n//node.warn(diff);\nif (avg)\n    msg.payload = avg.toBuffer();\nelse\n    msg.payload = '';\nreturn msg;","outputs":1,"noerr":0,"x":1190,"y":480,"wires":[["31cbd341.94334c"]]},{"id":"31cbd341.94334c","type":"http response","z":"160657d4.0b6df8","name":"","statusCode":"","headers":{"content-type":"image/jpeg"},"x":1350,"y":480,"wires":[]},{"id":"e279fa1c.7e43d8","type":"http in","z":"160657d4.0b6df8","name":"","url":"/avgs","method":"get","upload":false,"swaggerDoc":"","x":1040,"y":520,"wires":[["ca0564ac.9c9478"]]},{"id":"38a16fc.550779","type":"http response","z":"160657d4.0b6df8","name":"","statusCode":"","headers":{},"x":1390,"y":520,"wires":[]},{"id":"ca0564ac.9c9478","type":"template","z":"160657d4.0b6df8","name":"listtemplate","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<html>\n<head>\n<meta http-equiv=\"refresh\" content=\"0.1\" >    \n</head>\n<body>\n    <img src=\"\\avg\"></img>\n</body>\n</html>\n","output":"str","x":1230,"y":520,"wires":[["38a16fc.550779"]]},{"id":"1fff581b.4bde48","type":"function","z":"160657d4.0b6df8","name":"asyncsplit","func":"setTimeout(function(){node.send([msg, null])}, 0);\nsetTimeout(function(){node.send([null, msg])}, 0);\n","outputs":"2","noerr":0,"x":440,"y":120,"wires":[["920386ac.a58f48"],[]]},{"id":"1f33ca57.83ff96","type":"function","z":"160657d4.0b6df8","name":"asyncsplit","func":"setTimeout(function(){node.send([msg, null])}, 0);\nsetTimeout(function(){node.send([null, msg])}, 0);\n","outputs":"2","noerr":0,"x":440,"y":160,"wires":[["d048fc1f.980fc"],[]]},{"id":"cb4d6b4b.4713f8","type":"function","z":"160657d4.0b6df8","name":"asyncsplit","func":"setTimeout(function(){node.send([msg, null])}, 0);\nsetTimeout(function(){node.send([null, msg])}, 0);\n","outputs":"2","noerr":0,"x":440,"y":200,"wires":[["d0e81c8f.c4306"],[]]},{"id":"d5899f37.0b0f8","type":"function","z":"160657d4.0b6df8","name":"SetImg","func":"if (msg.img){\n    var img = flow.get('img');\n    if (img)\n        img.release();\n    flow.set(\"img\", msg.img);\n}\nreturn msg;\n","outputs":1,"noerr":0,"x":600,"y":400,"wires":[["88c36d3d.72b94"]]},{"id":"ae95ba4d.604e68","type":"http in","z":"160657d4.0b6df8","name":"","url":"/img","method":"get","upload":false,"swaggerDoc":"","x":1040,"y":380,"wires":[["abf3083b.384de8"]]},{"id":"abf3083b.384de8","type":"function","z":"160657d4.0b6df8","name":"","func":"var avg = flow.get('img');\n//node.warn(diff);\nif (avg)\n    msg.payload = avg.toBuffer();\nelse\n    msg.payload = '';\nreturn msg;","outputs":1,"noerr":0,"x":1190,"y":380,"wires":[["aef27b6e.2265d8"]]},{"id":"aef27b6e.2265d8","type":"http response","z":"160657d4.0b6df8","name":"","statusCode":"","headers":{"content-type":"image/jpeg"},"x":1350,"y":380,"wires":[]},{"id":"9e2ce556.bb40b8","type":"http in","z":"160657d4.0b6df8","name":"","url":"/imgs","method":"get","upload":false,"swaggerDoc":"","x":1040,"y":420,"wires":[["85629851.bff758"]]},{"id":"adef0482.6f5288","type":"http response","z":"160657d4.0b6df8","name":"","statusCode":"","headers":{},"x":1390,"y":420,"wires":[]},{"id":"85629851.bff758","type":"template","z":"160657d4.0b6df8","name":"listtemplate","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<html>\n<head>\n<meta http-equiv=\"refresh\" content=\"0.1\" >    \n</head>\n<body>\n    <img src=\"\\img\"></img>\n</body>\n</html>\n","output":"str","x":1230,"y":420,"wires":[["adef0482.6f5288"]]},{"id":"88c36d3d.72b94","type":"function","z":"160657d4.0b6df8","name":"100ms delay","func":"setTimeout(function(){node.send([msg, null])}, 100);\nsetTimeout(function(){node.send([null, msg])}, 100);\n","outputs":"2","noerr":0,"x":450,"y":440,"wires":[["7a46df27.2a26c"],[]]},{"id":"69c95457.54910c","type":"http in","z":"160657d4.0b6df8","name":"","url":"/notmask","method":"get","upload":false,"swaggerDoc":"","x":1050,"y":300,"wires":[["b0d5cd93.88f9a"]]},{"id":"b0d5cd93.88f9a","type":"function","z":"160657d4.0b6df8","name":"","func":"var avg = flow.get('notmask');\n//node.warn(diff);\nif (avg)\n    msg.payload = avg.toBuffer();\nelse\n    msg.payload = '';\nreturn msg;","outputs":1,"noerr":0,"x":1190,"y":300,"wires":[["fa0e28d9.5cb4f8"]]},{"id":"fa0e28d9.5cb4f8","type":"http response","z":"160657d4.0b6df8","name":"","statusCode":"","headers":{"content-type":"image/jpeg"},"x":1350,"y":300,"wires":[]},{"id":"97dbc938.6b8748","type":"function","z":"160657d4.0b6df8","name":"asyncsplit","func":"setTimeout(function(){node.send([msg, null])}, 0);\nsetTimeout(function(){node.send([null, msg])}, 0);\n","outputs":"2","noerr":0,"x":440,"y":240,"wires":[["50c81625.5e2668"],[]]},{"id":"cd872b16.f51ea8","type":"function","z":"160657d4.0b6df8","name":"asyncsplit","func":"setTimeout(function(){node.send([msg, null])}, 0);\nsetTimeout(function(){node.send([null, msg])}, 0);\n","outputs":"2","noerr":0,"x":440,"y":280,"wires":[["1faa8aed.e55ef5"],[]]},{"id":"ef1d7197.fc387","type":"function","z":"160657d4.0b6df8","name":"asyncsplit","func":"setTimeout(function(){node.send([msg, null])}, 0);\nsetTimeout(function(){node.send([null, msg])}, 0);\n","outputs":"2","noerr":0,"x":440,"y":360,"wires":[["f56d3f08.0e4af"],[]]},{"id":"7429233b.a4775c","type":"function","z":"160657d4.0b6df8","name":"Variables","func":"\nflow.set(\"area\", 500);\nflow.set(\"minthresh\", 16);\n\nreturn msg;","outputs":1,"noerr":0,"x":120,"y":100,"wires":[["936359ad.d48278"]]},{"id":"868aa259.67e48","type":"ui_chart","z":"160657d4.0b6df8","name":"","group":"79fe411f.39187","order":0,"width":0,"height":0,"label":"chart","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"x":860,"y":420,"wires":[[],[]]},{"id":"79fe411f.39187","type":"ui_group","z":"","name":"pond","tab":"ff210cde.54ae6","disp":true,"width":"6"},{"id":"ff210cde.54ae6","type":"ui_tab","z":"","name":"Home","icon":"dashboard"}]
btsimonh

Flow Info

created 1 month ago

Node Types

Core
  • catch (x1)
  • debug (x2)
  • file (x1)
  • function (x29)
  • http in (x7)
  • http response (x7)
  • inject (x3)
  • template (x3)
Other
  • ui_chart (x1)
  • ui_group (x1)
  • ui_tab (x1)

Tags

  • opencv
  • motion
  • video
  • raspberry
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option