Tot nu toe hebben we in deze serie artikelen over neuronen in neurale netwerken een neuraal netwerk gemaakt en inzicht gekregen in hoe het functioneert. Het lukte zelfs om het te leren hoe de XOR-functie werkt, iets dat de classificatie van invoerpatronen vereist. In dit artikel zullen we onderzoeken hoe we een onderdeel van een autonoom rijdend systeem kunnen implementeren: het herkennen van de status van verkeerslichten. 


Er zijn veel voorspellingen gedaan over zelfrijdende auto's [1], waarvan nog geen enkele is uitgekomen. Veel van de complexiteit komt voort uit pogingen om de intentie van andere weggebruikers en voetgangers te begrijpen. Veel van het autonoom rijden gaat echter over het classificeren van alles wat de vele sensoren en camera's rond het voertuig 'zien'. Dit varieert van verkeerslichten en verkeersborden tot straat- of wegmarkeringen, voertuigtypes en mensen. Nu we een werkend neuraal netwerk hebben in de vorm van ons meerlagig perceptron, zullen we het gebruiken om de kleuren van een verkeerslicht te detecteren.


Een van de geweldige dingen van de Processing-omgeving die we tot nu toe hebben gebruikt is het gemak waarmee het webcams kan benaderen. De voorbeelden die hier gebruikt worden zullen draaien op vrijwel elke laptop of PC met Windows, Linux of macOS met een geïntegreerde of externe camera.

Zoek Je Camera

Voordat we aan de slag kunnen, moet er een nieuwe bibliotheek aan Processing worden toegevoegd die toegang geeft tot eventueel gekoppelde webcams. Selecteer in het menu Sketch -> Import Library… -> Add Library… (Figuur 1), waarmee het venster van figuur 2 wordt geopend. Zorg ervoor dat het tabblad Libraries is geselecteerd en voer "video" in het zoekvak in. Uit de lijst die verschijnt selecteren we Video | GStreamer-based video library for Processing en klikken vervolgens op Install. Net als voorheen zullen we de code gebruiken uit de GitHub repository die voor deze serie artikelen is voorbereid [2].

Kennismaking Met Neuronen - Add a new library to Processing
Figuur 1: Een nieuwe library toevoegen aan Processing.

Wanneer de bibliotheek is geïnstalleerd, kunnen we het project /trafficlight/findcamera/findcamera.pde uitvoeren. Deze code vraagt eenvoudigweg de lijst op van op de computer aangesloten beschikbare camera's en stelt de gebruiker in staat er een te selecteren door een nummer tussen 0 en 9 in te voeren. Zorg ervoor dat het kleine findcamera-venster prioriteit heeft (klik in het venster) voordat je een nummer intoetst. Als het Processing IDE-venster prioriteit heeft, zul je gewoon ergens in de broncode een nummer moeten typen.

Kennismaking Met Neuronen - Search for and install the Video library
Figuur 2: Zoeken en installeren van de Video library.

Zodra een camera-bron is geselecteerd, wordt de uitvoer ervan getoond in een lage-resolutie 320×240-pixel uitvoer in het venster (Figuur 3). De tekstconsole bevat ook de broncode die nodig is om de camera te selecteren voor de volgende twee projecten die we zullen bekijken (Figuur 4).

findcamera.pde example output
Figuur 3: Voorbeeld van uitvoer van findcamera.pde.

Tenslotte hebben we een verkeerslicht nodig. Aangezien je er waarschijnlijk geen bij de hand hebt, is er een klaargezet in trafficlight/resources in verschillende bestandsformaten. Print er gewoon een uit en houd het bij de hand.

Wanneer je Processing-projecten stopt die de camera gebruiken, kun je de boodschap "WARNING: no real random source present!" zien. Dit lijkt een bug te zijn die gerelateerd is aan het gebruik van de Video-library, maar heeft geen invloed op de functionaliteit van de code.

Console output of findcamera.pde
Figuur 4: De console-output van findcamera.pde levert de initialisatie-code voor de andere projecten die de gewenste camera gebruiken.

Hoe Zien Camera's?

Eén van de belangrijkste aspecten van het gebruik van neurale netwerken is het begrijpen van de wijze waarop een computer de binnenkomende gegevens kan interpreteren. In het geval van camera-invoer wordt het computerbeeld weergegeven door de drie primaire kleuren, rood, groen en blauw, te mengen. Dit wordt gewoonlijk het RGB-formaat genoemd. De drie waarden variëren tussen 0 en 255 (of 0x00 en 0xFF in hexadecimaal). Als we de camera op iets blauws richten, zouden we verwachten dat de B-waarde relatief hoog is en de andere waarden vrij laag. Richten we de camera op iets geels, dan zou de R- en G-waarde hoog moeten zijn, omdat rood en groen samen geel maken. Om een beter gevoel te krijgen voor additieve kleurmenging kan het project /trafficlights/addititive/additive.pde interessant zijn (figuur 5).

additive.pde demos additive color mixing
Figuur 5: additive.pde demonstreert additieve kleurmenging.

Met deze kennis lijkt het zinvol te bepalen hoe onze camera de kleuren van ons verkeerslicht 'ziet' en de RGB-waarden te noteren die hij rapporteert. Vervolgens kunnen we ons neuraal netwerk de drie kleuren van het verkeerslicht leren, zodat die deze kan classificeren als rood, oranje (amber) en groen.

RGB-waarden bepalen

Het project trafficlight/computer_vision/computer_vision.pde is het volgende project dat we nodig zullen hebben. Dit toont de uitvoer van de geselecteerde camera naast de RGB-waarden die hij rapporteert. Met dit project kunnen we de RGB-waarden opnemen die de camera ziet. Vergeet niet om, voordat je met de code begint, de regel code die je hebt bepaald in findcamera.pde te plakken op regel 22 in dit project. Dit zorgt ervoor dat de door jou gekozen camera wordt gebruikt.

Terwijl je de camera op het rode verkeerslicht richt (houd het 'licht' ongeveer binnen de gestippelde cirkel), noteer je de kleur die je ziet (bovenaan) en de RGB-waarden die deze kleur bepalen (Figuur 6). De RGB-waarden zijn in feite het gemiddelde van alle pixels die de camera vastlegt in het rode omlijnde vierkant van het centrum. Hoewel het een gemiddelde is, zullen de RGB-waarden snel fluctueren. Om een enkele waarde vast te leggen, druk je op 'p' op je toetsenbord, en de code pauzeert op een enkele reeks waarden. Zorg ervoor dat u in dit venster klikt voordat u op 'p' drukt om het prioriteit te geven. Door op 's' te drukken start u de camera-opname en RGB-generatie opnieuw.

Kennismaking Met Neuronen - computer_vision.pde provides the RGB values
Figuur 6: computer_vision.pde levert ons de RGB-waarden die de camera ‘ziet’ voor elke verkeerslichtkleur.

De hier gebruikte afdruk van het verkeerslicht was gelaagd, dus er zijn hier en daar wat reflecties. Als je je verkeerslichtafbeelding met een laserprinter hebt afgedrukt, kun je ook een licht reflecterend oppervlak hebben. Het gevolg is dat, hoewel de camera op het rode verkeerslicht is gericht, de 'geziene kleur' rozig kan zijn of zelfs bijna wit. Dit is uiteraard niet erg nuttig voor het neurale netwerk. Het moet de kleur 'rood verkeerslicht' onder optimale omstandigheden kennen, dus verplaats de camera of verander de belichting tot je het gevoel hebt dat je een RGB-waarde hebt bereikt die de kleur optimaal weergeeft.

Dit werpt ook een ander probleem op in verband met de nauwkeurigheid. Bestuurders weten hoe moeilijk het is om te bepalen welk verkeerslicht actief is wanneer de zon in onze ogen of rechtstreeks in de lampen schijnt. Als wij mensen al niet kunnen onderscheiden welke lamp brandt, hoe kan een neuraal netwerk dat dan? Het antwoord is: dat kan het niet. Als we een robuuster algoritme nodig hebben, moeten we het trainen met gegevens over 'slecht zicht'. Misschien moeten we ook een andere input geven, zoals waar de zon op dat moment schijnt, zodat het neurale netwerk weet wanneer er sprake is van 'slecht zicht' en dat het de gegevensverzameling 'slecht zicht' moet gebruiken. Tenslotte zouden we de inkomende gegevens van de camera kunnen verbeteren, misschien door een infraroodbeeld van het verkeerslicht toe te voegen (welke lampen zijn heet) of een andere slimme filtering. We zullen wat robuustheid toevoegen aan onze trainingsgegevens om enige variatie in de kleur van onze verkeerslichtinvoer aan te kunnen.

De belangrijkste taak op dit punt is het verzamelen van de RGB-gegevens voor de rode, oranje en groene verkeerslichten met behulp van je camera en je lichtomstandigheden. De gegevens die met de opstelling van de auteur zijn verzameld, zijn te zien in tabel 1.

RGB values captured for the three colors - practical neurons article
 Tabel 1: RGB-waarden, verkregen voor de drie verkeerslichtkleuren.

Verkeerslichten Detecteren

Gewapend met onze gegevens, kunnen we nu het neurale netwerk de kleuren van ons verkeerslicht laten trainen. Voor deze laatste fase hebben we het project trafficlight/tlight_detect/tlight_detect.pde nodig, geopend in Processing. Begin met ervoor te zorgen dat de juiste camera-initialisatie-code in regel 38 is geplakt (van find_camera.pde).

Dit project maakt gebruik van een MLP met drie ingangen, zes verborgen nodes en vier uitgangen (3/6/4). De drie ingangen zijn voor de drie kleuren, R, G, en B. Drie van de vier uitgangen zijn voor het classificeren van 'rood', 'oranje', en 'groen' van het verkeerslicht. De vierde zal later worden gebruikt. Het gebruik van zes verborgen nodes is willekeurig gekozen omdat dit 'genoeg' is voor de classificatietaak. We zullen zien dat deze configuratie werkt en de lezer wordt aangemoedigd te experimenteren met minder of meer verborgen nodes.

Als de code wordt uitgevoerd 'as is', werkt het neurale netwerk zonder enig leren. De resultaten (figuur 7) laten zien dat elke kleur wordt geclassificeerd als alle kleuren die het netwerk volgens de definitie moet detecteren.

Response of tlight_detect.pde prior to learning colors
Figuur 7: De respons van tlight_detect.pde voordat dat kleuren heeft geleerd.

Het leren van het neurale netwerk vindt plaats rond regel 51. Haal het commentaar weg bij de eerste drie methoden en voeg de RGB-waarden toe die u eerder hebt verkregen. De drie methoden die worden gebruikt om rood, oranje en groen te definiëren zijn:

teachRed(159, 65, 37);

teachAmber(213, 141, 40);

teachGreen(128, 152, 130);
 

Telkens wanneer deze functies worden aangeroepen, wordt het netwerk getraind om die RGB-combinatie te classificeren als de bijbehorende kleur (figuur 8). Om enige variatie in verlichting en automatische veranderingen in belichting door de camera mogelijk te maken, wordt een kleine hoeveelheid variatie (±4) toegepast op de RGB-waarden met behulp van een randomise()-functie (regel 336). Ook hier kun je experimenteren met de effectiviteit van deze aanpak en de mate van randomisatie die wordt toegepast.

 De drie verkeerslichtkleuren in RGB-waarden in 3D na randomiseren.
Figuur 8: De drie verkeerslichtkleuren in RGB-waarden in 3D na randomiseren.

Het trainen van het netwerk gaat snel in vergelijking met vorige projecten, omdat we de foutwaarden tijdens het leren niet langer naar een bestand schrijven. Start het project en na een paar seconden zal het neurale netwerk de kleur in het rode begrenzende vierkant van het cameravenster beginnen te evalueren (Figuur 9).

tlight_detect.pde having learned red, amber, and green.
Figuur 9: tlight_detect.pde nadat het de kleuren rood, oranje en groen heeft geleerd.

Het verkeerslicht in het gezichtsveld van de camera wordt bepaald op regel 156 en verder. De vastgelegde RGB-kleuren worden toegepast op de ingangen van het MLP en de output van het netwerk wordt berekend:

network.setInputNode(0, (float) r / 255.0);

network.setInputNode(1, (float) g / 255.0);

network.setInputNode(2, (float) b / 255.0);

network.calculateOutput();

De beslissing over de geziene kleur wordt genomen vanaf regel 171. De output van elke outputnode wordt geëvalueerd. Indien de classificatiezekerheid boven 90% (0,90) ligt, wordt de geziene kleur in een cirkel weergegeven, samen met de classificator 'Rood',  'Oranje' of 'Groen'.

// If likelihood of ‘Red’ > 90%...

if (network.getOutputNode(0) > 0.90) {

  fill(200, 200, 200);

  // …write “Red”…

  text("Red", 640+(100), 320);

  // … and set color to the color seen.

  fill(r, g, b);

} else {

  // Otherwise, set color to black

  fill(0, 0, 0);

}

// Now draw the color seen in a circle

ellipse(640+(50), 300, 40, 40);
 

Je kunt experimenteren met de nauwkeurigheid van het MLP door de camera op de verschillende verkeerslichten te richten onder verschillende hoeken en onder verschillende lichtomstandigheden. Probeer ook de camera te richten op objecten in je omgeving die, volgens jou, de kleuren benaderen die het MLP heeft geleerd.

Wat je wellicht opvalt is de verkeerde classificatie van een breed scala van kleuren als een bekende kleur. In het voorbeeld van de auteur wordt de classificatie 'groen' ook gegeven voor de omgeving van het verkeerslicht, het frame en de algemene beeldachtergrond (Figuur 10).

 Misclassificatie van andere kleuren als ‘groen.’
Figuur 10: Misclassificatie van andere kleuren als ‘groen.’

Aanscherping Neuraal Netwerk Classificatie

Uit de RGB-waarden blijkt duidelijk dat de kleuren die aan het MLP worden doorgegeven redelijk dicht in de buurt komen van de gewenste classificatie voor 'Groen'. Er zijn verschillende manieren om de classificatie aan te scherpen. De eerste zou zijn om de 90%-drempel voor nauwkeurige classificatie naar een hogere waarde te verhogen. Een andere mogelijkheid is het aantal leerepochs te verhogen. De andere is de classificatie-implementatie te heroverwegen.

Tot nu toe hebben we ons geconcentreerd op wat we positief willen classificeren. Soms kan het echter helpen om het neurale netwerk te leren wat niet tot de patronen behoort die we zoeken. In wezen kunnen we zeggen: "dit zijn drie dingen waarnaar we op zoek zijn, maar hier zijn enkele soortgelijke dingen waarnaar we zeker niet op zoek zijn." Dit is waar onze vierde output node in het spel komt.

Als we nog eens teruggaan naar het computer_vision.pde project, kunnen we de RGB-waarden vastleggen voor kleuren die we willen classificeren als 'overig'. Als voorbeeld werden de RGB-waarden voor de donkere verkeerslichtrand, de witte rand en de blauwe achtergrond verzameld, met de resultaten zoals weergegeven in tabel 2.

RGB values for ‘unwanted’ colors
Tabel 2: RGB-waarden verkregen voor de 'ongewenste' kleuren.

Terug in tlight_detect.pde kunnen deze waarden worden aangeleerd als 'Andere' ongewenste kleuren met behulp van de teachOther()methode. Verwijder gewoon het volgende commentaar uit de code rond regel 60 en voeg uw RGB-waarden toe:

teachOther(76, 72, 35);

teachOther(175, 167, 138);

teachOther(152, 167, 161);

Het opnieuw uitvoeren van het project leidt tot een merkbare verbetering. Het gebied rond de verkeerslichten (rand, kader, achtergrond) wordt geclassificeerd als 'Overig' in plaats van 'Groen' (figuur 11).

Misclassification of other colors as ‘green’ resolved using ‘other’ output node.
Figuur 11: Misclassificatie van andere kleuren als ‘groen’ opgelost met de ‘other’ output node.

Voor De Volgende Keer

In dit artikel hebben we nu gezien hoe een neuraal netwerk een echt classificatieprobleem oplost. We hebben ook geleerd dat het kan helpen bij het aanleren van zowel de gewenste classificatie als de ongewenste classificatiegegevens.

Waarom niet proberen voort te bouwen op dit voorbeeld om het volgende te onderzoeken?

  • Hoe 'robuust' kun je het MLP maken voor camerahoek en veranderingen in belichting? Is het beter om de leerdata zwaarder te randomiseren of de lat voor classificatie hoger te leggen (> 90%)?
  • Verbetert de nauwkeurigheid als je het aantal 'Andere' outputnodes verhoogt en elke node een ongewenste kleur leert?
  • Welke invloed heeft het verlagen of verhogen van het aantal verborgen nodes op het systeem?
  • Zou een vierde ingang voor 'algemene helderheid' helpen om de herkenningsnauwkeurigheid bij wisselende lichtomstandigheden te verhogen?

Hoewel het geweldig is om neurale netwerken op krachtige laptops en PC's te draaien, zullen velen van ons die mogelijkheid willen hebben op de kleinere processors die gebruikt worden op boards zoals Arduino. In ons laatste artikel van deze serie, zullen we een RGB-sensor en een Arduino gebruiken om een kleur-detecterend neuraal netwerk te implementeren. Misschien vormt dit wel de basis voor je volgende slimme Arduino-project!
 

Vragen Over Practische Neuronen?

Heb je technische vragen of opmerkingen over dit artikel? E-mail de auteur op stuart.cording@elektor.com.

 

Vertaling: Jelle Aarnoudsen