Based on the following interesting link:
I have created following flow
[{"id":"bc2c036f.64fdd","type":"tab","label":"camera","disabled":false,"info":""},{"id":"8034150c.af4418","type":"http in","z":"bc2c036f.64fdd","name":"","url":"/camera","method":"get","upload":false,"swaggerDoc":"","x":120,"y":100,"wires":[["47244028.f6766"]]},{"id":"d30eb1de.5a647","type":"http response","z":"bc2c036f.64fdd","name":"","statusCode":"","headers":{},"x":810,"y":100,"wires":[]},{"id":"47244028.f6766","type":"template","z":"bc2c036f.64fdd","name":"take/select photo and upload","field":"payload","fieldType":"msg","format":"html","syntax":"plain","template":"<!DOCTYPE html>\n<html>\n<head>\n <title>Take or select photo</title>\n <script type=\"text/javascript\">\n // The code on this page comes from: \n // https://www.codepool.biz/take-a-photo-and-upload-it-on-mobile-phones-with-html5.html\n function fileSelected() {\n var count = document.getElementById('fileToUpload').files.length;\n document.getElementById('details').innerHTML = \"\";\n for (var index = 0; index < count; index ++)\n {\n var file = document.getElementById('fileToUpload').files[index];\n var fileSize = 0;\n if (file.size > 1024 * 1024)\n fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';\n else\n fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';\n document.getElementById('details').innerHTML += 'Name: ' + file.name + '<br>Size: ' + fileSize + '<br>Type: ' + file.type;\n document.getElementById('details').innerHTML += '<p>';\n }\n }\n function uploadFile() {\n var fd = new FormData();\n var count = document.getElementById('fileToUpload').files.length;\n for (var index = 0; index < count; index ++)\n {\n var file = document.getElementById('fileToUpload').files[index];\n fd.append(file.name, file);\n }\n var xhr = new XMLHttpRequest();\n xhr.upload.addEventListener(\"progress\", uploadProgress, false);\n xhr.addEventListener(\"load\", uploadComplete, false);\n xhr.addEventListener(\"error\", uploadFailed, false);\n xhr.addEventListener(\"abort\", uploadCanceled, false);\n xhr.open(\"POST\", \"upload_file\");\n xhr.send(fd);\n }\n\n function uploadProgress(evt) {\n if (evt.lengthComputable) {\n var percentComplete = Math.round(evt.loaded * 100 / evt.total);\n document.getElementById('progress').innerHTML = percentComplete.toString() + '%';\n }\n else {\n document.getElementById('progress').innerHTML = 'unable to compute';\n }\n }\n\n function uploadComplete(evt) {\n /* This event is raised when the server sends back a response */\n alert(evt.target.responseText);\n }\n\n function uploadFailed(evt) {\n alert(\"There was an error attempting to upload the file.\");\n }\n\n function uploadCanceled(evt) {\n alert(\"The upload has been canceled by the user or the browser dropped the connection.\");\n }\n\n </script>\n</head>\n\n<body>\n <form id=\"form1\" enctype=\"multipart/form-data\" method=\"post\" action=\"upload_file\">\n <div>\n <label for=\"fileToUpload\">Take or select photo: </label><br />\n <input type=\"file\" name=\"fileToUpload\" id=\"fileToUpload\" onchange=\"fileSelected();\" accept=\"image/*\" capture=\"camera\" />\n </div>\n <div id=\"details\"></div>\n <div>\n <input type=\"button\" onclick=\"uploadFile()\" value=\"Upload\" />\n </div>\n <div id=\"progress\"></div>\n </form>\n</body>\n</html>","output":"str","x":520,"y":100,"wires":[["d30eb1de.5a647"]]},{"id":"5e233b94.b4dd84","type":"http in","z":"bc2c036f.64fdd","name":"","url":"upload_file","method":"post","upload":true,"swaggerDoc":"","x":140,"y":200,"wires":[["be60433e.90ec1","a6291ff2.65a8e"]]},{"id":"ad665769.14da28","type":"http response","z":"bc2c036f.64fdd","name":"","statusCode":"","headers":{},"x":850,"y":200,"wires":[]},{"id":"8c21a2ff.3d4d7","type":"template","z":"bc2c036f.64fdd","name":"response text","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Thank you, we have successfully received \"{{payload.filename}}\" (size = {{payload.filesizeKB}}KB )","output":"str","x":680,"y":200,"wires":[["ad665769.14da28"]]},{"id":"be60433e.90ec1","type":"debug","z":"bc2c036f.64fdd","name":"upload_file [post]","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":310,"y":160,"wires":[]},{"id":"a6291ff2.65a8e","type":"change","z":"bc2c036f.64fdd","name":"set filename, filesizeKB","rules":[{"t":"set","p":"payload.filename","pt":"msg","to":"req.files[0].fieldname","tot":"msg"},{"t":"set","p":"payload.filesize","pt":"msg","to":"req.files[0].size","tot":"msg"},{"t":"set","p":"payload.filesizeKB","pt":"msg","to":"$round(payload.filesize/1024)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":200,"wires":[["8c21a2ff.3d4d7"]]},{"id":"27009030.02da4","type":"comment","z":"bc2c036f.64fdd","name":"Documentation","info":"This node is based on https://www.codepool.biz/take-a-photo-and-upload-it-on-mobile-phones-with-html5.html\n\n# Usage\n\n * On your mobile phone navigate to `<your Node-RED-editor-url>/camera`\n * Click on `Choose File` button to take a photo.\n * Click on `Upload` button to send the photo to Node-RED","x":100,"y":40,"wires":[]}]
This flow creates a simple webpage at <your Node-RED-editor-url>/camera
which allows you to take a photo and send it to node-red. The URL also works in the browser of your laptop but in that case you won't be able to take a photo, but instead you can select a photo from your hard disk.
I think that this flow also addresses the security issues raised in previous post. So Node-RED doesn't get access to the camera. Only photos that the mobile phone user has explicitly uploaded by pushing the upload button will be send to Node-RED.