Skip to content

Instantly share code, notes, and snippets.

@PonDad
Created November 23, 2016 15:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PonDad/ecc0db7cd024cd3a6c13622a535a1b4f to your computer and use it in GitHub Desktop.
Save PonDad/ecc0db7cd024cd3a6c13622a535a1b4f to your computer and use it in GitHub Desktop.
PonBot - face recognition
var express = require("express");
var app = express();
var path = require("path");
var server = require('http').Server(app);
var io = require('socket.io')(server);
var fs = require('fs');
var request = require('request');
var five = require('johnny-five');
var exec = require('child_process').exec;
var OpenJTalk = require('openjtalk');
var mei = new OpenJTalk({ htsvoice: '/home/pi/ponbot04/node_modules/openjtalk/voice/mei/mei_happy.htsvoice' });
var MeCab = new require('mecab-async')
var mecab = new MeCab();
var array = [];
var reply = [];
var cv = require('opencv');
var indico = require('indico.io');
indico.apiKey = <API_KEY>;
var COLOR = [255, 255, 255]; // default red
var thickness = 2; // default 1
server.listen(3000, function () {
console.log('listening on *:3000');
});
app.use(express.static(__dirname + '/public'));
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
});
io.sockets.on('connection', function(socket) {
socket.on('chat_message', function(data) {
MeCab.command = "mecab -d /usr/lib/mecab/dic/mecab-ipadic-neologd"
MeCab.parseFormat(data, function(err, morphs) {
if (err) throw err;
morphs.map(function(morph) {
if (morph.lexical === '感動詞') {
array.push(morph.original);
reply = '!'
console.log(array);
io.emit('msg','shutter');
}
if (morph.compound === '固有名詞') {
array.push(morph.original);
reply = 'っていいね。'
console.log(array);
io.emit('msg','action');
}
if (morph.lexical === '形容詞' | morph.compound === '自立') {
array.push(morph.original);
console.log(array);
reply = 'よね。'
io.emit('msg','action');
}
});
if(array.length <= 0){
bot_reply = 'そうなんだ。' ;
}else{
bot_reply = array[Math.floor(Math.random() * array.length)] + reply;
}
mei.talk(bot_reply);
array = [];
reply = [];
});
});
socket.on('shutter', function () {
var raspistill = exec('raspistill -o ./public/images/output.jpg -h 480 -w 640 -t 100 -n');
raspistill.on('close', function () {
console.log('写真を撮りました');
});
setTimeout(function () {
cv.readImage('./public/images/output.jpg', function(err, im) {
if (err) throw err;
if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size');
im.detectObject('./node_modules/opencv/data/haarcascade_frontalface_alt2.xml', {}, function(err, faces) {
if (err) throw err;
for (var i = 0; i < faces.length; i++) {
face = faces[i];
im.rectangle([face.x - 30, face.y - 30], [face.width + 60, face.height + 60], COLOR, 2);
}
im.save('./public/images/face.jpg');
console.log('顔認識しました');
fs.readFile('./public/images/face.jpg', function(err, buf){
io.emit('image', { image: true, buffer: buf.toString('base64')});
console.log('画像を送信します…');
});
});
});
cv.readImage('./public/images/output.jpg', function(err, im) {
if (err) throw err;
if (im.size()[0] > 0 && im.size()[1] > 0){
im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){
if (err) throw err;
if (!faces.length) return console.log("No Faces");
var face = faces[0];
var ims = im.size();
var im2 = im.roi(face.x - 30, face.y - 30, face.width + 60, face.height + 60)
/*
im.adjustROI(
-face.y
, (face.y + face.height) - ims[0]
, -face.x
, (face.x + face.width) - ims[1])
*/
im2.save('./public/images/face_2.jpg')
console.log('顔認証を切り出しました');
var filename = "./public/images/face_2.jpg"
var facepp = exec('curl -X POST "https://apicn.faceplusplus.com/recognition/identify?api_key=<API_KEY>&api_secret=<API_SECRET&group_name=pulp_fiction" -F "img=@' + filename + '"',
function (error, res) {
console.log(res)
var identify = JSON.parse(res)
var a = identify.face
var b = []
var c = []
for (var i = 0; i < a.length; i++) {
for (var j = 0; j < a[i]["candidate"].length; j++) {
b.push(a[i]["candidate"][j].person_name);
c.push(a[i]["candidate"][j].confidence);
};
};
if(c[0] > 10){
console.log(b[0])
console.log(c[0])
io.sockets.emit('msg3', b[0] + ' : ' + c[0]);
io.emit('msg','action');
if(b[0] === 'samuel'){
mei.talk('サミュエル');
}else if(b[0] === 'travolta'){
mei.talk('トラボルタ');
}else if(b[0] === 'pon_dad'){
mei.talk('ポンダッド');
}
}
var response = function(res) {
console.log(res);
var emotion =[res.Angry, res.Sad, res.Neutral, res.Surprise, res.Fear, res.Happy];
var max_emotion = Math.max.apply(null, emotion);
if(max_emotion === res.Angry){
console.log('angry : '+ res.Angry);
io.sockets.emit('msg2', 'angry : '+ res.Angry);
mei.talk('怒ってるの');
}else if(max_emotion === res.Sad){
console.log('sad : '+ res.Sad);
io.sockets.emit('msg2', 'sad : '+ res.Sad);
mei.talk('つまんないね');
}else if(max_emotion === res.Neutral){
console.log('neutral : '+ res.Neutral);
io.sockets.emit('msg2', 'neutral : '+ res.Neutral);
mei.talk('いいね');
}else if(max_emotion === res.Surprise){
console.log('surprise : '+ res.Surprise);
io.sockets.emit('msg2', 'surprise : '+ res.Surprise);
mei.talk('おどろいたね');
}else if(max_emotion === res.Fear){
console.log('fear : ' + res.Fear);
io.sockets.emit('msg2', 'fear : '+ res.Fear);
mei.talk('怖いね');
}else if(max_emotion === res.Happy){
console.log('happy : '+ res.Happy);
io.sockets.emit('msg2', 'happy : '+ res.Happy);
mei.talk('楽しいね');
}
}
var logError = function(err) { console.log(err); }
var filename = "./public/images/face_2.jpg";
fs.readFile(filename, function(err, data) {
base64data = new Buffer(data).toString('base64');
indico.fer(base64data)
.then(response)
.catch(logError);
});
if (error !== null) {
console.log('exec error: ' + error);
}
});
})
} else {
console.log("Camera didn't return image")
}
});
}, 3000);
});
});
board = new five.Board();
board.on("ready", function() {
var a = new five.Motor({
controller: "GROVE_I2C_MOTOR_DRIVER",
pin: "A",
});
var b = new five.Motor({
controller: "GROVE_I2C_MOTOR_DRIVER",
pin: "B",
});
/*
var proximity = new five.Proximity({
controller: "HCSR04",
pin: 7
});
*/
io.sockets.on('connection', function (socket) {
socket.on('click_servo_yes', function (degree_y) {
console.log('サーボ1: ' + degree_y);
var options_y = {
uri: 'https://us.wio.seeed.io/v1/node/GroveServoD1/angle/' + degree_y,
form: { access_token: '4e2b286ed9df49400201b233587011de' },
json: true
};
request.post(options_y, function(error, response, body){
if (!error && response.statusCode == 200) {
} else {
console.log('error: '+ response.statusCode);
}
});
});
socket.on('click_servo_no', function (degree_n) {
console.log('サーボ0: ' + degree_n);
var options_n = {
uri: 'https://us.wio.seeed.io/v1/node/GroveServoD0/angle/' + degree_n,
form: { access_token: '4e2b286ed9df49400201b233587011de' },
json: true
};
request.post(options_n, function(error, response, body){
if (!error && response.statusCode == 200) {
console.log(body);
} else {
console.log('error: '+ response.statusCode);
}
});
});
/*
proximity.on("data", function() {
console.log("cm: ", this.cm);
socket.emit('message', this.cm);
});
*/
socket.on('click_motor_forward', function () {
a.rev(252);
b.fwd(252);
setTimeout(function(){
a.stop();
b.stop();
},500);
});
socket.on('click_sound_robot', function () {
exec('aplay /home/pi/ponbot05/public/sounds/robot.wav', function(error, stdout, stderr) {
if (error != null) {
console.log(error);
}
});
});
socket.on('click_sound_shutter', function () {
exec('aplay /home/pi/ponbot05/public/sounds/shutter.wav', function(error, stdout, stderr) {
if (error != null) {
console.log(error);
}
});
});
socket.on('click_motor_stop', function () {
a.stop();
b.stop();
});
socket.on('click_motor_right', function () {
a.rev(381);
b.rev(381);
setTimeout(function(){
a.stop();
b.stop();
},300);
});
socket.on('click_motor_right_turn', function () {
a.rev(381);
b.rev(381);
});
socket.on('click_motor_left', function () {
a.fwd(381);
b.fwd(381);
setTimeout(function(){
a.stop();
b.stop();
},300);
});
socket.on('click_motor_left_turn', function () {
a.fwd(381);
b.fwd(381);
});
socket.on('click_motor_backward', function () {
a.fwd(252);
b.rev(252);
setTimeout(function(){
a.stop();
b.stop();
},500);
});
});
});
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>PonBot03</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Orbitron" rel="stylesheet">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<article>
<h1>PonBot05</h1>
<article>
<div id="container">
<img class="img-responsive" id="image">
<br>
<p id="massage3"></p>
<p id="massage2"></p>
</div>
<div class="spinner">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
</div>
</article>
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/annyang/2.4.0/annyang.min.js"></script>
<script>
$(document).ready(function() {
var socket = io.connect('http://192.168.0.11');
if (annyang) {
var commands = {'*i': function() {console.log("実行")}};
annyang.setLanguage('ja-JP')
annyang.addCommands(commands);
annyang.start();
console.log('録音開始');
annyang.addCallback('resultMatch', function(userSaid) {
console.log('録音: ' + userSaid);
socket.emit('chat_message', userSaid);
});
};
socket.on('msg', function(msg) {
if(msg === 'action'){
console.log('アクション');
setTimeout(function(){
socket.emit('click_sound_robot');
socket.emit('click_servo_yes',60);
socket.emit('click_motor_left');
setTimeout(function(){
socket.emit('click_servo_yes',120);
socket.emit('click_motor_right');
setTimeout(function(){
socket.emit('click_servo_yes',60);
socket.emit('click_motor_left');
setTimeout(function(){
socket.emit('click_servo_yes',120);
socket.emit('click_motor_right');
setTimeout(function(){
socket.emit('click_servo_yes',80);
socket.emit('click_servo_no',90);
},1500);
},1200);
},900);
},600);
},300);
}else if(msg === 'shutter'){
console.log('シャッター');
socket.emit('shutter');
socket.emit('click_sound_shutter');
}
});
socket.on('image', function(face) {
$("#image").attr('src', 'data:image/jpg;base64,' + face.buffer );
});
socket.on('msg3', function(massage3) {
$("#massage3").text(massage3);
});
socket.on('msg2', function(massage2) {
$("#massage2").text(massage2);
});
});
</script>
</body>
</html>
{
"name": "ponbot05",
"version": "1.0.0",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "pon_dad",
"license": "ISC",
"dependencies": {
"express": "^4.14.0",
"indico.io": "^0.10.5",
"johnny-five": "^0.10.3",
"mecab-async": "^0.1.0",
"opencv": "^6.0.0",
"openjtalk": "^0.1.6",
"request": "^2.76.0",
"socket.io": "^1.5.1"
},
"devDependencies": {},
"description": ""
}
body{
font-family: 'Orbitron', sans-serif;
background-color: #3D8EB9;
color: #f6f6f6;
max-width: 480px;
margin: 0 auto;;
padding: 20px;
}
.btn-group-width{
max-width: 250px;
margin: 0 auto;
}
.spinner {
margin: 100px auto 0;
width: 70px;
text-align: center;
}
.spinner > div {
width: 18px;
height: 18px;
background-color: #f6f6f6;
border-radius: 100%;
display: inline-block;
-webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
animation: sk-bouncedelay 1.4s infinite ease-in-out both;
}
.spinner .bounce1 {
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
.spinner .bounce2 {
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
@-webkit-keyframes sk-bouncedelay {
0%, 80%, 100% { -webkit-transform: scale(0) }
40% { -webkit-transform: scale(1.0) }
}
#caption{
margin-top: 20px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment