-
Notifications
You must be signed in to change notification settings - Fork 282
/
visualreco
1 lines (1 loc) · 20.4 KB
/
visualreco
1
[{"id":"bba7a490.62287","type":"change","z":"17b46e42.bbdc6a","name":"Extract image URL","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.imageurl","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":100,"wires":[["44d21610.3a0d2"]]},{"id":"fb36f3b8.74512","type":"switch","z":"17b46e42.bbdc6a","name":"Check image url","property":"payload.imageurl","propertyType":"msg","rules":[{"t":"null"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":360,"y":60,"wires":[["e7d6615.e9a7ba"],["bba7a490.62287"]]},{"id":"f6876aaf.532ef","type":"http in","z":"17b46e42.bbdc6a","name":"","url":"/visualrecognition1","method":"get","upload":false,"swaggerDoc":"","x":140,"y":60,"wires":[["fb36f3b8.74512"]]},{"id":"e7d6615.e9a7ba","type":"template","z":"17b46e42.bbdc6a","name":"Simpe Web Page","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<h1>Welcome to a Watson Visual Recognition sample image app</h1>\n<hr>\n<h2>Create a Watson Visual Recognition Custom Classifier</h2>\n<p>Upload 10 images and train a Watson Visual Recognition Custom Classifier</p>\n\n<form action=\"/upload2zip_post\" method=\"POST\" enctype=\"multipart/form-data\">\n <br>Step 1: Submit a name for this Custom Classifier:<br>\n <input type=\"text\" name=\"ClassifierName\"/>\n <br><br>Step 2: Select (10 or more) POSITIVE .png/.jpg files to be uploaded and zipped:<br>\n <input type=\"file\" name=\"Positive\" multiple/>\n <br><br>Step 3: Select (10 or more) NEGATIVE .png/.jpg files to be uploaded and zipped:<br>\n <input type=\"file\" name=\"Negative\" multiple/>\n <br><br>Step 4: Train a custom classifier<br>\n <input type=\"submit\" value=\"Zip and Train\">\n</form>\n<hr>\n<h2>Test Watson Visual Recognition</h2>\n<p>Copy/Paste a URL to any image on the Internet to be classified:</p>\n<form action=\"{{req._parsedUrl.pathname}}\">\n <br/>Paste the URL in the box below.<br/>\n <br>Image URL: <input type=\"text\" name=\"imageurl\"/>\n <input type=\"submit\" value=\"Analyze Image URL\"/>\n</form>\n<hr>\n<p>Upload a file to be classified:</p>\n\n<form action=\"/uploadsimple_post\" method=\"POST\" enctype=\"multipart/form-data\">\n <input type=\"file\" name=\"myFile\"/>\n <input type=\"submit\" value=\"Analyze File\">\n</form>\n<hr>","x":810,"y":60,"wires":[["7f9fd213.b77714"]]},{"id":"7f9fd213.b77714","type":"http response","z":"17b46e42.bbdc6a","name":"","statusCode":"","headers":{},"x":1070,"y":340,"wires":[]},{"id":"6528eb00.0c0544","type":"debug","z":"17b46e42.bbdc6a","name":"Print msg.result.images","active":true,"console":"false","complete":"result.images","x":630,"y":400,"wires":[]},{"id":"d0b84d61.987db8","type":"comment","z":"17b46e42.bbdc6a","name":"Step #1 - Create a Visual Recognition Service","info":"1. Log into your Bluemix account\n2. Navigate to the Bluemix Catalog\n3. Scroll to the Watson Services section\n4. Find and click on the Visual Recognition service\n5. Create an unbounded Visual Recognition instance\n6. Open the new service and navigate to the Service Credentials\n7. Copy the api_key to the clipboard\n8. Open the above \"visual recognition v3\" node and paste your new API Key","x":260,"y":420,"wires":[]},{"id":"ed1313fd.bbe858","type":"function","z":"17b46e42.bbdc6a","name":"Process Results - Multiple Classifiers","func":"if (typeof msg.result == 'undefined') {\n return null;\n}\n\nif (typeof msg.result.error != 'undefined') {\n //The Lite Plan allows users to make 7,500 API calls for free\n // Daily limit is (up to 250 calls per day)\n // {\"status\":\"ERROR\",\"statusInfo\":\"Key is over transaction limit\"}\n msg.template = msg.result.error.message;\n return msg;\n}\n\n// Text Extraction\nif (typeof msg.result.images[0].text != 'undefined') {\n var image_text = msg.result.images[0].text;\n msg.payload = image_text;\n msg.template = image_text;\n if( image_text.length >0 ) {\n msg.template= \"Watson found the words: \"+image_text;\n }\n return msg;\n}\n\nvar c_id = 0;\nvar WhichClassifier = [];\n\nfor ( c_id=0; c_id < (msg.result.images[0].classifiers.length); c_id++ ){\n var bestcolor = -1;\n var colorscore = 0;\n var item = \"\";\n // find the best color, if any\n for( i =0; i<(msg.result.images[0].classifiers[c_id].classes.length); i++ ){\n if( typeof msg.result.images[0].classifiers[c_id].classes[i] != 'undefined') {\n if( typeof msg.result.images[0].classifiers[c_id].classes[i].class != 'undefined') {\n var object = msg.result.images[0].classifiers[c_id].classes[i].class;\n if ( object.includes(\"color\") ) {\n if( msg.result.images[0].classifiers[c_id].classes[i].score > colorscore){\n bestcolor = i;\n colorscore = msg.result.images[0].classifiers[c_id].classes[i].score;\n }\n }\n } \n } \n }\n\n var bestItem = 0;\n var itemScore = 0;\n for( i =0; i<(msg.result.images[0].classifiers[c_id].classes.length); i++ ){\n if( typeof msg.result.images[0].classifiers[c_id].classes[i] != 'undefined') {\n if( typeof msg.result.images[0].classifiers[c_id].classes[i].class != 'undefined') {\n var object = msg.result.images[0].classifiers[c_id].classes[i].class;\n if ( !object.includes(\"color\") ) {\n if( msg.result.images[0].classifiers[c_id].classes[i].score > itemScore){\n // bestItem = i;\n bestItem = 0;\n itemScore = msg.result.images[0].classifiers[c_id].classes[i].score;\n }\n }\n }\n } \n }\n\n if( bestcolor != \"-1\") {\n // found a color\n if( msg.result.images[0].classifiers[c_id].classes.length > 0) {\n if( typeof msg.result.images[0].classifiers[c_id].classes[bestcolor].class != 'undefined') {\n item = msg.result.images[0].classifiers[c_id].classes[bestcolor].class + \" \" + msg.result.images[0].classifiers[c_id].classes[bestItem].class;\n }\n }\n bestcolor = -1;\n } else {\n if( msg.result.images[0].classifiers[c_id].classes.length > 0) {\n if( typeof msg.result.images[0].classifiers[c_id].classes[bestItem].class != 'undefined') {\n item = msg.result.images[0].classifiers[c_id].classes[bestItem].class;\n } \n } \n }\n \n WhichClassifier.push(\"Watson's \" + msg.result.images[0].classifiers[c_id].name + \" classifier thinks this picture contains a \" + item +\".<br>\");\n}\n\nvar picInfo = msg.result.images[0].classifiers[0].classes;\nvar arrayLength = picInfo.length;\nif( typeof(msg.result.images[0].resolved_url) != 'undefined' ) {\n msg.template=\"<p>Analyzed image: \"+ msg.result.images[0].resolved_url+\"<br/><img src=\"+msg.result.images[0].resolved_url+\" height=\\\"200\\\"/></p>\";\n} else {\n msg.template = \"<p>Analyzed image: \"+ msg.mypic;\n}\nmsg.template=msg.template+\"<style>\";\nmsg.template=msg.template+\"table { width: 440px; margin-top: 10px; }\";\nmsg.template=msg.template+\"tr:nth-child(even){background-color: #f2f2f2;}\";\nmsg.template=msg.template+\"th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; width: 10%;}\";\nmsg.template=msg.template+\"</style>\";\n\n// 1st Table\nmsg.template=msg.template+\"<h2>\"+WhichClassifier[0]+\"</h2><table span=100%><tr><th>Class</th><th>Confidence</th></tr>\";\nfor (var i = 0; i < arrayLength; i++) {\n msg.template = msg.template + \"<tr><td>\" + picInfo[i].class + \"</td><td>\" + picInfo[i].score + \"</td></tr>\";\n}\nmsg.template = msg.template + \"</table>\";\n\n// More than one classifier?\nif( msg.result.images[0].classifiers.length == 1 ) {\n msg.payload=msg.template;\n return msg;\n}\n\n// Next Classifier\npicInfo = msg.result.images[0].classifiers[1].classes;\narrayLength = picInfo.length;\n\n// 2nd Table\nmsg.template=msg.template+\"<h2>\"+WhichClassifier[1]+\"</h2><table span=100%><tr><th>Class</th><th>Confidence</th></tr>\";\nfor ( i = 0; i < arrayLength; i++) {\n msg.template = msg.template + \"<tr><td>\" + picInfo[i].class + \"</td><td>\" + picInfo[i].score + \"</td></tr>\";\n}\nmsg.template = msg.template + \"</table>\";\nmsg.payload=msg.template;\nreturn msg;\n","outputs":1,"noerr":0,"x":670,"y":360,"wires":[["7f9fd213.b77714"]]},{"id":"4c96eba9.f19f34","type":"visual-recognition-v3","z":"17b46e42.bbdc6a","name":"","vr-service-endpoint":"https://gateway.watsonplatform.net/visual-recognition/api","image-feature":"classifyImage","lang":"en","x":290,"y":380,"wires":[["6528eb00.0c0544","ed1313fd.bbe858"]]},{"id":"5ef99b26.d52054","type":"function","z":"17b46e42.bbdc6a","name":"Process Results - One Classifier","func":"if (typeof msg.result == 'undefined') {\n return null;\n}\n\nif (typeof msg.result.error != 'undefined') {\n //The Lite Plan allows users to make 7,500 API calls for free\n // Daily limit is (up to 250 calls per day) \n // {\"status\":\"ERROR\",\"statusInfo\":\"Key is over transaction limit\"}\n msg.template = msg.result.error.message;\n return msg;\n}\n\n// Text Extraction\nif (typeof msg.result.images[0].text != 'undefined') {\n var image_text = msg.result.images[0].text;\n msg.payload = image_text;\n msg.template = image_text;\n if( image_text.length >0 ) {\n msg.template= \"Watson found the words: \"+image_text;\n }\n return msg;\n}\n\nvar bestcolor = -1;\nvar colorscore = 0;\nvar c_id = 0;\nvar say = \"\";\nvar item;\n\nfor ( c_id=0; c_id < (msg.result.images[0].classifiers.length); c_id++ ){\n // find the best color, if any\n for( i =0; i<(msg.result.images[0].classifiers[c_id].classes.length); i++ ){\n var object = msg.result.images[0].classifiers[c_id].classes[i].class;\n if ( object.includes(\"color\") ) {\n if( msg.result.images[0].classifiers[c_id].classes[i].score > colorscore){\n bestcolor = i;\n colorscore = msg.result.images[0].classifiers[c_id].classes[i].score;\n }\n }\n }\n \n var bestItem = 0;\n var itemScore = 0;\n for( i =0; i<(msg.result.images[0].classifiers[c_id].classes.length); i++ ){\n var object = msg.result.images[0].classifiers[c_id].classes[i].class;\n if ( !object.includes(\"color\") ) {\n if( msg.result.images[0].classifiers[c_id].classes[i].score > itemScore){\n// bestItem = i;\n bestItem = 0;\n itemScore = msg.result.images[0].classifiers[c_id].classes[i].score;\n }\n }\n }\n \n if( bestcolor != \"-1\") {\n // found a color\n item = msg.result.images[0].classifiers[c_id].classes[bestcolor].class + \" \" + msg.result.images[0].classifiers[c_id].classes[bestItem].class;\n bestcolor = -1;\n } else {\n item = msg.result.images[0].classifiers[c_id].classes[bestItem].class;\n }\n// say = say + \" Watson's \" + msg.result.images[0].classifiers[c_id].name + \" classifier thinks this picture contains a \" + item +\".\";\n say = say + \" Watson thinks this picture contains a \" + item +\".\";\n}\nmsg.payload = say;\n\nvar picInfo = msg.result.images[0].classifiers[0].classes;\nvar arrayLength = picInfo.length;\nmsg.template=\"<p>Analyzed image: \"+ msg.result.images[0].resolved_url+\"<br/><img src=\"+msg.result.images[0].resolved_url+\" height=\\\"200\\\"/></p>\";\nmsg.template=msg.template+\"<style>\";\nmsg.template=msg.template+\"table { width: 440px; margin-top: 10px; }\";\nmsg.template=msg.template+\"tr:nth-child(even){background-color: #f2f2f2;}\";\nmsg.template=msg.template+\"th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; width: 10%;}\";\nmsg.template=msg.template+\"</style>\";\n\nmsg.template=msg.template+\"<h2>\"+say+\"</h2><table span=100%><tr><th>Class</th><th>Confidence</th></tr>\";\nfor (var i = 0; i < arrayLength; i++) {\n msg.template = msg.template + \"<tr><td>\" + picInfo[i].class + \"</td><td>\" + picInfo[i].score + \"</td></tr>\";\n}\nmsg.template = msg.template + \"</table>\";\nmsg.payload = msg.template;\nreturn msg;","outputs":1,"noerr":0,"x":680,"y":320,"wires":[["7f9fd213.b77714"]]},{"id":"bf1c7b30.007428","type":"debug","z":"17b46e42.bbdc6a","name":"","active":true,"tosidebar":true,"console":false,"complete":"req.files","x":350,"y":180,"wires":[]},{"id":"cbbeae19.3fc73","type":"comment","z":"17b46e42.bbdc6a","name":"Simple file upload example","info":"http://localhost:1880/upload","x":130,"y":180,"wires":[]},{"id":"94105122.7ce218","type":"http in","z":"17b46e42.bbdc6a","name":"","url":"/uploadsimple_post","method":"post","upload":true,"swaggerDoc":"","x":130,"y":220,"wires":[["bf1c7b30.007428","b47f2300.0b56"]]},{"id":"b47f2300.0b56","type":"change","z":"17b46e42.bbdc6a","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"req.files[0].buffer","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":370,"y":220,"wires":[["725368e9.f17df"]]},{"id":"725368e9.f17df","type":"function","z":"17b46e42.bbdc6a","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,"x":610,"y":220,"wires":[["44d21610.3a0d2"]]},{"id":"3eb4b04a.56a28","type":"comment","z":"17b46e42.bbdc6a","name":"Multiple file upload","info":"","x":150,"y":480,"wires":[]},{"id":"59b12c7c.8ba50c","type":"http in","z":"17b46e42.bbdc6a","name":"","url":"/upload2zip_post","method":"post","upload":true,"swaggerDoc":"","x":160,"y":520,"wires":[["377d5f68.ddee4","1942f58b.4293f2"]]},{"id":"377d5f68.ddee4","type":"debug","z":"17b46e42.bbdc6a","name":"","active":true,"tosidebar":true,"console":false,"complete":"req.files","x":390,"y":480,"wires":[]},{"id":"1942f58b.4293f2","type":"function","z":"17b46e42.bbdc6a","name":"Construct Zip File attributes","func":"// Confirm that all the files are images\nvar NumImages = msg.req.files.length ;\nvar AllImages = true;\n\n// Watson Visual Recognition requires a minimum of 10 images\n// to train a custom classifier\nif( NumImages < 2 ) {\n msg.payload = \"Watson Visual Recognition requires a minimum of 10 images to train a custom classifier\";\n return [msg, null] ;\n}\n\nfor( var i = 0; i < NumImages ; i++ ) {\n if ( !msg.req.files[i].mimetype.includes('image')) {\n // At least one file is not an image, throw an error\n AllImages = false ;\n }\n}\nif( !AllImages ) {\n msg.payload = \"Error Not all files are .png / .jpg image files\";\n return [msg, null] ;\n}\n\n// Step 1:\n// Install the node-red-contrib-zip Node-RED node\n//\n// Step 2:\n// Construct a msg.payload of an Array of files to be compressed into a ZIP object.\n// The ZipFile name is specified with msg.filename\n// Array: An array of objects containing 'filename' as a String and 'payload' as a Buffer/String\n// each representing one file in the resultiing zip\n\nvar PosZipArray = [];\nvar NegZipArray = [];\nfor( i = 0; i < NumImages ; i++ ) {\n if( msg.req.files[i].fieldname == \"Positive\") {\n PosZipArray.push( { \"filename\":msg.req.files[i].originalname, \"payload\":msg.req.files[i].buffer }) ;\n } else if ( msg.req.files[i].fieldname == \"Negative\") {\n NegZipArray.push( { \"filename\":msg.req.files[i].originalname, \"payload\":msg.req.files[i].buffer }) ;\n }\n}\nmsg.filename = msg.payload.ClassifierName;\n// Zip the Positive Example files first\nmsg.payload = PosZipArray ;\n// Store the Negative Examples for a second zip\nmsg.NegativeExamples = NegZipArray ;\n\nreturn [null,msg];","outputs":2,"noerr":0,"x":440,"y":520,"wires":[["7f9fd213.b77714"],["342762a1.ac529e","adfb998e.f43e3","8ec1e215.fda9f8"]]},{"id":"342762a1.ac529e","type":"change","z":"17b46e42.bbdc6a","name":"Success","rules":[{"t":"set","p":"payload","pt":"msg","to":"Zip file created! Watson Visual Recognition is Training a custom classifier","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":500,"wires":[["7f9fd213.b77714"]]},{"id":"adfb998e.f43e3","type":"debug","z":"17b46e42.bbdc6a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":730,"y":540,"wires":[]},{"id":"ca986845.7935a8","type":"visual-recognition-util-v3","z":"17b46e42.bbdc6a","name":"","vr-service-endpoint":"https://gateway-a.watsonplatform.net/visual-recognition/api","image-feature":"createClassifier","x":500,"y":700,"wires":[["d133bab8.8bedb8","83e16be9.a19ba8"]]},{"id":"46789d1f.54f464","type":"function","z":"17b46e42.bbdc6a","name":"Prepare to Create a Classifier","func":"// Create a Classifier\n// Provide the following input :\n// msg.params[\"name\"] : a string name that will be used as prefix for the returned classifier_id (Required)\n// msg.params[\"{classname}_positive_examples\"] : a Node.js binary Buffer of the ZIP that contains a minimum of 10 images. (Required)\n// msg.params[\"negative_examples\"] : a Node.js binary Buffer of the ZIP that contains a minimum of 10 images.(Optional)\n//\n// More information on this API documentation.\n// https://cloud.ibm.com/apidocs/visual-recognition#create-a-classifier\n\nvar classnamepos = msg.filename+\"_positive_examples\";\nmsg.params = {} ;\nmsg.params.name = msg.filename ;\nmsg.params.negative_examples = msg.payload\nmsg.params[classnamepos] = msg.PositiveExamplesZipped // zip file!\n\n// don't bother sending a big zip file to the Watson Visual Recognition Util node\n//msg.payload = \"\"; \n\nreturn msg ;","outputs":1,"noerr":0,"x":190,"y":700,"wires":[["ca986845.7935a8","5650b22f.f8496c"]]},{"id":"d133bab8.8bedb8","type":"debug","z":"17b46e42.bbdc6a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"result","targetType":"msg","x":730,"y":760,"wires":[]},{"id":"dbb22787.f39f7","type":"change","z":"17b46e42.bbdc6a","name":"Zip 2nd Set of Examples","rules":[{"t":"set","p":"PositiveExamplesZipped","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"NegativeExamples","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":620,"wires":[["f612b496.253eb"]]},{"id":"5650b22f.f8496c","type":"debug","z":"17b46e42.bbdc6a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"params","targetType":"msg","x":470,"y":760,"wires":[]},{"id":"83e16be9.a19ba8","type":"change","z":"17b46e42.bbdc6a","name":"","rules":[{"t":"set","p":"CustomClassifier","pt":"flow","to":"result.classifier_id","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":770,"y":700,"wires":[["e5d58a06.e7ddb"]]},{"id":"44d21610.3a0d2","type":"function","z":"17b46e42.bbdc6a","name":"Custom Classifier","func":"var CustomClassifier = flow.get(\"CustomClassifier\") || \"\";\nmsg.params = {};\n\n// Check if a Custom Classifier has been trained\nif( CustomClassifier.length ) {\n msg.params.classifier_ids = CustomClassifier + \",default\" ;\n} else {\n msg.params.classifier_ids = \"default\" ;\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":840,"y":160,"wires":[["4c96eba9.f19f34","b39c9564.d38df"]]},{"id":"b39c9564.d38df","type":"debug","z":"17b46e42.bbdc6a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"params","targetType":"msg","x":1070,"y":160,"wires":[]},{"id":"585ea41e.344f04","type":"inject","z":"17b46e42.bbdc6a","name":"Store a PreBuilt Custom Classifier ID","topic":"","payload":"YourCustomClassifier_1724727066","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":210,"y":820,"wires":[["346284e4.4ec104"]]},{"id":"346284e4.4ec104","type":"change","z":"17b46e42.bbdc6a","name":"","rules":[{"t":"set","p":"CustomClassifier","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":820,"wires":[[]]},{"id":"e5d58a06.e7ddb","type":"template","z":"17b46e42.bbdc6a","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Please wait for the {{result.classifier_id}} to complete training.","output":"str","x":980,"y":700,"wires":[["17d912f.09abbed"]]},{"id":"17d912f.09abbed","type":"debug","z":"17b46e42.bbdc6a","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":1150,"y":700,"wires":[]},{"id":"8ec1e215.fda9f8","type":"zip","z":"17b46e42.bbdc6a","name":"Zip Positive Examples","mode":"compress","filename":"","outasstring":false,"x":180,"y":620,"wires":[["dbb22787.f39f7"]]},{"id":"f612b496.253eb","type":"zip","z":"17b46e42.bbdc6a","name":"Zip Negative Examples","mode":"compress","filename":"","outasstring":false,"x":690,"y":620,"wires":[["46789d1f.54f464"]]}]