Maak een slimme camera die via Google Home vertelt wat hij ziet

In deze post leg ik uit hoe je zelf een slimme camera maakt die herkent wat hij ziet.

06-08-2018 - 8 minutes, 39 seconds -

Inleiding

Met deze handleiding leer je hoe je zelf een camera kan bouwen die objecten herkent: je maakt een foto met een Raspberry Pi Camera én je krijgt feedback via je Google Home. Achter de schermen wordt je foto doorgestuurd naar de server van IBM, waar een algoritme zal terugsturen naar jouw Raspberry Pi wat er precies is herkend.

Wat heb je nodig?

Raspberry Pi Zero W
Het kleine broertje van de originele Raspberry Pi. Een soort mini-computer.
Compatibele camera
Een camera die werkt met de Pi Zero W. Kan zonder problemen een Chinese variant zijn.
Google Home
Een Google Home of Google Home - mini voor de voice feedback.

Raspbian installeren

Voor we beginnen moet onze Raspberry Pi Zero W geïnstalleerd worden. Dat betekent heel concreet dat je een besturingssysteem op je Raspberry moet installeren, zodat je hem kan gebruiken. Bij sommige versies van de Pi Zero W krijg je een kaartje met N00BS op.

Je plugt een keyboard in je Raspberry, koppelt 'm aan een scherm (of televisie) en je kan meteen opstarten vanop het kaartje dat is meegeleverd. Daarna selecteer je in het menu Raspbian, het systeem dat we gaan gebruiken. Al de rest wijst zichzelf uit. Vergeet zeker geen wifi-netwerk te selecteren.

Heb je een eigen, leeg kaartje. Dan moet je dat zelf nog even flashen met de juiste software. Een handleiding daarvoor vind je hier.

Voor we verder gaan, kan je best even controleren of je systeem helemaal up-to-date is. Dat kan je doen door een terminal te openen en deze commando's te gebruiken:

sudo apt-get update
sudo apt-get upgrade

De Pi voorbereiden

Ik ga er nu van uit dat je Raspbian hebt geïnstalleerd en dat je de Raspberry Pi Zero W hebt aangesloten aan een scherm. De bedoeling is dat we hem benaderbaar maken vanop een andere computer. Zo kan je het ding straks gewoon rustig loskoppelen van je scherm en toetsenbord. Doorloop daarvoor deze stappen:

  1. Ga naar het 'start'-menu op de Pi en klik daar op 'preferences'
  2. Klik op 'interfaces'
  3. Zet camera en SSH op 'enabled'

Dit is het moment waarop je de camera kan aansluiten op de Pi Zero W. Daarvoor gebruik je de speciale connector die is meegeleverd. Je krijgt bij sommige behuizingen ook een versie van de connector die korter is.

Voor we onze Raspberry Pi herstarten, en het scherm, keyboard en de muis loskoppelen gaan we even met de cursor over het 'wifi'-icoon hangen. Je krijgt dan het IP-adres van je Raspberry te zien. Dat kan je best even noteren, want we hebben het later nodig.

Inloggen via SSH

Voor we kunnen inloggen vanop afstand, moet je nog een programma op je PC of Mac installeren waardoor je SSH kan gebruiken. Ik gebruik daarvoor Bitvise SSH Client (enkel voor PC). Werk je op Mac dan kan je best gewoon de Terminal gebruiken of ga voor iTerm.

Welk programma je ook gebruikt: je zal nu gegevens moeten invullen om connectie te maken met je Raspberry Pi vanop afstand:

Host: het ip-adres dat je daarnet hebt genoteerd
Username: pi
Paswoord: raspberry

Klik op 'login' en als alles klopt, dan zal je automatisch een terminal-venster krijgen, dat in verbinding staat met je Raspberry Pi. Die kan je nu eender waar in huis laten slingeren: je kan 'm vanop afstand commanderen.

Node-RED installeren

Om makkelijk met de camera te werken, en de dienst van IBM die we willen gebruiken, zullen we nu Node-RED installeren.

Tik in je terminal-venster volgend commando:

bash <(curl -sL https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/update-nodejs-and-nodered)

Het zal even duren maar na een tijdje zou op je Pi Zero W Node-RED krijgen. Meer informatie over wat er allemaal gevraagd wordt, vind je hier.

Als de installatie gedaan is, mag je een browser-venster openen op je computer. Daarin tik je:

http://het-ip-adres-van-je-raspberry:1880

Als alles goed gaat, dan ben krijg je nu Node-RED te zien.

Node-RED voorbereiden

Node-RED werkt met nodes, die je toelaten om op een simpele manier heel complexe zaken te programmeren. Je kan met wat klikken en slepen al heel wat doen. De nodes die wij willen gebruiken zitten nog niet standaard ingebakken in de basis installatie. Die moeten we nog even installeren.

  1. Ga naar het 'hamburgermenu' rechts bovenaan
  2. Klik op 'manage pallette'
  3. Klik op 'install'
  4. Zoek naar de Google Notify - node (meer info)
  5. Installeer de IBM Watson - nodes (meer info)

Let op: de Pi Zero W is leuk maar traag. Daarom kan het verschillende minuten duren voor een node geïnstalleerd is. Wacht gewoon rustig af.

De flow bouwen

Nu is de tijd rijp voor het échte werk. We zullen een aantal nodes (die je links ziet staan) gebruiken om een 'flow' te bouwen. Die flow zal wanneer we dat willen foto's maken, ze doorsturen naar IBM, ontvangen wat er op de foto staat en dat doorsturen naar een Google Home.

  1. Zoek de 'inject'-node en sleep 'm naar je flow
  2. Dubbelklik op de inject-node om 'm in te stellen
  3. Kies bij Payload voor 'boolean' en tik in het vak ernaast 'true'
  4. Zoek de camerapi takefoto-node en sleep die ook naar je flow
  5. Verbind de uitgang van de inject-node met de ingang van de camera-node
  6. Dubbelklik op de Camera-node
  7. Kies bij 'file mode' voor buffermode: je Pi Camera maakt dan een foto maar slaat die niet op
  8. Klik op 'deploy'

We hebben nu een mini-fototoestel gebouwd: als je op de inject-knop drukt (linkerkant van de inject-node) dan maakt jouw Pi Camera een foto. Dat zie je als het lampje rood wordt.

Maar voorlopig gebeurt er nog niet veel met die foto (we slaan hem zelfs niet op). Daarom gaan we een stap verder:

  1. Voeg een Visual Recognition - node toe aan je flow
  2. verbind de uitgang van de Pi Camera - node met de ingang van de Visual Recognition node
  3. Dubbelklik op de Visual Recognition - node om hem in te stellen.

Voor we nu verder kunnen, moeten we eerst een account aanmaken bij IBM Cloud. Want: we gaan het IBM-algoritme gebruiken om te herkennen wat er op foto's staat. We gebruiken daar heel specifiek de dienst 'Watson Visual Recognition' voor. Tot 1.000 foto's per maand is die analyse gratis. Als je een account hebt aangemaakt, dan kan je een nieuwe 'instance' van Visual Recognition opzetten. Als je dat gedaan hebt krijg je een API-code. Die code hebben we nodig en moeten we invullen bij de Visual Recognition-node in Node-RED.

Werk je flow af door er achteraan nog een Debug-node aan toe te voegen. Deze node zal even opangen wat IBM naar je terugstuurt als je hen een foto bezorgt. Verbind de uitgang van je Visual Recognition-node met de ingang van de Debug-node en druk op de linkerkant van de inject-node.

In je Debug-venster (rechts) krijg je, als alles goed werkt, de output te zien van je flow. Het ziet er wat ingewikkeld uit, maar als je wat klikt krijg je een lijstje met daarin een aantal objecten en de waarschijnlijkheid dat dat precies is wat het algoritme heeft gezien.

Google Home laten praten

We willen graag dat Google Home zegt wat jouw camera ziet.

  1. Zoek de Google Home-node en voeg 'm toe aan je flow
  2. Zoek de 'function'-node en voeg die ook toe aan je flow
  3. Zoek de 'change'-node en voeg ook die toe
  4. connecteer de ingang van de change-node met de uitgang van de Visual Recognition-node, dubbelklik op de change-node.
  5. Om er voor te zorgen dat we énkel het meest waarschijnlijke object naar Google Home sturen (anders zou hij er 100 opnoemen) moet je uit de inhoud van msg.payload énkel dat ene object selecteren door de change-node als volgt te configureren:

Het pad naar dat ene object is:

result.images[0].classifiers[0].classes[0].class
  1. connecteer de uitgang van de Visual Recogntion-node met de ingang van de function-node
  2. connecteer de uitgang van de function-node met de ingang van de Google Home-node

We moeten nu alle nodes nog configureren:

  1. Dubbelklik op de Google Home-node en vul daar het IP-adres in van de Google Home die je wil laten spreken (je moet daarvoor op het pennetje klikken). Kies ook de taal waarin dat moet gebeuren (in ons geval Engels). Waar vind je dat IP-adres? De makkelijkste manier is even inloggen in je router en daar kijken welk IP je Google Home toegewezen gekregen heeft.
  2. Dubbelklik op de function-node. Hier moeten we een beetje code ingeven, want we willen dat het antwoord een mooie zin vormt. Dat doe je met deze functie:
msg.payload = "I think you photographed a " + msg.payload
return msg;
  1. Klik op 'Deploy'

Als je nu op de inject-node klikt, dan maakt je camera een foto, stuurt die naar IBM Watson, herkent wat er op staat én spreekt dan uit wat het precies is via je Google Home!

De volledige code

Ergens een foutje gemaakt? Dit is de code van de hele flow. Je moet enkel de nodes nog zelf configureren (de API bij de Visual Recognition-node invullen bijvoorbeeld en het IP-adres van je Google Home). Je kan de code gebruiken door in Node-RED te klikken op het hamburgermenu, dan op import en 'clipboard':

[{"id":"255806fa.73830a","type":"inject","z":"74ca59be.707378","name":"","topic":"","payload":"true","payloadType":"bool","repeat":"","crontab":"","once":false,"onceDelay":"30","x":241,"y":224,"wires":[["9348fdf9.7a012"]]},{"id":"d92c7533.386328","type":"visual-recognition-v3","z":"74ca59be.707378","name":"Watson Visual Recognition","apikey":"","vr-service-endpoint":"https://gateway.watsonplatform.net/visual-recognition/api","image-feature":"classifyImage","lang":"en","x":673.5,"y":226,"wires":[["9f68c900.b8d1e8"]]},{"id":"7687528c.9b1a6c","type":"debug","z":"74ca59be.707378","name":"Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":818.5,"y":314,"wires":[]},{"id":"9348fdf9.7a012","type":"camerapi-takephoto","z":"74ca59be.707378","filemode":"0","filename":"image.jpg","filedefpath":"1","filepath":"","fileformat":"jpeg","resolution":"8","fliph":"0","flipv":"0","brightness":"50","contrast":"0","sharpness":"0","quality":"80","imageeffect":"none","exposuremode":"auto","iso":"0","agcwait":"","awb":"auto","name":"","x":406,"y":225,"wires":[["d92c7533.386328"]]},{"id":"9f68c900.b8d1e8","type":"change","z":"74ca59be.707378","name":"","rules":[{"t":"move","p":"result.images[0].classifiers[0].classes[0].class","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":412,"y":355,"wires":[["7687528c.9b1a6c","3d89d3cc.9e2e8c"]]},{"id":"b947ea96.1cb938","type":"googlehome-notify","z":"74ca59be.707378","server":"","name":"Google Home Bureau","x":1073,"y":399,"wires":[]},{"id":"3d89d3cc.9e2e8c","type":"function","z":"74ca59be.707378","name":"Only the top answer","func":"msg.payload = \"I think you photographed a \" + msg.payload\nreturn msg;","outputs":1,"noerr":0,"x":799,"y":401,"wires":[["b947ea96.1cb938"]]}]