├── .gitignore ├── photo ├── image_15.jpg ├── image_16.jpg ├── image_17.jpg ├── image_18.jpg ├── image_19.jpg ├── image_20.jpg ├── image_21.jpg └── extra │ ├── image_14.jpg │ ├── image_150.jpg │ ├── image_166.jpg │ ├── image_171.jpg │ ├── image_22.jpg │ ├── image_24.jpg │ ├── image_276.jpg │ ├── image_282.jpg │ ├── image_311.jpg │ ├── qa-team.png │ ├── youtube.jpg │ ├── jamie-detected.png │ └── nexmo-sms-cat-detected.png ├── package.json ├── LICENSE.md ├── detectCatsFromPhoto.js ├── kittyCam.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | tmp 3 | config.js 4 | node_modules 5 | -------------------------------------------------------------------------------- /photo/image_15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/image_15.jpg -------------------------------------------------------------------------------- /photo/image_16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/image_16.jpg -------------------------------------------------------------------------------- /photo/image_17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/image_17.jpg -------------------------------------------------------------------------------- /photo/image_18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/image_18.jpg -------------------------------------------------------------------------------- /photo/image_19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/image_19.jpg -------------------------------------------------------------------------------- /photo/image_20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/image_20.jpg -------------------------------------------------------------------------------- /photo/image_21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/image_21.jpg -------------------------------------------------------------------------------- /photo/extra/image_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/image_14.jpg -------------------------------------------------------------------------------- /photo/extra/image_150.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/image_150.jpg -------------------------------------------------------------------------------- /photo/extra/image_166.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/image_166.jpg -------------------------------------------------------------------------------- /photo/extra/image_171.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/image_171.jpg -------------------------------------------------------------------------------- /photo/extra/image_22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/image_22.jpg -------------------------------------------------------------------------------- /photo/extra/image_24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/image_24.jpg -------------------------------------------------------------------------------- /photo/extra/image_276.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/image_276.jpg -------------------------------------------------------------------------------- /photo/extra/image_282.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/image_282.jpg -------------------------------------------------------------------------------- /photo/extra/image_311.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/image_311.jpg -------------------------------------------------------------------------------- /photo/extra/qa-team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/qa-team.png -------------------------------------------------------------------------------- /photo/extra/youtube.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/youtube.jpg -------------------------------------------------------------------------------- /photo/extra/jamie-detected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/jamie-detected.png -------------------------------------------------------------------------------- /photo/extra/nexmo-sms-cat-detected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/girliemac/RPi-KittyCam/HEAD/photo/extra/nexmo-sms-cat-detected.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kittyCam", 3 | "version": "1.2.0", 4 | "description": "This is a Raspberry Pi app using a camera and PIR motion sensor, with cat facial detection", 5 | "main": "kittyCam.js", 6 | "dependencies": { 7 | "cloudinary": "^1.3.1", 8 | "johnny-five": "^0.9.56", 9 | "nexmo": "^1.0.0-beta-7", 10 | "pubnub": "^3.15.1", 11 | "raspi-io": "^6.0.1" 12 | }, 13 | "devDependencies": {}, 14 | "scripts": { 15 | "test": "echo \"Error: no test specified\" && exit 1" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/girliemac/RPi-KittyCam.git" 20 | }, 21 | "author": "", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/girliemac/RPi-KittyCam/issues" 25 | }, 26 | "homepage": "https://github.com/girliemac/RPi-KittyCam#readme" 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Tomomi Imura 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /detectCatsFromPhoto.js: -------------------------------------------------------------------------------- 1 | // KittyDar - cat facial detection 2 | // Note: this file and kittydar need to use the same canvas module, otherwise it failes. 3 | // https://github.com/Automattic/node-canvas/issues/487 4 | 5 | 'use strict' 6 | 7 | const fs = require('fs'); 8 | const kittydar = require('kittydar'); 9 | const Canvas = require('kittydar/node_modules/canvas'); 10 | 11 | process.on('message', (m) => { 12 | 13 | let imgPath = m[0]; 14 | 15 | fs.readFile(imgPath, (err, data) => { 16 | if (err) { 17 | return console.error(err); 18 | } 19 | let img = new Canvas.Image; // creating an image object 20 | img.src = data; 21 | 22 | let w = img.width; 23 | let h = img.height; 24 | 25 | let canvas = new Canvas(w, h); 26 | let ctx = canvas.getContext('2d'); 27 | ctx.drawImage(img, 0, 0, w, h, 0, 0, w, h); 28 | 29 | console.log('PID ' + process.pid + ': ditecting cats in the photo...'); 30 | 31 | let cats = kittydar.detectCats(canvas); 32 | console.log('There are', cats.length, 'cats in this photo'); 33 | 34 | let base64Img = ''; 35 | 36 | if(cats.length > 0) { 37 | 38 | // Draw a rectangle around the detected cat's face 39 | ctx.strokeStyle = 'rgba(255, 64, 129, 0.8)'; 40 | ctx.lineWidth = 2; 41 | 42 | for (let i = 0; i < cats.length; i++) { 43 | let cat = cats[i]; 44 | console.log(cat); 45 | ctx.strokeRect(cat.x, cat.y, cat.width, cat.height); 46 | } 47 | 48 | base64Img = canvas.toDataURL(); // png by default. jpeg is currently not supported by node-canvas 49 | } 50 | 51 | process.send(base64Img); 52 | 53 | ctx.clearRect(0, 0, w, h); 54 | 55 | process.exit(0); 56 | 57 | }); 58 | }); 59 | 60 | process.on('error', (err) => { 61 | console.log('Child process error: ', err); 62 | }); 63 | -------------------------------------------------------------------------------- /kittyCam.js: -------------------------------------------------------------------------------- 1 | /* 2 | * KittyCam 3 | * A Raspberry Pi app using a camera PIR motion sensor, with cat facial detection 4 | * 5 | * Tomomi Imura (@girlie_mac) 6 | */ 7 | 8 | 'use strict' 9 | 10 | const config = require('./config'); 11 | const fs = require('fs'); 12 | const child_process = require('child_process'); 13 | 14 | require('events').EventEmitter.prototype._maxListeners = 20; 15 | 16 | // Johnny-Five for RPi 17 | const raspi = require('raspi-io'); 18 | const five = require('johnny-five'); 19 | const board = new five.Board({io: new raspi()}); 20 | 21 | let i = 0; 22 | 23 | board.on('ready', () => { 24 | console.log('board is ready'); 25 | 26 | // Create a new `motion` hardware instance. 27 | const motion = new five.Motion('P1-7'); //a PIR is wired on pin 7 (GPIO 4) 28 | 29 | // 'calibrated' occurs once at the beginning of a session 30 | motion.on('calibrated', () => { 31 | console.log('calibrated'); 32 | }); 33 | 34 | // Motion detected 35 | motion.on('motionstart', () => { 36 | console.log('motionstart'); 37 | 38 | // Run raspistill command to take a photo with the camera module 39 | let filename = 'photo/image_'+i+'.jpg'; 40 | let args = ['-w', '320', '-h', '240', '-o', filename, '-t', '1']; 41 | let spawn = child_process.spawn('raspistill', args); 42 | 43 | spawn.on('exit', (code) => { 44 | console.log('A photo is saved as '+filename+ ' with exit code, ' + code); 45 | let timestamp = Date.now(); 46 | i++; 47 | 48 | // Detect cats from photos 49 | 50 | if((/jpg$/).test(filename)) { // Ignore the temp filenames like image_001.jpg~ 51 | let imgPath = __dirname + '/' + filename; 52 | 53 | // Child process: read the file and detect cats with KittyDar 54 | let args = [imgPath]; 55 | let fork = child_process.fork(__dirname + '/detectCatsFromPhoto.js'); 56 | fork.send(args); 57 | 58 | // the child process is completed 59 | fork.on('message', (base64) => { 60 | if(base64) { 61 | uploadToCloudinary(base64, timestamp); 62 | } 63 | 64 | // Once done, delete the photo to clear up the space 65 | deletePhoto(imgPath); 66 | }); 67 | } 68 | 69 | }) 70 | }); 71 | 72 | // 'motionend' events 73 | motion.on('motionend', () => { 74 | console.log('motionend'); 75 | }); 76 | }); 77 | 78 | 79 | function deletePhoto(imgPath) { 80 | fs.unlink(imgPath, (err) => { 81 | if (err) { 82 | return console.error(err); 83 | } 84 | console.log(imgPath + ' is deleted.'); 85 | }); 86 | } 87 | 88 | 89 | // PubNub to publish the data 90 | // to make a separated web/mobile interface can subscribe the data to stream the photos in realtime. 91 | 92 | const channel = 'kittyCam'; 93 | 94 | const pubnub = require('pubnub').init({ 95 | subscribe_key: config.pubnub.subscribe_key, 96 | publish_key: config.pubnub.publish_key 97 | }); 98 | 99 | function publish(url, timestamp) { 100 | pubnub.publish({ 101 | channel: channel, 102 | message: {image: url, timestamp: timestamp}, 103 | callback: (m) => {console.log(m);}, 104 | error: (err) => {console.log(err);} 105 | }); 106 | } 107 | 108 | // Nexmo to send SMS 109 | 110 | const Nexmo = require('nexmo'); 111 | 112 | const nexmo = new Nexmo({ 113 | apiKey: config.nexmo.api_key, 114 | apiSecret: config.nexmo.api_secret 115 | }); 116 | 117 | function sendSMS(url, timestamp) { 118 | var t = new Date(timestamp).toLocaleString(); 119 | let msg = '🐈 detected on '+ t + '! See the photo at: ' + url; 120 | nexmo.message.sendSms( 121 | config.nexmo.fromNumber, 122 | config.nexmo.toNumber, 123 | msg, 124 | {type: 'unicode'}, 125 | (err, responseData) => { 126 | if (err) { 127 | console.log(err); 128 | } else { 129 | console.dir(responseData); 130 | } 131 | } 132 | ); 133 | } 134 | 135 | // Cloudinary to store the photos 136 | 137 | const cloudinary = require('cloudinary'); 138 | 139 | cloudinary.config({ 140 | cloud_name: config.cloudinary.cloud_name, 141 | api_key: config.cloudinary.api_key, 142 | api_secret: config.cloudinary.api_secret 143 | }); 144 | 145 | function uploadToCloudinary(base64Img, timestamp) { 146 | cloudinary.uploader.upload(base64Img, (result) => { 147 | console.log(result); 148 | publish(result.url, timestamp); // Comment this out if you don't use PubNub 149 | sendSMS(result.url, timestamp); // Comment this out if you don't use Nexmo 150 | }); 151 | } 152 | 153 | // Ctrl-C 154 | process.on('SIGINT', () => { 155 | process.exit(); 156 | }); 157 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Raspberry Pi KittyCam 2 | 3 | **Updated: Tutorial is now available on my blog, [KittyCam - Building a Raspberry Pi Camera with Cat Face Detection in Node.js](http://www.girliemac.com/blog/2015/12/25/kittycam-raspberrypi-camera-cat-face-recog-nodejs/), also 4 | [Upgrading KittyCam with Raspberry Pi 3](http://www.girliemac.com/blog/2016/06/13/kittycam-update-with-raspberrypi3/) 5 | ** 6 | 7 | --- 8 | 9 | [![Jamie on YouTube](https://raw.githubusercontent.com/girliemac/RPi-KittyCam/master/photo/extra/youtube.jpg "Jamie on YouTube")](https://www.youtube.com/watch?v=wqewhjhjaHY) 10 | 11 | [Watch the demo on YouTube :-)](https://www.youtube.com/watch?v=wqewhjhjaHY) 12 | 13 | ![RPi KittyCam](https://lh3.googleusercontent.com/o-XG7ZijXM_UXQHuYrDxC6mlTofyUzUCmHqNmr6oRYZk=w1346-h757-no "Rapsberry Pi KittyCam") 14 | 15 | ![RPi KittyCam](https://lh3.googleusercontent.com/UuKlrNQWs5wFciRqI8qiZKTVoh4XrTBa40LD5mUa5MIn=w1346-h757-no "Rapsberry Pi KittyCam") 16 | 17 | Raspberry Pi app using a camera and PIR motion sensor, written in Node.js using Johnny-Five and KittyDar for with cat facial detection. 18 | 19 | **I will write up the step-by-step tutorial (hopefully) soon!** But until then, here is the instruction how to run this code locally with your own Raspberry Pi. 20 | 21 | 22 | ## Building the Circuit 23 | 24 | ### What you need 25 | 26 | - Raspberry Pi 2 (with Raspbian. Also with WiFi adapter) 27 | - 5MP Camera Board Module ([buy](http://amzn.to/1pg7Y91)) 28 | - Pyroelectric Infrared (PIR) motion sensor ([buy](http://amzn.to/1pg828D)) 29 | - 3 F/F wires ([buy](http://amzn.to/1Mf50Xy)) 30 | 31 | If you are a Raspberry Pi newbie, I recommend to buy this [CanaKit Raspberry Pi 2 Complete Starter Kit](http://amzn.to/1QNFlcB). 32 | 33 | ### Wiring 34 | 35 | #### Camera to Pi 36 | - Connect the camera module to the CSI port 37 | 38 | #### PIR Sensor to Pi 39 | - 1 red wire: PIR-VCC to Pi's 5V 40 | - 1 black wire: PIR-GND to Pi's ground 41 | - 1 whatever color wire: PIR-OUT to Pi's Pin 7 (GPIO 4) 42 | 43 | ![RPi PIR](https://lh3.googleusercontent.com/vInXgXGKPueI2J4zq88BgUJOkcXgJCvReVT4kA2K1A16=w1424-h801-no "Rapsberry Pi 2, camera, and PIR wired") 44 | 45 | 46 | 47 | 48 | ## Software Setup 49 | 50 | ### 1. Install node.js in your Raspberry Pi 51 | 52 | #### Make sure your Pi is up-to-date 53 | 54 | `$ sudo apt-get update` 55 | 56 | then 57 | 58 | ``` 59 | $ sudo apt-get upgrade 60 | ``` 61 | 62 | #### [Updated] Download Node 63 | 64 | Node for ARM is now supported officially on Nodejs.org! Download and install from there: 65 | 66 | ```bash 67 | $ wget https://nodejs.org/dist/v4.4.5/node-v4.4.5-linux-armv7l.tar.xz 68 | $ tar -xvf node-v4.4.5-linux-armv7l.tar.xz 69 | $ cd node-v4.4.5-linux-armv7l 70 | $ sudo cp -R * /usr/local/ 71 | ``` 72 | 73 | Check if node is successfully installed: 74 | 75 | ``` 76 | $ node -v 77 | ``` 78 | 79 | ### 2. Enable Camera access 80 | 81 | Go to Pi Software Config Tool to enable camera 82 | 83 | ``` 84 | $ sudo raspi-config 85 | ``` 86 | 87 | Test if your camera is working by try typing this command on terminal: 88 | 89 | ``` 90 | $ raspistill -o photo.jpg 91 | ``` 92 | 93 | 94 | ## Running this Code 95 | 96 | I would like to say, `$ npm install` to install all the dependencies, and voilà! but it is **not**! 97 | 98 | ### 1. Prerequisite: Install Cairo to the System 99 | 100 | for cat facial detection, I am using **kittydar**, which dependencies including **node-canvas**, which requires **Cairo**. 101 | 102 | So let's get Cairo on your Raspbian first. 103 | 104 | ``` 105 | $ sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++ 106 | ``` 107 | 108 | See more info on how to install Cairo for Node [Canvas](https://github.com/Automattic/node-canvas), see this [*Installation Ubuntu and other Debian based systems*](https://github.com/Automattic/node-canvas/wiki/Installation---Ubuntu-and-other-Debian-based-systems) 109 | 110 | If you download and use the whole `node_modules` contents of this repo, skip the step 2, and proceed to step 3. 111 | Otherwise, go to the next step to fresh-install the next several modules. 112 | 113 | 114 | ### 2. Install Dependency Modules 115 | 116 | #### Install KittyDar 117 | 118 | ![Jamie detected](https://raw.githubusercontent.com/girliemac/RPi-KittyCam/master/photo/extra/jamie-detected.png "Jamie detected by KittyDar") 119 | 120 | *This is an actual photo taken by my Raspberry Pi, while Jamie was eating, and detected by KittyDar cat facial detection!* 121 | 122 | 123 | Once your environment is set up, in this RPi-KittyCam dir, install node dependency modules. 124 | 125 | Ideally install from `npm install kittydar —save` 126 | 127 | However, node-canvas 1.0.1 (the version specified in package.json for KittyDar) failed to build with the current Node.js (v0.12.6). 128 | 129 | So what I did was download the zip from github repo into *node_modules*, alter the `package.json`, where canvas: `~1.0.1` to `^1.0.1` so that the latest v1.x canvas will be installed as I `npm install` from the kittydar directory. 130 | 131 | Get the zip from [my forked repo](https://github.com/girliemac/kittydar). 132 | 133 | *Note: I am sending a pull request (https://github.com/harthur/kittydar/pull/27)* 134 | 135 | The following packages are specified in`package.json` file so they will be installed from `npm install` automatically, however, I just list them in case you want to know what they are: 136 | 137 | #### Install Johnny-Five 138 | 139 | [Johnny-Five](https://jonny-five.io) is a Javascript robotics framework that let you program micro controllers easily with carious hardware APIs. 140 | 141 | ``` 142 | $ npm install johnny-five 143 | ``` 144 | 145 | #### Install Raspi-io 146 | 147 | This I/O plugin allows you to use Johnny-Five on Raspbian. 148 | 149 | ``` 150 | $ npm install raspi-io 151 | ``` 152 | 153 | #### Install PubNub 154 | 155 | This is used to establish real-time live-updating the web interface, use PubNub (v3.x, imcompatible with the new v4). 156 | 157 | ``` 158 | $ npm install pubnub@3.15.2 159 | ``` 160 | 161 | You need to [sign up and get you own publish and subscribe keys!](http://pubnub.com) 162 | 163 | #### Install Cloudinary 164 | 165 | To store photos in a cloud, I am using Cloudinary. 166 | 167 | ``` 168 | $ npm install cloudinary 169 | ``` 170 | 171 | You need to [sign up and get you own API keys!](http://cloudinary.com) 172 | 173 | ### Install Nexmo [New feature! Aug 30, 2016] 174 | 175 | To send a SMS message with the Cloiudinary image link to your phone, use Nexmo SMS API. 176 | 177 | ``` 178 | $ npm install nexmo 179 | ``` 180 | 181 | You need to [sign up and get your own keys!](https://dashboard.nexmo.com/sign-up) 182 | 183 | ![SMS via Nexmo](https://raw.githubusercontent.com/girliemac/RPi-KittyCam/master/photo/extra/nexmo-sms-cat-detected.png "A kitty cat detected! Send SMS via Nexmo") 184 | 185 | ### 3. Set up your config.js with Credentials 186 | 187 | I removed my `config.js` file from the public repo so nobody abuses my API keys. So you need to create your own `config.js` in the root dir of the app. 188 | 189 | The file should include your API keys: 190 | 191 | ``` 192 | module.exports = { 193 | 194 | cloudinary: { 195 | cloud_name: 'your_name', 196 | api_key: 'your_API_key', 197 | api_secret: 'your_API_secret', 198 | }, 199 | pubnub: { 200 | subscribe_key: 'your_sub_key', 201 | publish_key: 'your_pub_key' 202 | }, 203 | nexmo: { 204 | api_key: 'your_API_key', 205 | api_secret: 'your_API_secret', 206 | fromNumber: 'your_Nexmo_phone_number', 207 | toNumber: 'your_mobile_phone_number' 208 | } 209 | 210 | }; 211 | ``` 212 | 213 | Nexmo's phone number should begin with a country code. e.g. '14155551234'. 214 | 215 | ### 4. Run the Code 216 | 217 | You must run with sudo, because some modules used in the app requires root access: 218 | 219 | ``` 220 | $ sudo node kittyCam.js 221 | ``` 222 | 223 | The camera will take a photo when a motion is detected by the PIR sensor. 224 | Then the child_process runs to detect if there is any cats in the photo. 225 | When there are any cat, it sends the photo to Cloudinary. 226 | 227 | Analyzed photos are deleted from the filesystem to clear up Pi. 228 | 229 | ### 5. View the Live Photo Update on Web 230 | 231 | - Get the web interface source code from `gh-pages` branch. 232 | - Run the `index.html` on browser 233 | 234 | 235 | ## Known Issue 236 | 237 | ### Raspistill (Camera Software) 238 | - Raspistill continuously takes a bunch of photos when I set `t = 0` (and crashes Pi while so many child process is running) so I have set `t = 1`, which causes delay. It seems to take only integer. Cats are too fast to wait for a second. 239 | - The camera can't capture recognizable pics after the sun is set. My room light is too dark. 240 | 241 | ### KittyDar (Cat Facial Detection) 242 | 243 | - During mealtime. When a cat is eating food (head-down position), the facial detection doesn't detect the cat at all. 244 | - When my cat moves, eats from the side of the dish, or put his butt on the camera, it fails to tell me my cat was eating. 245 | 246 | #### The cat photos failed to be recognized 247 | 248 | ![Jamie undetected](photo/extra/image_14.jpg "Jamie undetected") 249 | ![Jamie undetected](photo/extra/image_24.jpg "Jamie undetected") 250 | ![Jamie undetected](photo/extra/image_150.jpg "Jamie undetected") 251 | ![Jamie undetected](photo/extra/image_166.jpg "Jamie undetected") 252 | ![Upside-down Jamie undetected](photo/extra/image_311.jpg "Jamie undetected") 253 | 254 | ## Thank you! 255 | ![QA team](photo/extra/qa-team.png "QA Team") 256 | 257 | ### Presentation at JS Kongress in München 258 | 259 | [*KittyCam.js - Raspberry Pi Camera w/ Cat Facial Detection* on Slideshare](https://www.slideshare.net/tomomi/js-kongress-2016-kittycamjs-raspberry-pi-camera-w-cat-facial-detection) 260 | --------------------------------------------------------------------------------