Open GermanBluefox opened 5 years ago
With https://github.com/justadudewhohacks/face-api.js
const path = require('path'); const trainedModelFile = 'model_08.json'; //const trainedModelDirPath = '/opt/iobroker/node_modules/iobroker.javascript/node_modules/'; //const dataPath = path.resolve('/opt/iobroker/iobroker-data/files/camera/input'); //const facepath = '/opt/iobroker/iobroker-data/files/camera/faces/'; const dataDir = '/opt/iobroker/iobroker-data/files'; const facepath = dataDir+'/camera/faces/'; const trainedModelDirPath = dataDir+'/camera/conf/'; const dataPath = dataDir+'/camera/input'; const percent_prob = 10; const days_history = 60; //Количество дней хранения рапознанных лиц в БД и на диске (кроме обученных) const fs = require('fs'); const fr = require('face-recognition'); const detector = fr.FaceDetector(); const recognizer = fr.FaceRecognizer(); const recognizer_new = fr.FaceRecognizer(); var db_faces; var array_checked = []; var model = []; var model_new = []; const init_user = {"className":"inituser","faceDescriptors":[[ 0.05138051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634 ],[ 0.05838051210860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634, 0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634,0.05838051810860634 ]]}; var init_array = []; init_array.push(init_user); fs.stat(trainedModelDirPath+trainedModelFile, function(err, stat) { if(err === null) { model= JSON.parse(fs.readFileSync(trainedModelDirPath+trainedModelFile)); recognizer.load(model); console.log('face_db='+JSON.stringify(recognizer.getDescriptorState())); db_faces = recognizer.getDescriptorState(); setState('javascript.0.fr_model',JSON.stringify(model)); } else if(err.code == 'ENOENT') { const modelinit = init_array; console.log('Create '+trainedModelFile +' with init_db ='+JSON.stringify(recognizer.getDescriptorState())); fs.writeFileSync(trainedModelDirPath+trainedModelFile, JSON.stringify(modelinit)); model= JSON.parse(fs.readFileSync(trainedModelDirPath+trainedModelFile)); recognizer.load(model); console.log('new_face_db='+JSON.stringify(recognizer.getDescriptorState())); db_faces = recognizer.getDescriptorState(); } var arr3 = {}; model.forEach(function(element_U,index_U,array_U) { var user = model[index_U]['className']; var arr2 = (model[index_U]['faceDescriptors']); arr2.forEach(function(element_F,index_F,array_F) { var new_index=user+ '__'+index_F; arr3 = {"className":new_index,"faceDescriptors":[element_F,element_F]}; model_new.push(arr3); }); }); setState('javascript.0.fr_model_alt',JSON.stringify(model_new)); recognizer_new.load(model_new); var query2='select id, filename_face, face_desc from iobroker.faces where checked=1'; sendTo('sql.0', 'query',query2 , function (result) { if (result.error) { console.error(result.error); } else { var obj = JSON.stringify(result.result); obj = JSON.parse(obj ); if (obj.length>0) { array_checked=obj; //console.log('array_checked[0]='+JSON.stringify(array_checked[0])); setState('javascript.0.fr_array_checked',JSON.stringify(array_checked)); } } }); }); var FileArray; var InputImgs; var Timestamp; on({id: "javascript.0.fr_model", change: 'any'}, function (objsp) { console.log('Update model'); model= JSON.parse(getState("javascript.0.fr_model").val); recognizer.load(model); model_new= JSON.parse(getState('javascript.0.fr_model_alt').val); recognizer_new.load(model_new); array_checked = JSON.parse(getState("javascript.0.fr_array_checked").val); }); schedule("0 * * * *", function () { var query2 = 'SELECT filename_face FROM iobroker.faces where checked<>1 and datetime < DATE_SUB(now(), INTERVAL '+days_history+' DAY)'; console.log(query2); sendTo("sql.0", "query", query2, function (result){ if (result.error) { console.error(result.error); } else { var obj = JSON.stringify(result.result); obj = JSON.parse(obj ); if (obj.length>0) { for(var i=0;i<obj.length;i++) { fs.unlink(obj["filename_face"], function(err){ if (err) throw err; console.log(obj["filename_face"] + "deleted"); }); } var query3 = 'DELETE FROM iobroker.faces where checked<>1 and datetime < DATE_SUB(now(), INTERVAL '+days_history+' DAY)'; //console.log(query3); sendTo("sql.0", "query", query3, function (result){ if (result.error) { console.error(result.error); } }); } } }); }); function processFiles() { //console.log('face_db='+JSON.stringify(recognizer.getDescriptorState())); // console.log('face_db_new='+JSON.stringify(recognizer_new.getDescriptorState())); FileArray = fs.readdirSync(dataPath) var SmallArray =[]; var max_load = 1 ; var method_alt = getState("javascript.0.fr_method").val; if (FileArray.length >0) { SmallArray=FileArray.slice(0,max_load); InputImgs = SmallArray .map(f => path.join(dataPath, f)) .map(fp => fr.loadImage(fp)); Timestamp = SmallArray .map(f => fs.statSync(dataPath +'/'+ f).mtime.toISOString() ); for (const [i, _img] of InputImgs.entries() ) { var start_rec = new Date(); let img = _img; var start_detect = new Date(); const faceRects = detector.locateFaces(img).map(res => res.rect); var filename_src = dataPath+'/'+FileArray[i]; const unknownThreshold = (100-percent_prob)/100; console.log('faceRects.length='+faceRects.length); faceRects.forEach((rect, t) => { console.log('Face detected!'); //const faceImages = detector.detectFaces(img); const faces = detector.getFacesFromLocations(img, faceRects, 150); console.log('End detectFaces='+new Date()); var event_date_sql; var face_name; var prob; var calc_time; var filename_rec=''; var end_detect; if (method_alt === true) { console.log('Use alt model'); // const prediction = recognizer_new.predictBest( faceImages[t], unknownThreshold); const prediction = recognizer_new.predictBest( faces[t], unknownThreshold); console.log('face_name alt ='+prediction.className); event_date_sql = formatDate(Timestamp[i], "JJJJ-MM-TT SS:mm:ss.sss"); face_name = prediction.className; prob = Math.round((1-prediction.distance)*100,0); filename_face = facepath+Timestamp[i]+'_'+t+'_face.jpg'; // fr.saveImage(filename_face,faceImages[t]); fr.saveImage(filename_face,faces[t]); end_detect = new Date(); calc_time = (end_detect-start_detect)/1000; var new_name= face_name; var arr_2; var fase_desc_rec; // переместил вниз. строка 225 // console.log("Обнаружено лицо "+face_name); // оригинальная строка, видимо с процентами console.log("Обнаружено лицо "+'face_name='+face_name); model_new.forEach(function(element_U,index_U,array_U) { var user = model_new[index_U]['className']; if (user == face_name) { arr_2 = model_new[index_U]['faceDescriptors']; fase_desc_rec = '[['+ arr_2[0] + ']]'; } }); face_name=face_name.substring( 0, face_name.indexOf( "__" ) ); prob = Math.round((1-prediction.distance)*100,0); var kk =''; console.log("Обнаружено лицо "+face_name); if (face_name === 'Саида') { console.log("Отправил телегу Саиде"); setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'Привет дорогая, отлично выглядишь!', caption: 'Добро пожаловать!', user: 'Саида', // chatId: '-186628872' }); } else if (face_name === 'Руслан') { setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'О! Руслан приехал.', caption: 'Добро пожаловать!', // user: 'Anzor', chatId: '-186628872' }); } else if (face_name === 'Валя') { setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'Валя пришла.', caption: 'Добро пожаловать!', // user: 'Anzor', chatId: '-186628872' }); } else if (face_name === 'Женя_тварь') { setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'Женя.', caption: 'Добро пожаловать!', // user: 'Anzor', chatId: '-186628872' }); } else if (face_name === 'Тимур') { setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'О! Тимур приехал.', caption: 'Добро пожаловать!', // user: 'Anzor', chatId: '-186628872' }); } else if (face_name === 'Аня') { setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'Кажется, я узнал Аню!', caption: 'Добро пожаловать!', // user: 'Anzor', chatId: '-186628872' }); } else if (face_name === 'Марат') { setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'О! Марат приехал.', caption: 'Добро пожаловать!', // user: 'Anzor', chatId: '-186628872' }); } else if (face_name === 'Света') { setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'О! Света.', caption: 'Добро пожаловать!', // user: 'Anzor', chatId: '-186628872' }); } else if (face_name === 'Раиса') { setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'О! Теща! Бегом стол накрывать!', caption: 'Добро пожаловать!', // user: 'Anzor', chatId: '-186628872' }); } else if (face_name === 'Анзор') { console.log("Отправил в телегу месагу Анзору"); setState("mqtt.0.homebridge.vto_TargetState"/*vto_lock_TargetState*/, 0); sendTo('telegram.0', { text: 'Хозяин, мое почтение!', caption: 'Добро пожаловать!', user: 'Anzor', //chatId: '-186628872' }); } if (face_name !== 'inituser' & face_name !== 'unknown' & face_name !== '') { array_checked.forEach(function(el,ind,array) { if ( array_checked[ind]['face_desc'] == fase_desc_rec ) kk = ind; }); if (kk) filename_rec = array_checked[kk]['filename_face']; } var query1 = 'INSERT INTO iobroker.faces (datetime, filename_src, face_name, filename_face,prob,calc_time,filename_rec) VALUES (\'' + String(event_date_sql)+ '\',\'' + filename_src + '\',\'' + face_name + '\',\'' + filename_face+ '\',' + prob + ','+calc_time+',\'' + filename_rec + '\')'; console.log(query1); sendTo("sql.0", "query", query1, function (result){ if (result.error) { console.error(result.error); } else { if (face_name == 'unknown') { } else { //var saytext = "Обнаружено лицо " + face_name; // setState("sayit.0.tts.text",'ru;60;'+saytext); } } }); } //if method_alt else { const prediction = recognizer.predictBest(faces[t], unknownThreshold); console.log('Use classic model'); event_date_sql = formatDate(Timestamp[i], "JJJJ-MM-TT SS:mm:ss.sss"); face_name = prediction.className; prob = Math.round((1-prediction.distance)*100,0); filename_face = facepath+Timestamp[i]+'_'+t+'_face.jpg'; fr.saveImage(filename_face,faces[t]); end_detect = new Date(); calc_time = (end_detect-start_detect)/1000; var query2 = 'INSERT INTO iobroker.faces (datetime, filename_src, face_name, filename_face,prob,calc_time,filename_rec) VALUES (\'' + String(event_date_sql)+ '\',\'' + filename_src + '\',\'' + face_name + '\',\'' + filename_face+ '\',' + prob + ','+calc_time+',\'' + filename_rec + '\')'; console.log(query2); sendTo("sql.0", "query", query2, function (result){ if (result.error) { console.error(result.error); } else { if (face_name == 'unknown') { } else { console.log("Обнаружено лицо2 " + face_nam); //var saytext = "Обнаружено лицо " + face_name; // setState("sayit.0.tts.text",'ru;60;'+saytext); } } }); } //classic method }); //faceRects.forEach fs.unlink(filename_src, function(err){ if (err) throw err; // console.log(filename_src + " parsed and deleted"); }); } //for } //if setTimeout(processFiles, 1*100); } //processFiles setTimeout(processFiles, 1*100);
Hay, is there a manual or similar for this script to integrate it into iobroker.
@GermanBluefox @DutchmanNL
Is there a more up-to-date example available? i want to use faceDetection within a iobroker script
With https://github.com/justadudewhohacks/face-api.js