FACULTEIT INDUSTRIELE INGENIEURSWETENSCHAPPEN CAMPUS DE NAYER
Camera gebaseerde analyse van de verkeersstromen aan een kruispunt
Jeroen PROVOOST
Promotor:
Ir. Steven Puttemans
Co-promotor:
Ir. Xavier Smet
Masterproef ingediend tot het behalen van de graad van master of Science in de ¨ wetenschappen: Elektronica-ICT industriele Afstudeerrichting informatie- en communicatietechnieken
Academiejaar 2013 - 2014
c Copyright KU Leuven
Zonder voorafgaande schriftelijke toestemming van zowel de promotor(en) als de auteur(s) is over¨ nemen, kopieren, gebruiken of realiseren van deze uitgave of gedeelten ervan verboden. Voor aanvragen tot of informatie i.v.m. het overnemen en/of gebruik en/of realisatie van gedeelten uit deze publicatie, wend u tot KU Leuven campus De Nayer, Jan De Nayerlaan 5, B-2860 Sint-KatelijneWaver, +32-15-316944 of via e-mail
[email protected]. Voorafgaande schriftelijke toestemming van de promotor(en) is eveneens vereist voor het aanwenden van de in deze masterproef beschreven (originele) methoden, producten, schakelingen en programma’s voor industrieel of commercieel nut en voor de inzending van deze publicatie ter deelname aan wetenschappelijke prijzen of wedstrijden.
Dankwoord Ik wil graag van deze gelegenheid gebruik willen maken om bepaalde personen te bedanken. Zonder deze personen zou het onmogelijk geweest zijn om deze masterthesis tot een goed eind te brengen. Zo wil ik graag mijn promotor ir. Puttemans Steven bedanken om mij gedurende dit academiejaar steeds te hulp te staan wanneer er problemen opdoken. Ook zou ik graag mijn bedrijfspromotor ir. Smet Xavier willen bedanken voor de goede hulp en tips. Zo wil ik ook het bedrijf FLIR ITS bedanken voor het aanbieden van dit interessant onderwerp. Verder wil ik mijn ouders en naaste familie bedanken voor de jarenlange steun die ze me hebben gegeven. Zonder hen kon ik nooit beginnen aan deze studie. Als laatste wil ik iedereen bedanken die mij tijdens deze periode heeft bijgestaan en mijn tekst heeft nagelezen.
v
Abstract Dagelijks komen er steeds meer voertuigen bij op de Belgische autowegen. Deze toename van voertuigen zorgt ervoor dat er meer en meer files ontstaan. Om de verkeersdrukte en/of intensiteit te bepalen, kunnen er metingen op dit verkeer uitgevoerd worden. Het doel van deze masterthesis is een systeem te ontwikkelen met de mogelijkheid om voertuigen real-time te kunnen tellen ter hoogte van een kruispunt. Hierbij moet rekening worden gehouden met de mogelijkheid dat niet elk kruispunt eenzelfde indeling en vorm heeft. In deze masterproef ´ rijrichting geis gekozen voor een oplossing met RGB kleurencamera’s. Per camera wordt er e´ en observeerd, die voor ruwe inputbeelden zorgt. Om in deze ruwe data voertuigen te kunnen tellen, dienen deze eerst gedetecteerd en gevolgd te worden. Hiervoor dient een algoritme geschreven te worden die de data van de camera’s kan analyseren. Ondanks de beelden afkomstig zijn van RGB kleurencamera’s, worden alle bewerkingen gedaan op grijswaarde beelden. Met de data afkomstig uit de camera’s wordt er een binair model gemaakt welke de voertuigen (de voorgrond) kan onderscheiden van de weg (de achtergrond). Dit wordt gedaan aan de hand van voorgrond / achtergrond segmentatie. Zo wordt er gekozen om deze segmentatie te doen aan de hand van de mixture of Gaussians. Bij deze segmentatie krijgen de voorgrond pixels een waarde van 255 (wit) en de achtergrond pixels een waarde van 0 (zwart). Bovengenoemd binair model kan vervolgens gebruikt worden voor verdere analyse. Voertuigen worden op dit beeld weergegeven als blobs, die aangrenzende regio’s van voorgrond pixels zijn. Het is dus zeer belangrijk alleen deze blobs te analyseren. Aan de hand van de contouren van elke blob kan de oppervlakte en het zwaartepunt berekend worden welke op hun beurt weer gebruikt kunnen worden om de voertuigen te traceren. Het traceren zal gedaan worden aan de hand van meerdere Kalman filters. Hierdoor is voor elk voertuig in het beeld een aparte Kalman filter noodzakelijk. Wanneer er geen detectie meer plaatsvindt, zal er een voorspelling gemaakt worden van de mogelijks volgende locatie van het voertuig. Om er voor te zorgen dat de elke detectie aan de corresponderende tracker wordt toegewezen, wordt er gebruik gemaakt van het Hongaars algoritme. In het beeld van de camera kunnen lijnen getrokken worden per richting. Telkens wanneer een tracker een van deze lijnen overschrijdt, zal er telling plaatsvinden in de richting van deze lijn. Om het aantal fout-positieve detecties te minimaliseren wordt er tevens gebruik gemaakt van een voertuigdetector. Het doel van deze detector is het analyseren van de laatste bekende punten van de tracker om zo te kunnen vaststellen dat het wel degelijk om een voertuig gaat. Met behulp van al deze algoritmen in de juiste volgorde is er een systeem ontstaan dat voertuigen kan tellen op een kruispunt. Door gebruik te maken van lijnen, welke de rijrichting bepalen, is het mogelijk om verschillende indelingen en vormen van kruispunten te analyseren.
vii
Abstract Every day more and more vehicles appear on the Belgian roads. Due too the increase of the number of vehicles, more traffic jams occur. In order to determine the traffic volume and intensity, measurements can be taken. The goal of this master thesis is to develop a system that has the possibility to count the vehicles at the level of crossroads in real time. Not every crossroad has a similar shape, which should be taken into account. In this project the choice to use RGB cameras. These cameras ensures raw data. To be able to count vehicles from this raw data, they first should be detected and followed. Therefore an algorithm is needed that can analyze the data from the cameras. With the data derived from the cameras, a binary model is made that segments the vehicles (foreground) from the road (background). The foreground pixels have a value of 255 and the background pixels have a value of 0. The binary model can then be used for further analysis. Vehicles appear as blobs, a set of adjacent foreground pixels. It is important to analyze only these blobs. On the basis of the contours of each blob, the surface area and the centre of gravity can be calculated. Combining the surface area and the centre of gravity, the vehicles can be tracked. The tracking will be done using multiple Kalman filters. Because of this a separate Kalman filter is required for each vehicle in the image. When no detection occurs, a prediction will be made of the next possible location of the vehicle. In order to ensure that each detection will be assigned to the corresponding tracker, the Hungarian algorithm is used. To count the vehicles, count lines will be used. These lines can be drawn during the initializing period of the system. Each time a tracker exceeds one of these lines, there will be a count held in the direction of this line. To minimize the number of false-positives detections, vehicle detectors are used. The purpose of this detector is to analyze the last known points of the tracker in order to determine that it is indeed a vehicle, and not any other moving object. Using a sequence of these algorithms, a system that can count vehicles at a crossroad, is created. By making use of the lines, which determine the direction of travel, it is possible to analyse the different formats and types of intersections.
ix
Short summary Traffic increases year after year. This growth result into more and more traffic jam. To get a view of the traffic flow, measurements are made on a regular base. Several solutions to count the traffic already exist. However, these solutions aren’t always that efficient. In this master thesis, a camera based traffic counter will be developed to use on cross roads. This traffic count needs te be processed in real-time. To achieve this goal, foreground / background segmentation will be used. This program is written in C++ with an include of the OpenCV library. Nowadays several vehicle classification systems already exist. The only problem of these systems is the processing time used to detect the vehicles. Because these classification systems cannot process real-time, a better solution must be found. Another approach is to look at the motion made by the vehicles.
(a)
(b)
Figuur 1: Region of interest masker en toegepast op een frame.
Foreground / background segmentation makes use of this motion. To get the vehicles out of the frame, a difference is made between a background and a recent frame. This results in an image which contains the difference between these frames. Before this operation can work properly, noise filtering will be done by Gaussian blur. The motion of these vehicles will be detected by the difference between these frames. Using this difference, the positions of every moving vehicle is known. The segmentation algorithm used in this system is the mixture of Gaussians. Figure 1(b)shows the result of a foreground / background segmentation of figure 1(a). Erosion and dilation are used to remove noise coming from foreground / background segmentation. To count the vehicles, a tracker will be used. In this case a Kalman filter will track the vehicles through the frames. To achieve the input data for the Kalman filter, the contours of each blob are analyzed. Using the moments method, the point of gravity of each blob is calculated. With these xi
xii
points, Kalman filters can be initialized. A Kalman filter is not only a tracker. It can even predict the next point of each vehicle, when no detection is made. Multiple kalman filters are needed to track all vehicles. To make sure that every detection is assigned to the corresponding track, the Hungarian algorithm is used.
(a)
Figuur 2: Counting lines.
The method used in this system to count vehicles is based on count lines. Every line corresponds with one direction only, when a tracker crossed a line, it counts for the specified direction. The use of these lines where chosen, because of the various shape of each crossroad. An expansion which will be discussed is the use of a HAAR cascade classifier. This classifier will only be used on the positions of each vehicle. In this case, this will still work in real time. Results have shown that our system can count vehicles with a precision around 90%. This is only on low traffic videos. When there is more traffic, more false positives and false negatives have showed up resulting into 80%. These result are made by the supposition that traffic never stop on a crossroad. The system can also process in real time. The expansion by using a vehicle detection gives less true-positive detection for this project . Because the vehicle detection is not done properly, this expansion will not be used.
Inhoudsopgave Dankwoord
v
Abstract
vii
Engels abstract
ix
Short summary
xi
Inleiding
1
1 Situering en doelstelling
5
1.1 Doelstelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
1.2 Situering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.2.1 EAVISE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.2.2 FLIR ITS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
1.3 Mogelijk gebruikte beeldverwerkingssoftware . . . . . . . . . . . . . . . . . . . . .
7
1.4 State-of-the-art in automatische telalgoritmes voor voertuigen . . . . . . . . . . . .
8
1.4.1 Moving Vehicle Detection for Measuring Traffic Count . . . . . . . . . . . . .
9
2 Literatuurstudie
11
2.1 Voorbereidende stappen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.1.1 Ruis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.1.2 Gaussian blurring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.1.3 Mediaanfilter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2 Voorgrond / achtergrond segmentatie . . . . . . . . . . . . . . . . . . . . . . . . . 16 2.2.1 Wat is voorgrond / achtergrond segmentatie? . . . . . . . . . . . . . . . . . 16 2.2.2 Beeldstabilisatie
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.2.3 Verschillende soorten segmentatiemethodes
. . . . . . . . . . . . . . . . . 19
2.3 Morfologische operaties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.3.1 Erosie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.3.2 Dilatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.3.3 Opening & Closing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 xiii
xiv
INHOUDSOPGAVE
2.4 Tracking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.4.1 Soorten trackers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.4.2 Voorbereidende stappen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.4.3 De Kalman filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 2.4.4 Het Hongaars algoritme
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.5 Voertuigdetectie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 2.5.1 Haar cascade classifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3 Verwerking van de data
39
3.1 Region of interest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.2 Ruis uit een beeld halen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.3 Implementeren van een voorgrond / achtergrond algoritme . . . . . . . . . . . . . . 43 3.4 Morphologische operaties implementeren . . . . . . . . . . . . . . . . . . . . . . . 46 4 Het volgen van voertuigen doorheen de frames
49
4.1 Implementatie van de Kalman filter . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 4.2
Het tellen van de voertuigen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.3 Uitbreiding: de Haar cascade voertuig detector . . . . . . . . . . . . . . . . . . . . 55 5 Evaluatie van de resultaten
57
5.1 Het opmaken van een Ground truth . . . . . . . . . . . . . . . . . . . . . . . . . . 57 5.1.1 Annotatie tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 5.2 Precision-recall performantie test 5.2.1
. . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Het vergelijken van meting met ground truth . . . . . . . . . . . . . . . . . . 60
6 Besluit
67
6.1 Future work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Bibliografie
68
Bijlage
71
A Programmacode initialisatie van het systeem
71
B Programmacode verdere verloop programma
75
Lijst van figuren 1
Region of interest masker en toegepast op een frame.
2
Counting lines.
3
Evolutie van het verkeer.
4
¨ De evolutie van het wagenpark in Belge.
5
Verschillende manieren voor het tellen van het verkeer.
6
Een camera voor het verkeer te meten.
. . . . . . . . . . . . . . . . . . . . .
xi
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
. . . . . . . . . . . . . . . . . . . . . . . . . . .
2
. . . . . . . . . . . . . . . . . . . . .
2
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
1.1 Schets van de opstelling en de te tellen richtingen. . . . . . . . . . . . . . . . . . . . . . . .
5
1.2 Logo van de EAVISE onderzoeksgroep. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
1.3 Logo voormalig Traficon en huidig FLIR ITS. . . . . . . . . . . . . . . . . . . . . . . . . . .
7
2.1 Volgorde van de bestudeerde stappen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2 De twee voorbereidende stappen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3 Voorbeeld Salt & pepper ruis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.4 Gaussische functie visueel voorgesteld. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.5 Voorbeeld Gaussian Blurring. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.6 Mediaan berekenen van omliggende pixels. Structuurelement van 3x3. . . . . . . . . . . . . . . 15 2.7 Voorbeeld mediaanfilter.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.8 Voorbeeld nadelig effect weersomstandigheden en licht. . . . . . . . . . . . . . . . . . . . . . 17 2.9 Voorbeeld nadelig effect camera shake. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.10 Frame Differencing voorbeelden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.11 Running Average voorbeelden.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.12 Approximated mediaan voorbeelden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.13 Mixture of Gaussians grafiek. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.14 Mixture of Gaussians voorbeelden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 2.15 Morfologische operaties. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 2.16 Voorbeeld van Erosie. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 2.17 Voorbeeld van Dilatie.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.18 Opening & Closing voorbeelden. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.19 Voorbeeld van Model based tracking. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.20 Voorbeeld van optical flow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 xv
xvi
LIJST VAN FIGUREN
2.21 Verschil tussen uitwendige en inwendige contours. . . . . . . . . . . . . . . . . . . . . . . . 29 2.22 Werking van Kalman filter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.23 Structuur van de Kalman klassen. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.24 Resultaat van de Kalman filter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 2.25 Assignment probleem met Euclidische afstand.
. . . . . . . . . . . . . . . . . . . . . . . . 33
2.26 De verschillende stappen van het Hongaars algoritme. . . . . . . . . . . . . . . . . . . . . . 34 2.27 De verschillende stappen van het Hongaars algoritme. . . . . . . . . . . . . . . . . . . . . . 36 2.28 Een voorbeeld van een integral image. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 2.29 Werking van cascade classifiers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.1 Aangeklikte punten om een region of interest te maken. . . . . . . . . . . . . . . . . . . . . . 39 3.2 Region of interest masker en toegepast op een frame.
. . . . . . . . . . . . . . . . . . . . . 40
3.3 Verkleind venster met region of interest. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.4 Grafiek verschil in rekentijd Gaussiaans vervagen en mediaanfilter. . . . . . . . . . . . . . . . . 42 3.5 Grafiek verschil in rekentijd voor de verschillende segmentatie algoritmes. . . . . . . . . . . . . . 43 3.6 Voorgrond beelden van voertuigen met de verschillende methodes. . . . . . . . . . . . . . . . . 45 3.7 Erosie toegepast op een voorgrond beeld. . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 ¨ 3.8 Dilatie toegepast op het geerodeerde beeld. . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.1 Structuur van de ge¨ıimplementeerde Kalman klassen.
. . . . . . . . . . . . . . . . . . . . . 50
4.2 Voorbeel van de ligging van de tellijnen en wanneer er geteld wordt.
. . . . . . . . . . . . . . . 53
4.3 De aangemaakte klasse voor de tellijnen. . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 5.1 De confusion matrix. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 ¨ 5.2 Precision-recall curve voor een varierende ’deltaTime’. . . . . . . . . . . . . . . . . . . . . . 61 ¨ 5.3 Precision-recall curve voor een varierende ’deltaTime’ met interval = 30 frames.
. . . . . . . . . . 62
5.4 Opstelling en resultaten rustig verkeer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 5.5 Opstelling en resultaten rustig verkeer bis. . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 5.6 Opstelling en resultaten drukker verkeer. . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 5.7 Opstelling en resultaten drukker verkeer met voertuigdetector. . . . . . . . . . . . . . . . . . . 64 5.8 Opstelling en resultaten drukker verkeer met voertuigdetector. . . . . . . . . . . . . . . . . . . 65 6.1 Voorstel andere positie camera. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Inleiding Dagelijks ontstaan er honderden kilometers file op de Belgische autowegen. Volgens een artikel in ´de Tijd´ [19], verliest een gemiddelde autobestuurder hieraan jaarlijks 103 uur, gebaseerd op een chauffeur die 30 minuten per dag in Brussel moet rijden. Hiermee staat Brussel in de top 10 van de meest filegevoelige steden van Europa. Dit fileprobleem zorgt ervoor dat mensen te laat op hun bestemming komen of dat ze stressgevoeliger zijn. Dit zijn slechts twee gevolgen die voor verminderde prestaties of agressie kunnen zorgen.
Figuur 3: Evolutie van het verkeer.
Door het toenemend aantal voertuigen, geraken de wegen steeds meer verzadigd. Zoals te zien is op afbeelding 3 is er een toename van verkeersdrukte van 20% sinds 2000. De verwachting is dat deze met nog eens 15% zal toenemen in 2030. Hierdoor zullen wegen nog meer oververzadigd geraken, wat zorgt voor nog meer files. Door de verkeersstromen te analyseren, kan er bepaald worden welke knooppunten er in de nabije toekomst voor problemen kunnen zorgen. Aan de hand van deze analyse kan er bepaal worden waar deze voertuigen vandaan komen en kan er gezocht worden naar een passende oplossing. 1
2
LIJST VAN FIGUREN
¨ Figuur 4: De evolutie van het wagenpark in Belge.
Om te weten waar dit verkeer vandaan komt, worden er dagelijks op de Belgische wegen tellingen verricht die de intensiteit van het verkeer in kaart brengen. Van deze tellingen worden er dan uiteindelijk verkeersmodellen gemaakt zoals te zien is op figuur 4. Door middel van een kleurcodering wordt de verkeersdrukte aangegeven. Tevens worden deze verkeerstellingen ook gebruikt om de impact van wegwerkzaamheden in kaart te brengen. Voor aanvang van de wegwerkzaamheden wordt er een nultelling gedaan. Vervolgens wordt er tijdens de wegwerkzaamheden een tweede telling uitgevoerd welke vergeleken wordt met de nultelling, zodat men de impact van de wegwerkzaamheden kan analyseren.
(a)
(b)
(c)
Figuur 5: Verschillende manieren voor het tellen van het verkeer.
Vaak worden deze tellingen nog manueel uitgevoerd door studenten of werknemers [1]. Dit in combinatie met de verwerking van de data kan zorgen voor hoge arbeidskosten en een lange doorlooptijd. Tevens kan op de data van de handteller geen verdere analyse plaats vinden. Het gebruik van een tablet [3] bij een telling, lost een deel van dit probleem op. Om het probleem in zijn geheel op te lossen, dient er gekeken te worden naar een alternatieve vorm van verkeerstellingen. Zo’n alternatieve methode om de verkeersstromen in kaart te brengen, is door gebruik te maken van een pneumatische telslang. Zo’n telslang, afgebeeld op figuur 5(b), wordt meestal tijdelijk op een plaats geplaatst waar het dan het aantal assen van voorbijrijdende voertuigen kan tellen. Een nadeel van dit systeem is dat het enkel de assen van een voertuig kan tellen en niet het voertuig zelf, waardoor vrachtwagens ( die meer dan 2 assen hebben) een vertekend beeld kunnen geven. Deze manier van tellen zou ook mogelijk zijn voor lange termijn tellingen, maar door vandalisme of schade moet er regelmatig onderhoud gepleegd worden. Een nog andere manier van tellen is d.m.v. detectielussen in de grond. Deze lussen zullen door hun elektromagnetische eigenschappen voertuigen kunnen detecteren. Deze manier is vrij kos-
LIJST VAN FIGUREN
3
telijk omdat de lussen gemaakt zijn van koper en voor het installeren van zulke lussen de baan opengebroken moet worden . Op figuur 5(c) is een voorbeeld van detectielussen te zien. Hier is te ´ rijvak. Deze manier van tellen is permanent. zien dat er twee detectielussen geplaatst zijn op e´ en Met deze methode is het dus niet mogelijk om tijdelijke steekproeven te doen. Ook doen er zich volgens [8] nog fouten voor of is er een tijdelijke data-onbeschikbaarheid.
Figuur 6: Een camera voor het verkeer te meten.
In deze masterthesis wordt er gekeken naar een oplossing met camera’s om een nauwkeurigere en uitgebreidere analyse te kunnen doen. Omdat er al op veel plekken camera’s zijn geplaatst, die het huidige verkeer monitoren, kunnen deze wellicht ook gebruikt worden voor dit doel. Verder kunnen de camera’s ook gebruikt worden voor andere doeleinden zoals nummerplaatdetectie. Dit kan tevens zorgen voor een snellere adoptie van het systeem. Hoofdstuk 1 bespreekt de situering en doelstellingen van deze masterthesis. Nadien bespreekt hoofdstuk 2 de literatuurstudie. Hierna bespreekt hoofdstuk 3 de implementatie van een voorgrond / achtergrond segmentatie algoritme. Vervolgens bespreekt hoofdstuk 4 de implementatie van een tracking algoritme. Nadien bespreekt hoofdstuk 5 de verkregen resultaten. Uiteindelijk wordt in hoofdstuk 6 een algemeen besluit genomen en wordt er ook gesproken over mogelijke uitbreidingen voor het systeem.
Hoofdstuk 1
Situering en doelstelling 1.1
Doelstelling
(a)
(b)
Figuur 1.1: Schets van de opstelling en de te tellen richtingen.
Het doel van deze masterthesis is om een algoritme te ontwikkelen dat voertuigen telt aan een kruispunt per opgereden richting. De opstelling van de camera wordt aan de hand van figuur 1.1(a) duidelijk gemaakt. Zo wordt de camera aan de andere kant van het kruispunt geplaatst, waardoor de nadruk gelegd wordt op de toekomende voertuigen. Op figuur 1.1(b) wordt dit aangetoond door het blauwe voertuig dat volgens de rode stippellijn rijdt. Het is dus de bedoeling dat enkel deze voertuigen in rekening worden gebracht. Zo zijn er steeds 4 camera’s nodig om al het verkeer van dit kruispunt te tellen. Op deze figuur zijn 3 richtingen te zien waarnaar het blauwe voertuig kan rijden, namelijk rechts, rechtdoor en links. Dit is echter niet altijd zo het geval. Zo kan elk kruispunt een verschillend aantal richtingen hebben en op zich ook een andere vorm. Ook de kijkhoek van de camera is verschillend per kruispunt. Het is de bedoeling om een algoritme te ontwikkelen dat voertuigen aan eender welk kruispunt kan tellen. Hierdoor is het nodig om rekening te houden met vele verschillende factoren, zodat een universeel telsysteem voor verschillende kruispunten wordt bekomen. 5
6
1 Situering en doelstelling
1.2
Situering
Deze masterthesis bevindt zich binnen het domein van de computervisie. Dit domein bestaat uit het analyseren van camerabeelden om zo vervolgens een bepaalde beslissing te nemen. Dit valt te vergelijken met de werking van onze hersenen op basis van de data die afkomstig komt van onze ogen. Zo wordt computervisie reeds gebruikt bij het detecteren van fouten tijdens een produc¨ automatisering [10], maar ook voor het detecteren tieproces, wordt het gebruikt bij de industriele van gezichten bij compacte fototoestellen. In het verkeer wordt computervisie ook al toegepast. Een voorbeeld waarbij computervisie gebruikt wordt in het verkeer zijn de automatic number plate recognition (ANPR) camera’s. Deze camera’s gaan - door middel van computervisie - de nummerplaten van voertuigen herkennen, zodat geseinde wagens gedetecteerd worden. Zo beslaat de ´ domein, maar wordt dit gebruikt over meerdere domeinen. computervisie niet enkel e´ en
1.2.1
EAVISE
Figuur 1.2: Logo van de EAVISE onderzoeksgroep.
Mijn promotor Ir. Puttemans maakt deel uit van de onderzoeksgroep Embedded Artificially intelligent VISion Engineering (EAVISE) 1 . Deze computervisie onderzoeksgroep is gevestigd op Campus De Nayer te Sint-Katelijne-Waver en behoort tot de KU Leuven universiteit en Thomas More hogeschool. Het doel van deze onderzoeksgroep is het toepassen van state-of-the-art computervisie technieken ¨ problemen. Deze computervisie technieken worden dan nadien als een oplossing voor industriele ¨ geoptimaliseerd zodat het op een embedded platform kan werken, zoals bv. op GPU´s, DSP´s of FPGA´s. ´ van hun lopende projecten. Dit project bestaat uit het ontwikkelen en impleZo is ’InSight Out’ e´ en menteren van nieuwe methodes voor het analyseren van data, afkomstig van mobiele eye-tracking devices. Een ander lopend project is ’the active blind spot camera’. Het doel van dit project is om zwakke weggebruikers te detecteren in de dode hoek van een vrachtwagen. Ook hier wordt dit gedaan met behulp van een camera. Vele ongevallen die veroorzaakt worden met vrachtwagens, zijn te wijten aan de dode hoek. Aangezien de verplichte dodehoekspiegels weinig bevorderingen maken, wordt er gezocht naar alternatieve oplossingen. Door deze jarenlange ervaring in computervisie, kan deze onderzoeksgroep de nodige ondersteuning bieden bij het bestuderen en maken van het telsysteem. 1
http://www.eavise.be
1 Situering en doelstelling
1.2.2
7
FLIR ITS
Figuur 1.3: Logo voormalig Traficon en huidig FLIR ITS.
Deze masterthesis is in samenwerking met het bedrijf FLIR ITS 2 dat gelegen is te Marke. Eind 2012 migreerde Traficon in de groep FLIR en is het voortaan FLIR Intelligent Transportation Systems of kortweg FLIR ITS, een Westvlaamse KMO gespecialiseerd in cameragebasseerde verkeersanalyse. Het bedrijf is opgericht in het jaar 1992 met de ambitie marktleider te worden op het vlak van videodetectie voor verkeerstoepassingen. ´ van de producten die gemaakt worden door FLIR ITS. De TrafiCam is een Zo is de TrafiCam e´ en combinatie tussen een CMOS camera en een voertuig detector. Deze combinatie zorgt ervoor dat voertuigen gedetecteerd worden, zodat de aansturing van verkeerslichten dynamisch aangepast worden voor een betere doorstroming. Buiten gewone camera’s werkt FLIR ITS nu ook met thermische camera’s. Deze thermische camera’s doen infrarode waarnemingen, waardoor er geen rekening meer wordt gehouden met de belichting. Meer informatie over FLIR ITS is te vinden op de site.
1.3
Mogelijk gebruikte beeldverwerkingssoftware
Binnen de computervisie bestaan er reeds vele bibliotheken met algoritmes voor het manipuleren van beelden. De meerderheid van deze bibliotheken zijn geoptimaliseerd en bevatten vele stateof-the-art algoritmes. Omdat er voor deze masterthesis vooral software wordt geschreven en om ervoor te zorgen dat het systeem real-time functioneert, is het nodig om een goede keuze te maken tussen deze verschillende bibliotheken. ¨ Zo wordt er gekozen om de programmacode in C++ te schrijven. Deze objectgeorienteerde taal is een uitbreiding van de originele C taal. Omdat er reeds opensource bibliotheken met state-of-theart algoritmes te vinden zijn, wordt er hiervan gebruik gemaakt. Opensource software wilt in feite zeggen dat de broncode van deze software wordt vrijgegeven, zodat gebruikers vrij zijn om deze te bestuderen, te gebruiken en aan te passen. Doordat iedereen deze broncode kan raadplegen en aanpassen, wordt deze code dan ook continu verbeterd. Opensourcesoftware valt ook onder bepaalde licenties. Zo zijn er licenties die beperkingen opleggen op het gebruik van de broncode. Zo is alles onder de NPOSL-3.0 licentie verboden voor commercieel gebruik, terwijl alles onder de BSD-licentie vrij te gebruiken is. Met deze verschillende licenties moet er dus ook rekening gehouden worden bij de keuze van softwarebibliotheek. Zo wordt er gekeken of OpenCV, Libccv of BGSLibrary aan de eisen voldoen om gebruikt te worden. Deze drie bibliotheken zijn reeds veelgebruikte opensource bibliotheken. Zowel OpenCV als Libccv vallen onder de BSD-licentie en BGSLibrary valt onder de GPL-licentie. Deze drie bibliotheken worden allereerst nader verklaard. 2
http://www.flir.com/cvs/americas/en/traffic/view/?id=61993
8
1 Situering en doelstelling
Zo is OpenCV 3 een open source computer visie bibliotheek dat is ontwikkeld door Intel in het jaar 1999. Deze bibliotheek heeft de focus op real-time computer visie en machine learning en bevat meer dan 2500 verschillende functies om beelden te manipuleren en te maken. Sinds een grote release in 2006 is er in OpenCV ook een C++ interface ge¨ımplementeerd. Door een grote hoeveelheid state-of-the art technieken zijn ook bedrijven zoals Google, IBM, enz. de OpenCV bibliotheek gaan gebruiken. Een voordeel van OpenCV is dat het een multiplatform bibliotheek is, zodat het werkt onder Windows, Linux of MacOSX. Ook bevat de OpenCV bibliotheek momenteel al enkele implementaties op GPU en zijn er ook mogelijkheden om multi-threaded te werken. Deze bibliotheek bevat een uitgebreide documentatie [6][12] en heeft ook een grote community. Libccv 4 is een modern open-source computervisie framework met allerlei verschillende computervisie methodes. Zelf beweren ze 5 snellere algoritmes te hebben dan die in de OpenCV bibliotheek, omdat Libccv nog steeds werkt met een C-API. Libccv is een bibliotheek die momenteel nog mono-threaded werkt, wat het ook weer trager maakt. Ook bevat Libccv momenteel nog geen implementatie om op GPU te werken. Het was echter moeilijk om documentatie en informatie over de werking van de verschillende Libccv functies te vinden, wat het moeilijk maakt om aanpassingen te doen aan de algoritmes. BGSLibrary 6 is een C++ framework om voorgrond/achtergrond segmentatie toe te passen. Dit open-source framework, dat door Andrews Sobral is gemaakt, bevat momenteel 34 verschillende segmentatie methodes die elk gebaseerd zijn op reeds verschenen papers. De broncode is eenvoudig te downloaden van de website en bevat buiten deze 34 methodes ook een demo project voor Visual Studio 2010. Deze bibliotheek valt onder de GPL licentie. Deze licentie is minder geliefd door een bedrijf, omdat als er voor deze bibliotheek wordt gekozen, het volledige systeem ook onder deze GPL licentie valt. Het gevolg hiervan is dat de volledige broncode ook moet worden vrijgegeven. Doordat BGSLibrary onder deze licentie valt, wordt er niet gekozen om deze bibliotheek te gaan gebruiken De keuze die gemaakt wordt tussen OpenCV enerzijds en Libccv anderzijds, wordt gemaakt op basis van de beschikbare documentatie en de gebruiksvriendelijkheid. Omdat OpenCV een duidelijke documentatie heeft - die ervoor zorgt dat het ook gebruiksvriendelijk is - wordt er voor deze bibliotheek gekozen. Als er gekeken wordt naar de performantie van de OpenCV bibliotheek, dan kan er geconcludeerd worden dat deze bibliotheek ook vele real-time state-of-the-art algoritmes bevat.. Door de vooruitstrevende denkwijze van OpenCV blijft deze bibliotheek ook up-to-date en bevat het ook altijd state-of-the-art algoritmes.
1.4
State-of-the-art in automatische telalgoritmes voor voertuigen
¨ automatiseringsprocessen. De Computervisie is zoals eerder vermeld veel gebruikt bij industriele markt van computervisie is niet beperkt tot enkel deze processen. Zo bestaan er ook algoritmes om het verkeer te tellen. In dit deel zullen enkele reeds bestaande telalgoritmes voor voertuigen besproken worden. LogiRoad 7 is een Frans bedrijf dat een leider is op vlak van verkeersanalyse met behulp van camera’s. Zo is er het OD Soft, dat een analyse kan doen van de verkeersstromen aan kruispunten 3
http://opencv.org http://libccv.org 5 http://libccv.org/post/an-elephant-in-the-room/) 6 https://github.com/andrewssobral/bgslibrary 7 http://www.logiroad.com 4
1 Situering en doelstelling
9
en ronde punten. Zo kan dit analyseren van waar de voertuigen komen en naar waar er gereden wordt. Vervolgens is het ook in staat om te categoriseren of het om een auto, een motor, een truck, ¨ enz. gaat. In 2012 is LogiRoad genomineerd voor de nationale competitie voor het creeren van innovatieve technologie. TRAZERr ( TRaffic AnalyZer and EnumeratoR )8 is een technologie dat gebruikt wordt om data te verkrijgen uit het verkeer. Zo biedt het steeds accurate data aan onder elke verkeersconditie. TRAZERris Suite een oplossing voor het analyseren van het verkeer. Deze software is in staat om zowel op vooraf opgenomen beelden als op live beelden, van een ip-camera, een snelle en automatische processing te doen. In dit softwarepakket zit een configuratie module, een automatische verkeersteller en classifier en een feedback module. Deze software kan bijvoorbeeld afdraaiende voertuigen tellen alsook het verkeers per rijvak aan een kruispunt tellen.
1.4.1
Moving Vehicle Detection for Measuring Traffic Count
In de paper ´Moving Vehicle Detection for Measuring Traffic Count Using OpenCV´[11] wordt er ook al gesproken over een cameragebasseerd telsysteem van voertuigen met gebruik van de OpenCV bibliotheek. Deze paper beschrijft de werkwijze van dit systeem en de resultaten van experimenten die op een snelweg zijn uitgevoerd. Er wordt tevens onderscheid gemaakt tussen lichte voertuigen, zware voertuigen en motoren. Het resultaat van deze paper is dat er een systeem is ge¨ Effectieve cijfers maakt, die voertuigen kan tellen en classificeren in de verschillende categorieen. worden in deze papers niet gegeven, wat het moeilijk maakt om dit systeem nadien te vergelijken.
8
http://www.kritikalsolutions.com/products/traffic-analyzer.html
Hoofdstuk 2
Literatuurstudie
Figuur 2.1: Volgorde van de bestudeerde stappen.
In dit hoofdstuk worden de methodes besproken die gebruikt kunnen worden om tot een robuust en real-time telsysteem te komen. De verschillende stappen die in dit hoofdstuk opgenomen worden, worden afgebeeld op figuur 2.1. Allereerst bespreekt paragraaf 2.1 enkele voorbereidende stappen op de verkregen beelden. Nadien bespreekt paragraaf 2.2 de verschillende voorgrond / achtergrond segmentatie methodes die de voertuigen uit de achtergrond halen. Vervolgens bespreekt paragraaf 2.3 enkele morfologische operaties die na de segmentatie van belang zijn. Hierna bespreekt paragraaf 2.4 het volgen van de voertuigen doorheen het beeld. Praagraaf 2.5 daarentegen bespreekt de detectie van voertuigen met behulp van een voertuigdetector.
2.1
Voorbereidende stappen
Beelden die rechtstreeks van een videocamera komen, zijn in de meeste gevallen niet geschikt om er rechtstreeks segmentatie op toe te passen. Deze beelden kunnen onderhevig zijn aan ruis, wat voor een nadelige invloed op de segmentatie zorgt. Daarom is het nodig om deze beelden eerst te bewerken, vooraleer er voorgrond / achtergrond segmentatie op toegepast kan worden. 11
12
2 Literatuurstudie
Figuur 2.2: De twee voorbereidende stappen.
Dit hoofdstuk bespreekt twee veelgebruikte manieren om ruis weg te filteren. De twee methodes waarover dit gaat zijn het Gaussiaans vervagen(Gaussian blur) en de mediaanfilter. Zo gaat er ´ van deze methodes te gebruiken. Vooraleer deze termen een keuze gemaakt worden om e´ en besproken worden, wordt er eerst wat meer uitleg over de term ruis gegeven.
2.1.1
Ruis
Beelden die van een camera komen hebben een kans dat ze ruis bevatten. Ruis zijn ongewenste signalen die ontstaan tijdens de transmissie of compressie van data. Zo zorgt ruis dat er een plots verschil in pixelwaarde is, waardoor bij segmentatie deze ruispixels mee als voorgrond worden gesegmenteerd. Hierdoor ontstaan foute detecties, wat nadelig is voor dit systeem. Doordat ruis een nadelige invloed heeft op de segmentatie, is het nodig deze voor de segmentatie uit de beelden te filteren.
Figuur 2.3: Voorbeeld Salt & pepper ruis.
Ruis voor als dynamische of statische ruis. Dynamische ruis is ruis dat zonder patroon voorkomt op de beelden. De plaatsen waar ruis voorkomt is dus telkens variabel en hierdoor ook moeilijk te bepalen. Een voorbeeld van dynamische ruis is het bekende salt’n pepper ruis. Een voorbeeld van salt’n pepper ruis op een beeld is te zien op figuur 2.3. Salt’n pepper ruis bestaat uit witte of zwarte pixels die willekeurig in het beeld voorkomen. In de meeste gevallen ontstaat salt’n pepperruis als gevolg van bit-errors door de transmissie. Statische ruis daarentegen is ruis dat steeds op eenzelfde plaats voorkomt. De oorzaak van statische ruis is meestal te wijten aan defecte fotodiodes in de camera. Deze fotodiodes bevinden zich achter de lens van de camera. De taak van deze diodes is het omzetten van licht naar een elektrisch signaal. Zo is er voor elke pixel van een beeld een corresponderende fotodiode. Van
2 Literatuurstudie
13
zodra een fotodiode defect is, zal de pixel foute informatie bevatten. In dit geval wordt er gesproken over statische ruis. Er wordt verwacht dat bij het opstellen van het systeem nog geen ruis aanwezig is. Omdat ruis voorkomt op een onbepaald moment en om ervoor te zorgen dat het systeem blijft werken - indien er plots ruis aanwezig is - wordt er automatisch aan ruisfiltering gedaan. Om dit te kunnen doen, worden vervolgens twee methodes besproken.
2.1.2
Gaussian blurring
Een veelgebruikte manier om salt’n pepper ruis uit een afbeelding te halen is met behulp van het Gaussiaans vervagen of ook Gaussian blurring. Om met deze methode ruis te verwijderen, wordt er in feite een convolutie gedaan met een Gaussiaanse functie. Zo’n Gaussiaanse functie ziet er voor een twee-dimensionaal vlak vervolgens uit:
G(x, y) =
1 − x2 + y2 e 2πσ2 2σ2
(2.1)
x = de afstand over de x-as van de oorsprong y = de afstand over de y-as van de oorsprong σ= de standaardafwijking van de Gaussiaan
Figuur 2.4: Gaussische functie visueel voorgesteld.
De berekende waarden hiervan maken een convolutiematrix met centraal gelegen diegene met de hoogste invloed. Een visueel voorbeeld hiervan wordt getoond op figuur 2.4. Hierop is te zien dat de top centraal gelegen is. Door deze matrix enerzijds horizontaal en anderzijds verticaal over de afbeelding te schuiven, wordt er telkens een gewogen gemiddelde van alle omliggende pixels gemaakt. De waarde van de centrale pixel in de matrix heeft dan als waarde dit gewogen gemiddelde. Het is echter ook mogelijk om met een 2D structuurelement dit toe te passen. Zo gaat de OpenCV functie GaussianBlur gebruik maken van een NxN structuurelement.
14
2 Literatuurstudie
(a) Originele figuur met 1% salt’n pepper ruis
(b) Gaussian Blurring met 9x9 structuurelement van figuur 2.5(a)
(c) Originele figuur met 5% salt’n pepper ruis
(d) Gaussian Blurring met 9x9 structuurelement van figuur 2.5(c)
Figuur 2.5: Voorbeeld Gaussian Blurring.
Gaussian blurring heeft als effect dat het werkt als een laagdoorlaatfilter. Zo bevat de resulterende afbeelding minder ruis, maar een nadelig effect van Gaussian blurring is dat er hierdoor ook minder details te zien zijn. Dit wordt ook aangetoond op figuur 2.5. Op figuur 2.5(d) valt er ook te zien dat bij meer salt’n pepper ruis, er grotere fouten gemaakt worden. Hierdoor wordt de figuur ook minder duidelijk. Gaussian blurring zal dus de grote uitschieters van de salt´n pepper ruis vervagen, maar de details van de afbeelding zullen ook minder duidelijk worden.
2.1.3
Mediaanfilter
Een andere manier om de eventuele ruis uit een beeld te halen, is door gebruik te maken van een mediaanfilter. Een mediaanfilter schuift een structuurelement over het beeld en bij elke pixel wordt de mediaan genomen van alle omliggende pixelwaarden. Deze mediaan wordt vervolgens gebruikt om de centrale pixel te vervangen. Doordat er hier met de mediaan wordt gewerkt, worden uitschieters afkomstig van salt’n pepper ruis eenvoudig uit een beeld gefilterd.
2 Literatuurstudie
15
Figuur 2.6: Mediaan berekenen van omliggende pixels. Structuurelement van 3x3.
(a) Originele figuur met 5% salt’n (b) Originele figuur met 25% salt’n (c) Originele figuur met 55% salt’n pepper ruis pepper ruis pepper ruis
(d) Resultaat mediaanfilter van figuur (e) Resultaat mediaanfilter van figuur (f) Resultaat mediaanfilter van figuur 2.7(a) 2.7(b) 2.7(c)
Figuur 2.7: Voorbeeld mediaanfilter.
Zoals in figuur 2.7 te zien is, worden de details minder hard herkenbaar, indien er meer salt’n pepper ruis in het beeld aanwezig is. Figuur 2.7(e) toont aan dat bij 25% salt’n pepper ruis het resultaat nog voldoende is om er segmentatie op toe te passen. Wanneer er meer dan 50% salt’n pepper ruis in een beeld zit, dus meer ruis dan origineel beeld, is het resultaat niet genoeg nauwkeurig meer om er verder mee te werken. Dit komt doordat de mediaan nu ook ruis is. Met deze voorbereidende stappen gaat het segmentatieproces minder invloed hebben van ruis. Hierdoor gaan de resultaten beter zijn, dan dat er geen voorbereidende stappen worden gedaan. ´ van beide methodes gekozen. Bij de implementatie wordt er voor slechts e´ en
16
2.2
2 Literatuurstudie
Voorgrond / achtergrond segmentatie
Wanneer de verkregen beelden gefilterd zijn van ruis, kan er voorgrond / achtergrond segmentatie op deze beelden toegepast worden. In dit hoofdstuk worden enkele verschillende voorgrond / achtergrond segmentatie-methodes besproken, namelijk frame differencing, running average, approximated mediaan en de mixture of Gaussians. Eerst wordt er wat meer uitleg gegeven wat deze voorgrond / achtergrond segmentatie doet en waarvoor deze gebruikt wordt.
2.2.1
Wat is voorgrond / achtergrond segmentatie?
Om uit de binnenkomende beelden voertuigen te kunnen halen, moet er een onderscheidt tussen voertuigen en achtergrond gemaakt worden. Een van de manieren om dit te doen is door middel van een voertuigdetector. Deze voertuigdetector gaat aan de hand van een model voertuigen zoeken in een beeld. Zo is een nadeel van deze methode de lange uitvoertijd. Om voertuigen uit een beeld te zoeken aan de hand van een model, wordt dit model over het beeld verschoven. Telkens wordt er gekeken of er overeenkomsten tussen model en beeld zijn. Omdat de voertuigen ook een verschillende grootte hebben, wordt er ook op schaal met dit model vergeleken. Deze procedure vraagt enorm veel tijd, vooraleer een volledig beeld is overlopen. Wanneer er voor deze methode wordt gekozen, waarbij geen extra intelligentie wordt aan toegevoegd, is het niet haalbaar om een real-time systeem op te zetten. Om dit op te lossen, wordt er in deze masterthesis gebruik gemaakt van voorgrond / achtergrond segmentatie. Zo gaat deze procedure de beweging van de voertuigen gebruiken om voertuigen (voorgrond) uit de achtergrond te halen. Op deze manier wordt de rekentijd verminderd, waardoor ¨ het systeem efficienter te werk gaat. Om voertuigen in een beeld te herkennen, wordt er gekeken naar de beweging die deze voertuigen maken. Zo gaat een rijdend voertuig een verschil in pixelwaarden teweeg brengen. Om een verschil te maken, wordt er eerst een referentie gemaakt. Zo maken de meeste voorgrond / achtergrond segmentatie-methodes gebruikt van een achtergrondmodel als referentie. Zo’n achtergrondmodel wordt per methode op een verschillende manier opgebouwd. Hoe elke methode dit doet, wordt verder in dit hoofdstuk besproken. Nadat een achtergrondmodel is opgebouwd, wordt elk nieuw beeld met dit model vergeleken. Zo gaat het resultaat van deze vergelijking een voorgrondbeeld geven. Een voorgrondbeeld bestaat slechts uit twee waarden. Bij een 8 bit beeld krijgt alles wat tot de achtergrond hoort een waarde nul en alles wat tot de voorgrond hoort een waarde 255. Zo kan de voorgrond bestaan uit voertuigen, mensen, ... maar ook andere objecten die voor een verschil in pixelwaarde zorgen. Omdat de rest van het systeem gebruik maakt van de resultaten van deze segmentatie, is het nodig om een robuuste voorgrond / achtergrond segmentatie-methode te gebruiken. Indien dit niet het geval is, kan het systeem in bepaalde situaties niet goed functioneren. Een goed robuust voorgrond / achtergrond segmentatie-algoritme moet op elke moment van de dag en bij alle weersomstandigheden een zelfde resultaat geven.
2 Literatuurstudie
17
(a) Originele figuur
(b) Voorbeeld nadelig effect weersomstandigheden en lichtintensiteit
Figuur 2.8: Voorbeeld nadelig effect weersomstandigheden en licht.
Het algoritme moet zo aan volgende vereisten voldoen:
• Het algoritme moet bestand zijn tegen alle weersomstandigheden zoals regen, sneeuw of mist. Sneeuw kan bijvoorbeeld zorgen voor meer fout positieven, doordat het zorgt voor een groot verschil in pixelwaarde.
• Het algoritme moet ook tegen een plots verschil in lichtintensiteit kunnen. Dit verschil in lichtintensiteit ontstaat wanneer bijvoorbeeld de zon voor / achter de wolken komt, de lichten van een auto in de lens schijnen, ... Zo is op figuur 2.8(b) te zien dat de lichten van de voertuigen een heldere vlek veroorzaken. Dit geeft als resultaat dat er een groot verschil in lichtintensiteit is. Hierdoor worden deze pixels ook als voorgrond gesegmenteerd.
• Een andere uitdaging is dat het bestand moet zijn tegen bewegende voorwerpen op de achtergrond. Zo’n voorwerpen kunnen vlaggen, bomen in de wind, ... zijn. Door de beweging is er een kans dat de pixelwaarden groot genoeg verschillen, zodat deze pixels ook als voorgrond gesegmenteerd worden.
• Verder moet het algoritme ook het verschil weten tussen een voertuig en zijn schaduw. Schaduwen geven een te grote detectie van een voertuig. Om schaduwen te detecteren moet er vooral gezien worden naar verschil in lichtintensiteit, terwijl de structuur hetzelfde gebleven is. Door het nadelig effect van schaduw kunnen meerdere blobs als e´ e´ geheel gezien worden, wat uiteraard moet worden vermeden.
• Uiteindelijk moet het algoritme als laatste ook tegen camera shaking kunnen. Meestal wordt er verondersteld dat de camera statisch wordt geplaatst, maar door trillingen krijgen de beelden een globale translerende beweging. Deze beweging gaat voor de meeste voorgrond / achtergrond segmentatie-methodes voor meer detecties zorgen. Om dit te vermijden is het nodig om deze beelden eerst statisch te maken. Hoe dit gedaan wordt, wordt in deel 2.2.2 besproken.
18
2.2.2
2 Literatuurstudie
Beeldstabilisatie
Meestal wordt er verondersteld dat een camera statisch wordt geplaatst. Deze veronderstelling is in vele gevallen niet zo. Door eventuele trillingen - afkomstig van de omgeving - gaat de camera beginnen bewegen. Dit effect wordt ook camera shaking genoemd.
(a) Camera shake frame x.
(b) Camera shake frame x+1.
(c) 2.9(a) - 2.9(b), theshold = 10.
Figuur 2.9: Voorbeeld nadelig effect camera shake.
Een nadelig effect van deze camera shaking is dat er bij de meeste voorgrond / achtergrond segmentatie-algoritmes er meer detecties worden gegeven, die normaal niet gedetecteerd mogen worden. Hierdoor daalt de betrouwbaarheid van het algoritme drastisch. Een voorbeeld waar het nadelig effect van deze camera shaking wordt getoond, is te zien op figuur 2.9. Hier is op figuur 2.9(a) en figuur 2.9(b) respectievelijk frame x en frame x+1 te zien. Wanneer beide frames van elkaar worden afgetrokken, wordt figuur 2.9(c) verkregen. Om het resultaat beter aan te tonen, wordt er gebruik gemaakt van een grenswaarde(threshold). Er wordt hier gekozen om een threshold met waarde 10 te gebruiken, zodat het resultaat duidelijk wordt aangetoond. Deze figuur is slechts een verschil tussen twee frames, waarmee de beweging tussen beide frames wordt aangetoond. Om van deze shaking camera’s toch stabielere beelden te maken, wordt er gezocht welke beweging er gemaakt wordt, zodat nadien deze beweging tegen gewerkt kan worden. Deze compensatie wordt gedaan door het verschuiven van het frame in tegengestelde richting, zodat de beweging neutraal gemaakt wordt. Wanneer bijvoorbeeld beeld x+1 naar boven is bewogen, wordt deze naar beneden verschoven tot deze terug in de originele positie komt. Een methode om deze translatie te meten is d.m.v. fasecorrelatie. Fasecorrelatie gaat in het frequentiedomein beide beelden vergelijken om zo de relatieve translatie te berekenen. OpenCV heeft een eigen functie phaseCorrelate() die de relatieve translatie in x en y coordinaten als resultaat teruggeeft. Door het beeld te verschuiven tegengesteld aan deze x en y waarde, wordt de beweging tegengewerkt. Het enige probleem dat bij deze verschuiving voordoet, is dat het beeld twee zwarte randen krijgt. Door de verschuiving van een beeld komt een deel van het verschoven beeld buiten zijn grenzen, waardoor er aan de andere kant zwarte randen ontstaan. Een andere methode is d.m.v. feature points. Feature points zijn kenmerkende punten in een beeld die eenvoudig terug te vinden zijn. Door in elk beeld de feature points te zoeken, is het mogelijk om de feature points van het nieuwe beeld te vergelijken met die van het vorige beeld. Wanneer een goede feature point descriptor en matcher gekozen worden, worden goede resultaten verkregen. Zo bevat de nieuwste OpenCV bibliotheek zelf een klasse ’videostab’ die gebruik maakt van deze methode om beelden stabiel te maken. Echter is het nog niet mogelijk om dit real-time toe te passen, waardoor beelldstabilisatie niet wordt toegepast in dit systeem.
2 Literatuurstudie
2.2.3
19
Verschillende soorten segmentatiemethodes
Na de korte inleiding over voorgrond / achtergrond segmentatie en beeldstabilisatie worden er in dit deel vier verschillende methodes besproken om voorgrond / achtergrond segmentatie te doen. Elke methode maakt gebruik van een achtergrondmodel en deze wordt ook per methode verschillend opgebouwd. Frame Differencing Van alle voorgrond / achtergrond segmentatie-methodes is deze methode de eenvoudigste. Deze methode gaat telkens het verschil berekenen tussen het huidige frame en een voorgaand frame[9][15]. Elk verschil wordt zo aangetoond als voorgrond en de rest als achtergrond. Wanneer er maar kleine bewegingen zijn, die moeilijk te detecteren zijn, wordt er gebruik gemaakt van een buffer die de laatste n frames bijhoudt, zodat de beweging over n frames groter worden.
Background(t + 1) = | f rame(t + 1) − f rame(t − n)|
(2.2)
Zo bevat Background(t+1) het verschil tussen frame(t+1) en frame(t-n). Wanneer er nu met een thresholdwaarde op Background(t+1) getest wordt, worden de verschillen tussen beide frames duidelijk. Het principe van de threshold is testen of een pixelwaarde groter / kleiner is dan de ingestelde thresholdwaarde. Wanneer de pixelwaarde groter is, wordt het als voorgrond gezien en wanneer deze kleiner is als achtergrond.
(a) Frame x.
(b) Frame x + 2.
(c) Frame Differencing met n = 2
Figuur 2.10: Frame Differencing voorbeelden.
Een voordeel van frame differencing is dat bij een plots verschil in lichtintensiteit, dit slechts gedurende 2 frames merkbaar is. Indien er gebruik gemaakt wordt van een buffer om de n laatste frames bij te houden, dan is de fout n frames merkbaar. Een nadeel van frame differencing is dat er een buffer van n frames wordt bijgehouden om kleine bewegingen te detecteren. Deze buffer heeft nood aan extra geheugen, wat op een embedded platform niet altijd al te veel van aanwezig is. Een voorbeeld van frame differencing, waarbij het verschil tussen 2 frames wordt genomen, is te zien op figuur 2.10(c).
20
2 Literatuurstudie
Running Average Een andere methode om aan voorgrond / achtergrond segmentatie te doen, is om het gemiddelde van pixelwaarde bij te houden [13]. Zo wordt het achtergrondmodel opgebouwd, door telkens het gemiddelde te nemen van pixelwaarden tussen het reeds gemaakte achtergrondmodel en het huidige frame. Er wordt een leerfactor al pha in rekening gebracht, zodat er meer gesproken wordt over een gewogen gemiddelde. De waarde van deze al pha is gelegen tussen 0 en 1 en maakt het verschil tussen een snel / traag lerend systeem. Deze factor wordt gebruikt om het belang van elk nieuw frame aan te geven om het gemiddelde te berekenen. Deze factor wordt in onderstaande formule meer duidelijk gemaakt.
Background(t + 1) = (1 − α)Background(t) + α f rame(t + 1)
(2.3)
Indien deze α klein van waarde is ( < 0.2) dan is het systeem traag lerend. Zo’n traag lerend systeem is in de meeste gevallen stabiel, doordat de invloed van elk nieuw frame relatief klein is t.o.v. het huidige achtergrondmodel. Als er dan toch nog een fout oploopt in het model, dan blijft deze fout redelijk lang in het systeem. Voor een snel lerend systeem is de invloed van een nieuw frame groter met als gevolg dat het model minder verzekerd is van fouten. Indien er toch fouten in komen, verdwijnen deze wel sneller uit het model.
(a) Originele figuur
(b) Running average met α = 0.01
(c) Running average met α = 0.05
Figuur 2.11: Running Average voorbeelden.
Het voordeel van deze methode is dat er geen buffer van vorige n frames moet worden bijgehouden. Hierdoor is er minder geheugen nodig. Door gebruik te maken van een gewogen gemiddelde is het algoritme robuust tegen geleidelijke veranderingen in lichtintensiteit. Een nadeel van running average is dat bij plotse veranderingen van lichtintensiteit de volgende achtergrondmodellen fouten gaan bevatten totdat het achtergrondmodel is aangepast aan de huidige lichtintensiteit. Deze methode heeft een periode van initialisatie nodig vooraleer de achtergrond is op opgebouwd. Een voorbeeld van running average segmentatie is te zien op figuur 2.11. Approximated Mediaan Nog een andere manier om een achtergrondmodel op te bouwen dan het gemiddelde te nemen, is door gebruik te maken van de mediaan van pixelwaarden over de tijd[5][15]. Om de mediaan te berekenen over de tijd, is er een buffer nodig van n frames. Nadien worden telkens de overeenkomstige pixels ( van vorige n frames ) gesorteerd om er nadien de mediaan van te berekenen. Deze manier van werken, waarbij een sorteeralgoritme en een buffer gebruikt wordt, zorgt ervoor dat de mediaan berekenen een rekenintensief proces is en in geen geval de
2 Literatuurstudie
21
doelstelling om het real-time te laten functioneren kan halen. Een oplossing hiervoor is de approximated mediaan. Het principe van deze approximated mediaan is om het achtergrondmodel zodanig aan te passen door telkens +1/-1 te doen, als de pixelwaarde van het huidige frame respectievelijk groter / kleiner is dan het huidige achtergrondmodel. Door nadien het huidige frame van dit achtergrondmodel af te trekken en ook hier een threshold te gebruiken, wordt de voorgrond op een rekenvriendelijke manier van de achtergrond gesegmenteerd.
(a) Originele figuur
(b) Approximated mediaan
Figuur 2.12: Approximated mediaan voorbeelden.
Het algoritme wordt uitgelegd in onderstaande pseudocode. Algorithm 1 Approximated Mediaan 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
if Frame(x,y) > Model(x,y) then Model(x,y) = Model(x,y) +1 else Model(x,y) = Model(x,y) - 1 end if Verschil(x,y) = Frame(x,y) - Model(x,y) if Verschil(x,y) > Threshold then Voorgrond else Achtergrond end if
Het resultaat van de approximated mediaan is te zien op figuur 2.12(b). Een voordeel van de approximated mediaan is - door het steeds +1 / -1 doen - er geen sorteeralgoritme en vooral geen buffer van n frames gebruikt wordt. Deze rekenintensieve processen die nu niet gedaan worden, zorgen ervoor dat de approximated mediaan wel real-time kan functioneren. Een nadeel is dan weer dat bij een plots verschil in lichtintensiteit het een tijd duurt tot het systeem zich heeft aangepast aan de nieuwe lichtintensiteit.
22
2 Literatuurstudie
Mixture of Gaussians Een laatste manier die besproken wordt dat voorgrond / achtergrond segmentatie doet, is de mixture of Gaussians. Deze manier om een achtergrondmodel op te bouwen, wordt gedaan door gebruik te maken van een statistisch model. Zo’n model - dat opgebouwd wordt door een gemiddelde en een standaardafwijking - gebruikt de geschiedenis van pixelwaarden om deze parameters een waarde te geven. Bij situaties waarbij alle pixels in een beeld met een gelijke waarde verschillen, is slechts 1 Gaussiaan nodig. Bij een verkeers scene zijn er meerdere verschillende situaties waarbij de pixelwaarden op een verschillende manier verschillen. Hiervoor worden er dus meerdere Gaussiaanse functies gebruikt of dus een mixture of Gaussians[13][5][15]. Deze manier om een achtergrondmodel op te bouwen is ontwikkeld door Stauffer en Grimson en is een van meest gebruikte manieren van zijn soort. Veronderstel een pixel ( x, y) uit een frame. Deze pixel wordt hier gezien als ci uit frame i. Voor kleurfoto’s is deze ci een 3 elementsvector waarin de waarden van de RGB kleuren rood, groen en blauw in zitten. De geschiedenis van pixel x,y op elk moment is:
c1 , c2 , ...ci
(2.4)
Een bewegend object gaat meer variantie produceren dan een statisch object. Het modelleren van de geschiedenis gebeurt door K Gaussiaanse distributies. Deze K wordt volgens [17] meestal gekozen tussen 3 en 5, maar is afhankelijk van het beschikbare geheugen. De waarschijnlijkheid dat de huidige pixel een bepaalde waarde heeft ziet er als volgt uit.
K
p(ct ) = ∑ ωi,t ∗ η(ct , µi,t , σ2i,t )
(2.5)
i=1
Met K = het aantal Gaussische verdelingen. ωi,t = schatting van het gewicht per Gaussiaan µi,t = gemiddelde waarde per Gaussiaan σ2i,t = de standaardafwijking per Gaussiaan De Gaussische waarschijnlijkheidsfunctie η ziet er als volgt uit.
−ct −µ2 1 η(ct , µi,t , σ2i,t ) = √ ∗ e 2σ2 σ 2π
(2.6)
2 Literatuurstudie
23
Figuur 2.13: Mixture of Gaussians grafiek.
Deze formules maken K Gaussianen zoals wordt aangegeven op figuur 2.13. De paarse, groene en cyane lijnen zijn de K Gaussianen en de rode lijn f (x) is de gesuperponeerde functie op deze K Gaussianen. Elke nieuwe pixel wordt nadien vergeleken worden met de K Gaussianen totdat er een match is gevonden. Er is pas een match als deze pixelwaarde binnen de 2,5 x standaardafwijking van het gemiddelde ligt. Indien er geen match is en de pixelwaarde binnen het rode gebied ligt (figuur 2.13, dan wordt de verdeling die het minst waarschijnlijk is vervangen door een verdeling met de huidige waarde als gemiddelde. Deze nieuwe verdeling heeft in eerste instantie een laag gewicht. Indien er ´ van de Gaussianen (dus de pixel is achtergrond), dan wordt het gewicht wel een match is met e´ en van deze match als volgt aangepast:
ωk,t = α + (1 − α)ωk,t−1
(2.7)
De andere modellen worden als volgt aangepast, zodat ze een lager gewicht krijgen.
ωk,t = (1 − α)ωk,t−1
(2.8)
α is de leerfactor van het gewicht. Deze bepaald met welke mate aanpassingen worden opgenomen in de achtergrond. Het resultaat van de Mixture of Gaussian is te zien op figuur 2.14
(a) Originele figuur
(b) Voorbeeld MOG
Figuur 2.14: Mixture of Gaussians voorbeelden.
24
2 Literatuurstudie
In de OpenCV bibliotheek is er reeds een mixture of Gaussians-methode ge¨ımplementeerd onder de naam: BackgroundSubtractorMOG21 . De documentatie van deze OpenCV klasse geeft nog extra parameters aan die aangepast kunnen worden in deze klasse. Zo kan bijvoorbeeld de parameter ’fTau’ aangepast worden om schaduwen weg te filteren. Deze 4 verschillende methodes worden in hoofdstuk 3 vergeleken om zo de beste methode te selecteren. Het gevormde voorgrondbeeld bevat in vele gevallen weer een vorm van ruis. Deze ruis zijn nu witte pixels die mee als voorgrond worden gesegmenteerd. Vooraleer er verdere analyse op deze beelden worden gedaan, moet eerst deze ruis van het voorgrondbeeld verwijderd worden. Hoe dit gedaan wordt, wordt in het volgende hoofdstuk besproken.
2.3
Morfologische operaties
Het resultaat van een voorgrond / achtergrond segmentatie met vervolgens een threshold maakt een voorgrondbeeld waarop de voorgrond wordt voorgesteld door witte pixels. Doordat er gebruik wordt gemaakt van een threshold, is het mogelijk dat individuele pixels net boven deze thresholdwaarde komen en dus als voorgrond worden gesegmenteerd. Hierdoor ontstaan er individuele voorgrondpixels die het systeem nadelig kan be¨ınvloeden. Om deze witte pixels weg te werken, bestaan er enkele morfologische operaties. Deze morfologische operatie worden in dit deel besproken.
Figuur 2.15: Morfologische operaties.
Erosie en dilatie zijn primaire morfologische operaties die individuele pixels uit een voorgrondbeeld kan halen. Zo gaat erosie de individuele witte pixels wegfilteren en dilatie gaat alle individuele zwarte pixels uit het voorgrondbeeld halen door extra witte pixels toe te voegen. Met andere woorden, erosie gaat een licht voorwerp op een donkere achtergrond verkleinen en dilatie gaat dit in het beeld vergroten. Beide morfologische operaties worden later apart besproken worden.
2.3.1
Erosie
Een van deze morfologische operaties is erosie. Bij erosie wordt er een structuurelement over het beeld geschoven en wordt er gekeken naar de pixelwaarden binnenin dit structuurelement. De vorm van dit structuurelement kan verschillend zijn als ook de grootte. Zo zijn de meest gebruikelijke vormen van het structuurelement ellipsvormig, vierkantig en kruisvormig. De grootte van het structuurelement wordt in de meeste gevallen ( wanneer de aan te passen pixel in het centrum ligt) oneven gekozen. Zo gaat erosie kijken naar de centrale pixel. Indien deze de waarde 255 1
http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html
2 Literatuurstudie
25
heeft, dan wordt er verder gekeken naar alle omliggende pixels. Wanneer deze dan ook allemaal de waarde 255 hebben, blijft deze centrale pixel ook de waarde 255 hebben. Alle andere gevallen zullen ervoor zorgen dat de centrale pixel de waarde nul krijgt.
(a) Segmentatie zonder erosie
(b) Segmentatie met erosie
Figuur 2.16: Voorbeeld van Erosie.
Het resultaat hiervan is dat de witte lijnen smaller gaan worden en de individuele witte pixels van salt’n pepper ruis gefilterd worden. Dit resultaat is te zien op figuur 2.16(b).
2.3.2
Dilatie
Bij dilatie wordt eigenlijk het omgekeerde proces gedaan dan bij erosie. Zo gaat dilatie individuele zwarte pixels uit het beeld halen door extra witte pixels toe te voegen. Ook dit wordt weer aan de hand van een structuurelement gedaan. Zo’n structuurelement kan dezelfde vorm en groottes hebben als bij erosie. Zo wordt er bij dilatie ook eerst naar de centrale pixel gekeken. Indien deze pixel de waarde nul heeft, wordt er gekeken naar alle omliggende pixels. Als alle omliggende pixels ook de waarde nul hebben, blijft de waarde van de centrale pixel ook nul. In de andere gevallen zal de centrale pixel de waarde 255 krijgen.
(a) Segmentatie zonder dilatie
(b) Segmentatie met dilatie
Figuur 2.17: Voorbeeld van Dilatie.
Dilatie geeft als gevolg dat de individuele zwarte pixels van salt’n pepperruis uit de afbeelding worden gehaald en de randen van donkere lijnen hierdoor smaller worden.
26
2.3.3
2 Literatuurstudie
Opening & Closing
Omdat erosie de randen weg erodeert en dilatie deze randen terug dikker maakt, worden deze twee bewerkingen vaak na elkaar uitgevoerd. Zo is opening in feite een erosie-operatie gevolgd door een dilatie. Closing is het omgekeerde proces, waarbij er eerst aan dilatie wordt gedaan en vervolgens erosie.Doordat deze bewerkingen bestaan uit 2 aparte primaire bewerkingen, worden opening en closing als secundaire bewerkingen gecategoriseerd.
(a) Opening
(b) Closing
Figuur 2.18: Opening & Closing voorbeelden.
De resultaten van opening en closing zijn te zien op figuur 2.18. De ruis die verkregen is van de segmentatie wordt door deze morfologische operaties uit de beelden gefilterd. Hierdoor wordt ervoor gezorgd dat niet de verkeerde objecten uit een frame getrackt worden, maar enkel de blobs die de voertuigen voorstellen. Hoe deze tracking te werk gaat, wordt in het volgende hoofdstuk besproken.
2.4
Tracking
Het doel is om voertuigen te tellen op basis van camerabeelden. Wanneer er voorgrond / achtergrond segmentatie is toegepast op deze beelden worden er blobs verkregen die elk voor een voertuig staat. Nu is de volgende stap het volgen van eenzelfde voertuig doorheen het beeld. Dit is ook direct de definitie van een tracker. Wanneer een tracker op een correcte manier is opgebouwd, dan weet deze tracker op welke plaatsen de voertuigen zijn geweest en waar ze momenteel ook zijn. Tracking is essentieel in dit systeem, omdat het ervoor zorgt dat de verkregen blobs ( die de voertuigen voorstellen en afkomstig zijn uit de segmentatie ) frame per frame met elkaar in verbinding staan. Op deze manier wordt er dus een relatie ontstaan tussen de verkregen blobs afkomstig van verschillende frames. Deze relatie wordt een track genoemd. Wanneer er geen gebruik wordt gemaakt van een tracking algoritme, dan hebben de blobs uit verschillende frames ook geen relatie met elkaar en kunnen de voertuigen ook niet geteld worden. Allereerst wordt er een woordje uitleg gegeven over verschillende trackers.
2 Literatuurstudie
2.4.1
27
Soorten trackers
Allereerst worden er in dit hoofdstuk de verschillende soorten trackers besproken. Elke soort trac´ van deze ker maakt gebruik van een verschillende input. Er wordt dus een keuze gemaakt uit e´ en verschillende soorten trackers. Eerst wordt er gesproken over de ’model based tracking’, waarna ’feature based tracking’ wordt besproken. Model based tracking Bij deze soort object tracker wordt er gekeken naar het model van het object. Zo wordt er bijvoorbeeld gebruik gemaakt van het active shape model om een model te maken. Dit is een manier om een model te maken door iteratief het model te verkleinen, totdat het het model van het voorwerp heeft gekregen. Dit valt ook te vergelijken met een elastiekje rond een object trekken.
(a) Model van een fles
(b) Lopende band vol flessen
Figuur 2.19: Voorbeeld van Model based tracking.
Deze manier van tracking wordt vooral gebruikt wanneer de modellen steeds dezelfde zijn. Zo wordt dit bijvoorbeeld gebruikt worden voor het tracken van een glazen fles op een lopende band. Deze flessen hebben telkens eenzelfde vorm en zijn dus snel herkenbaar. Ook wanneer deze flessen vanuit een ander perspectief te zien zijn, hebben ze eenzelfde model. Een voorbeeld hiervan is te zien op figuur 2.19. Op figuur 2.19(a) is het model van een fles te zien en figuur 2.19(b) toont een lopende band vol flessen. Wanneer de modellen van de gezochte objecten ongeveer hetzelfde zijn (zoals het tracken van eenzelfde soort product op een productieband) dan is deze methode van tracking een goede manier. Een probleem bij voertuigen is dat deze vele verschillende modellen hebben. Ook wanneer deze voertuigen vanuit een ander perspectief bekeken worden, is het model ook niet hetzelfde. Door deze grootte van variatie op het model, wordt er niet gekozen voor deze manier van tracking. Feature based tracking Een andere manier van tracking is door te kijken naar de regio’s die veranderen op een afbeelding. Hiermee wordt er bedoeld om enkel maar te kijken naar de regio’s waarin veranderingen zijn gebeurt. Zo wordt er dus gekeken naar beweging tussen de verschillende frames, maar ook naar regio’s met eenzelfde kleur. Omdat er voordien al aan voorgrond / achtergrond segmentatie wordt gedaan (dat ook gebruik maakt van veranderingen in de tijd) lijkt deze methode van tracking op het eerste zicht al interessant.
28
2 Literatuurstudie
Figuur 2.20: Voorbeeld van optical flow.
Feature motion trackers, zoals optical flow, maken gebruik van de beweging tussen de frames. Er wordt gekeken naar de gelijke features tussen verschillende frames en zoekt hierbij de beweging gemaakt over deze frames. Hiermee worden motions fields opgemaakt, zoals te zien is op figuur 2.20. Een andere variant zijn de punt trackers. Deze punt trackers maken gebruik ook van feature points, maar hiermee worden geen herkenningspunten bedoel. Hier gaat het meer over berekende punten, zoals het centerpunt van een voorwerp. Een punt tracker die hier een voorbeeld van is, is de Kalman filter. Deze filter is een variant van de punt trackers en heeft als input een punt in een frame nodig. Zo’n punt kan bijvoorbeeld het midden van een voertuig zijn. Als er nu operaties op de binaire beelden - afkomstig van de segmentatie worden uitgevoerd - zodat het midden of het zwaartepunt van elk voertuig gevonden wordt - dan is deze manier van tracking ideaal. Met deze denkwijze wordt er overwogen van een punt tracker te gebruiken, met name de Kalman filter. Deze Kalman filter wordt in deel 2.4.3 uitgebreid besproken, maar eerst worden enkele voorbereidende stappen besproken om tot zulke punten te bekomen.
2.4.2
Voorbereidende stappen
Omdat er voor een punt tracker is gekozen, worden er allereerst enkele voorbereidende stappen gedaan voor deze tracker de juiste input heeft. Als er vertrokken wordt van de voorgrondbeelden van de voorgrond / achtergrond segmentatie, dan is de eerste stap het zoeken naar alle gebieden met voorgrondpixels (blobs).
Zoeken naar contouren Een eerste voorbereidende stap is het zoeken naar alle blobs in een voorgrondbeeld. Het is nodig om dit op een correcte manier te doen. Dit kan bijvoorbeeld door gebruik te maken van de contouren van elke blob.
2 Literatuurstudie
29
Figuur 2.21: Verschil tussen uitwendige en inwendige contours.
De OpenCV-bibliotheek heeft hiervoor een functie genaamd ’findContours’. Deze functie gaat van elke blob de contouren zoeken en opslaan in een vector van punten. Volgens [18] bestaan er 2 soorten contouren in een binair beeld, namelijk een inwendig en een uitwendige contour. Figuur 2.21 laat het verschil tussen deze 2 verschillende contours zien. Hierop zijn B1, B3 en B4 uitwendige contouren en B2 is hier een inwendige contour. De OpenCV-functie findContours wordt zo ingesteld dat enkel maar de buitenste randen worden bijgehouden. De contouren vervolgens bestuderen Een volgende stap is het bestuderen van deze contouren, zodat er bruikbare informatie afkomstig komt. Zo kan bijvoorbeeld het zwaartepunt van elke blob bruikbare informatie zijn. Zo kan het berekenen van dit zwaartepunt gedaan worden, door een gemiddelde te nemen van alle posities van voorgrondpixels voor elke blob
mi j = ∑(array(x, y) · xi · y j )
(2.9)
x,y
Een andere manier zou zijn door gebruik te maken van integralen. Aangezien de contouren van elke blob een vector is van punten, wordt er hiervan een functie gemaakt. Een integraal wordt op zich ook voorgesteld als een lopende som. Omdat er hier 2 parameters zijn - die variabel zijn - is er dus een lopende som nodig, zoals er in formule 2.9 te zien is. Er wordt hier dus een lopende som gemaakt met x en y variabel.
x˜ =
m10 m01 , y˜ = m00 m00
(2.10)
De OpenCV-functie Moments gaat ook op deze manier tewerk. Wanneer de waarden van i en j nul zijn - dus m00 - wordt in formule 2.9 enkel de lopende som genomen van array(x, y). De ´ elementen die er achter komen zijn dan gewoon gelijk aan e´ en. Op deze manier wordt er dus een som genomen van voorgrondpixels binnen die blob en is de oppervlakte tussen de contouren dus gekend. Omdat de oppervlakte nu toch is berekend, zal deze ook worden bijgehouden voor verdere analyse. Om vervolgens het zwaartepunt van de blob te bepalen, wordt dit gedaan zoals in formule 2.10 getoond wordt. Het zwaartepunt van die blob ligt dan in (x, ˜ y) ˜ . Om de x-positiie van het zwaartepunt
30
2 Literatuurstudie
´ hebben. Hierdoor krijgt de x-positie mee zijn belang. te vinden, moet in formule 2.9 de i-waarde e´ en Door het resultaat hiervan te delen door de oppervlakte, wordt de x-positie van het zwaartepunt ´ te geven, is nu de y-positie van berekend. Door vervolgens ook eens de j in formule de waarde e´ en belang zijn. Door ook dit weer te delen door de oppervlakte, is de y-positie van het zwaartepunt bekend. Aan de hand van deze methode is het gelukt om een zwaartepunt te berekenen van elke blob. Doordat er hiervoor de oppervlakte van elke blob is berekend is, wordt deze oppervlakte ook bijgehouden. Deze kan van pas komen om een variabele bounding box te maken. Het zwaartepunt wordt gebruikt om de tracker te initialiseren en bij te sturen. Hoe dit gedaan wordt, wordt in het volgend deel besproken.
2.4.3
De Kalman filter
Zoals al eerder vermeld, is een Kalman filter een van de mogelijkheden om als tracker te gebruiken. Vooraleer er gekozen wordt voor deze filter, wordt er eerst gekeken of deze ook praktisch toepasbaar is.
Wat is een Kalman Filter? Een Kalman filter is een wiskundig model dat reeds voor vele toepassingen wordt gebruikt. Dit wiskundig model zorgt ervoor dat de filter telkens een voorspelling(prediction) kan maken van het volgende punt. Bij de initialisatie van een Kalman filter is het nodig om 4 matrices in te vullen. Dit zijn de status matrix xk die de huidige status weergeeft, een transitiematrix A die de verhouding tussen vorige state en huidige state verzorgt, een noise matrix wk voor de eventuele ruis, die aanwezig is, weg te werken en een measurement matrix zk waarin de waarden van de metingen komen te staan.
Xpredicted = AXn−1
1 xk yk 0 = x˙k 0 y˙k 0
0 ∆dt 0 xk−1 1 0 ∆dt · yk−1 xk−1 ˙ 0 1 0 yk−1 ˙ 0 0 1
(2.11)
(2.12)
De voorspelling van de volgende state wordt gedaan volgens formule 2.11. Hier is A de transitiematrix die gebruikt wordt om de voorspelling te bepalen. Deze transitionmatrix is uitgebreider te zien in formule 2.12. Deze formule toont aan wat bijvoorbeeld het verband tussen xk en xk−1 is.
2 Literatuurstudie
31
Figuur 2.22: Werking van Kalman filter.
Zo is er op figuur 2.22 te zien dat er 3 detecties rond een voertuig zijn afgebeeld. Het zijn in feite de centerpunten van de detecties die worden bijgehouden, maar door kaders worden voorgesteld. De blauwe kader geeft de huidige status aan van het voertuig. Deze waarde wordt zoals eerder vermeld in de state matrix bewaard. De gemeten waarde van hetzelfde voertuig wordt aangetoond door de groene kader, dit is de waarde uit de measurement matrix. De voorspelde waarde, die door de transitiematrix berekend wordt, wordt door de rode kader aangegeven. In [22] is het volledige wiskundige bewijs te zien, waarmee de Kalman gain en de noise berekend worden. De Kalman filter doet dus in principe 2 mogelijke operaties, ofwel wordt er een update gedaan als er een nieuw punt gevonden wordt, ofwel wordt er een voorspelling gedaan als er geen nieuw punt gevonden wordt door de segmentatie. Door telkens weer een detectie te gebruiken als feedback, wordt deze voorspelling stelselmatig nauwkeuriger.
Kalman filter in OpenCV
In de OpenCV bibliotheek is er al een klasse KalmanFilter ge¨ımplementeerd 2 . De informatie van deze klasse is volledig gedocumenteerd op de site. Omdat er telkens 1 Kalman filter is per detectie, gaan er dus meerdere Kalman filters nodig zijn om alle detecties te gaan tracken. Hiervoor is dus ¨ een efficiente manier nodig om al deze Kalman filters bij te houden.
2
http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html
32
2 Literatuurstudie
Figuur 2.23: Structuur van de Kalman klassen.
Omdat er nog meerdere parameters nodig zijn, worden er extra klassen aangemaakt. De extra ´ overkoepelende parameters en de indeling van deze klassen is te zien op figuur 2.23. Er is e´ en klasse KalmanTrackers gemaakt. Deze klasse houdt onder andere bij wat de maximale afstand is tussen trackpunt en de nieuwe detectie, hoeveel keer een track mag blijven bestaan zonder een nieuwe detectie te hebben en een vector van KalmanTracks waarin alle verdere parameters in opgeslagen worden. Deze vector wordt tevens in figuur 2.23 getoond. Deze vector is een vector van de vorm KalmanTrack. In elke KalmanTrack wordt er bijgehouden wat zijn id-nummer is, hoeveel keer deze track al geen detectie meer heeft gehad, de grootte van de blob bij een vorige detectie, het verleden van punten die deze track heeft gehad en een object van de klasse KalmanF. Dit object van de klasse KalmanF wordt onder andere de deltatime bijhouden die voor de transitiematrix van de Kalman filter wordt gebruikt, het laatste bekende punt, een booleaanse waarde of deze track nog geteld moet worden en de effectieve klasse vanuit de OpenCV bibliotheek kalmanFilter.Deze wordt aangetoond door een rode omkadering. Door deze structuur te gebruiken, worden er zo min mogelijke parameters meegegeven bij het initialiseren van een nieuwe Kalman filter.
(a) Binair beeld met een cirkel in het zwaartepunt.
(b) Frame met de Kalman filter op elk voertuig.
Figuur 2.24: Resultaat van de Kalman filter.
2 Literatuurstudie
33
Het resultaat hiervan is dat er een tracking systeem is gemaakt dat de voertuigen doorheen een frame volgt. Op figuur 2.24(b) is te zien dat er voor elk voertuig een tracker is gemaakt. De zwaartepunten die op figuur 2.24(a) te zien zijn, bevatten de informatie die de Kalman filters binnenkrijgen.
2.4.4
Het Hongaars algoritme
Wanneer er meerdere voertuigen in een frame zijn, moeten er dus ook meer Kalman filters tegelijk bestaan. Er zal dan nog een manier nodig zijn om te weten bij welke Kalman track de eventuele nieuwe detectie hoort. Dit zou kunnen door gebruik te maken van de Euclidische afstand. Door de afstand te berekenen tussen de detectie en het laatste punt van de track, zal de kleinste afstand tussen beide punten de correspondentie aantonen. Natuurlijk kan het zijn dat er tijdelijk geen detectie is. Door een maximumafstand vast te leggen, zal als de minimumafstand groter is dan deze maximumwaarde, er geen correspondentie zijn tussen track en detectie. Indien er geen correspondentie is voor een track, zal er gebruik gemaakt worden van de voorspelling van de Kalman filter.
Figuur 2.25: Assignment probleem met Euclidische afstand.
De minimale Euclidische afstand wordt niet gekozen om correspondenties te vinden, omdat er een mogelijkheid bestaat dat het niet altijd de kleinste afstand is die de beste correspondentie heeft. Een voorbeeld hiervan wordt aangetoond op figuur 2.25. Op deze figuur valt er te zien dat er voor track 2 ook 2 mogelijke kandidaten detecties zijn. Indien er gekozen wordt om voor de kortste afstand te kiezen, dan zal er een slechte overeenkomst zijn voor track 1. Deze zal dan detectie 1 als corresponderende krijgen, wat niet de meest ideale is. Om dus goede correspondenties te vinden, moet er dus een meer uitgebreide methode zijn die deze Euclidische afstand kan bestuderen. Een van zo´n uitgebreide methode is het Hongaars algoritme[4]. Dit Hongaars algoritme bestaat tegenwoordig al uit meerdere varianten, maar het principe erachter blijft steeds dezelfde. Zo zal er altijd gezocht worden naar de minimale kost bij de toewijzing van, in dit geval, detecties aan de reeds bestaande tracks.
34
2 Literatuurstudie
(a) Gegeven.
(b) Stap 1.
(c) Vervolg stap 1.
(d) Stap 2: De nullen bedekken.
(e) Stap 2: vervolg.
(f) Resultaat van toewijzing.
Figuur 2.26: De verschillende stappen van het Hongaars algoritme.
Om te beginnen wordt er een kostenmatrix opgemaakt. Deze kostenmatrix wordt opgemaakt door de Euclidische afstand te berekenen tussen elke detectie en het laatste gekende punt van een track. Zo toont figuur 2.26(a) een mogelijke kostenmatrix aan. ´ nul komt De eerste stap van het Hongaars algoritme zorgt ervoor dat er in elke rij minstens e´ en te staan. Dit wordt gedaan, door van elke rij het kleinste getal af te trekken. Het resultaat hiervan wordt op figuur 2.26(b) aangegeven. Vervolgens, indien er nog geen toewijzing mogelijk is, wordt
2 Literatuurstudie
35
deze stap nogmaals herhaald maar dan voor de kolommen. Zo is te zien op figuur 2.26(c) dat de kolommen waarin al een 0 stond niet veranderd zijn en dat de kolom van track 1 met waarde 6 is verminderd. Stap 2 van het Hongaars algoritme blijft uitgevoerd worden tot er uiteindelijk een toewijzing mogelijk is. Deze stap begint door alle rijen en kolommen, waarin nullen voorkomen, met zo min mogelijk lijnen te bedekken. Zo is er te zien op figuur 2.26(d) dat er hier 3 lijnen nodig zijn om alle nullen te bedekken. Als dit gedaan is, wordt er gezocht naar het kleinste niet bedekte getal. Dit getal, wat hier een 2 is, wordt dan van alle niet bedekte getallen afgetrokken. Ook wordt dit getal opgeteld bij de dubbel bedekte getallen. Op figuur 2.26(e) worden deze dubbel bedekte getallen aangegeven met een rode achtergrond. In dit geval is er een toewijzing mogelijk zoals er op figuur 2.26(f) wordt gegeven. Indien dit niet het geval is, wordt stap 2 uitgevoerd tot er wel een toewijzing mogelijk is. Dit voorbeeld is gedaan met een NxN matrix gedaan, maar er kunnen altijd meer detecties dan tracks zijn of omgekeerd. In deze gevallen krijgen er ook enkele toewijzingen de waarde -1. Deze waarde wil zeggen dat er geen toewijzing gedaan is voor deze track / detectie. In het systeem wordt er gebruik gemaakt van een Kalman filter om de voertuigen doorheen het frame te kunnen volgen. Het binaire beeld dat afkomstig is van de segmentatie wordt door de OpenCV-functies ’findContours’ en ’moments’ bestudeerd worden, zodat de Kalman filters ge¨ınitialiseerd worden. De toewijzing van detecties aan de Kalman filters wordt met het Hongaars algoritme gedaan.
2.5
Voertuigdetectie
Een mogelijke uitbreiding van het systeem is door gebruik te maken van een voertuigdetector. Wanneer een track, dat afkomstig is van deel 2.4.3, ook nog eens bevestigd wordt dat het een voertuig is, zal de betrouwbaarheid van het systeem hierdoor hoger liggen. Een voertuigdetector gaat aan de hand van een getraind model frame per frame zoeken naar correspondenties. In dit geval zijn deze correspondenties voertuigen. Dit getraind model moet wel eerst worden opgemaakt voor het kan worden gebruikt. In volgend deel wordt er een veelgebruikte voertuigdetector besproken, met name een model getraind met HAAR-wavelets via een cascade classifier techniek.
2.5.1
Haar cascade classifier
De haar cascade classifier is ontwikkeld door het duo Viola-Jones en is het eerste algoritme dat real-time aan gezichtsdetectie kon doen [21]. In dit deel wordt onder andere haar features, adaBoost en vervolgens over de cascadewerking besproken.
36
2 Literatuurstudie
Haar features Volgens [21] zijn er verschillende redenen om met features te werken in plaats van met pixelwaarde. Een van deze redenen is omdat gebruik makend van features, het systeem sneller zijn werk doet.
(a) 2-rechthoekige features.
(b) 3-rechthoekige features.
(c) 4-rechthoekige features.
Figuur 2.27: De verschillende stappen van het Hongaars algoritme.
Het principe achter haar features wordt aangetoond aan de hand van figuur 2.27. Zo is er te zien dat er zowel witte als zwarte rechthoeken zijn. Het zit zo dat deze features over een beeld worden verschoven en zo wordt telkens de som van pixels uit het witte gedeelte van de som van pixels uit het zwarte gedeelte afgetrokken. Dit valt te zien op figuur 2.27 waarop er 3 verschillende soorten haar features te zien zijn:
• Ten eerste zijn er de 2 rechthoekige features. Deze features detecteren randen in een beeld. Een voorbeeld hiervan is te zien op 2.27(a).
• Vervolgens zijn er de 3 rechthoekige features. Deze features detecteren lijnen in een beeld. Deze lijn features zijn te zien op figuur 2.27(b).
• Uiteindelijk zijn er ook de 4 rechthoekige features. Deze detecteren diagonale lijnen in een beeld. Dit feature is te zien op figuur 2.27(c).
Figuur 2.28: Een voorbeeld van een integral image.
Door gebruik te maken van deze haar features, wordt het mogelijk om randen en lijnen te detecteren. Een manier om ook nog eens snel deze features te berekenen, is door gebruik te maken van een integral image. Een voorbeeld van zo’n integral image is te zien op figuur 2.28. Op deze figuur is een regio D te zien. Bij een integral image gaat het erom dat op een bepaalde positie de
2 Literatuurstudie
37
waarde van al de bovenstaande en links liggende pixels wordt bijgehouden. Als dan deze D voor elk rechthoekig feature staat, dan is deze eenvoudig te berekenen door:
D = ii(4) + ii(1) − ii(2) − ii(3)
(2.13)
Op deze manier is het dus mogelijk om de rechthoekige haar features op een snelle manier te berekenen.
AdaBoost training Om een classifier werkende te krijgen, moet er een trainingsmodel worden opgebouwd. Zo´n trainingsmodel zal worden opgebouwd uit een reeks positieve samples en een reeks negatieve ¨ samples. De bedoeling hiervan is om een algemeen model van een voertuig te creeren. AdaBoost wordt hierbij gebruikt om de performantie van een simpele classifier te verbeteren. Het principe achter AdaBoost is door een combinatie van zwakke classificatie functies te gebruiken die een uiteindelijk sterke classifier vormen. Wanneer er dan een trainingsmodel is opgebouwd door middel van AdaBoost, wordt het nadien gebruikt voor detectie. Om de detectie ook van een complex algoritme te behouden, wordt er gebruik gemaakt van een cascade van classifiers. Wat deze cascade juist is en waarom het wordt gebruikt, wordt in het volgende deel besproken.
Hoe werkt een Cascade classifier? Nu er eenmaal een trainingsmodel is opgebouwd, kan de detectie gedaan worden. Omdat er op een beeld meer delen zijn die niet gedetecteerd worden dan voertuigen komt de snelheid van het systeem onder drang, indien alles volledig wordt vergeleken met het trainingsmodel. Een andere manier is om de detector op te splitsen in een cascade van classifiers.
Figuur 2.29: Werking van cascade classifiers.
Deze cascade van classifiers, dat afgebeeld wordt op figuur 2.29 zorgt ervoor dat het systeem meer performant is fan dat er geen cascade wordt gebruikt. Wanneer een beeld overlopen wordt, ontstaan er subwindows. Deze subwindows worden dan als input gebruikt voor de cascade classifier. Zo gaat er bij elke stage gekeken worden - door middel van haar features - of het subwindow overeenkomt met het gezochte object. In dit geval is dit object een voertuig. Indien er een overeenkomst is, gaat het subwindow verder naar een volgende stage. Wanneer alle stages gepasseerd
38
2 Literatuurstudie
zijn door eenzelfde subwindow, wordt er vanuit gegaan dat binnenin dit subwindow er zich een voertuig bevindt. Indien er een stage geen overeenkomst heeft, wordt het subwindow verworpen en kan er verder gezocht worden met andere subwindows. In de meeste gevallen worden er bij de eerste stage al een grote hoeveelheid subwindows verworpen. Hierdoor worden de volgende stages niet gebruikt en gaat er ook geen kostbare tijd verloren gaan. Door een combinatie van haar features, AdaBoost en een cascade van classifiers te gebruiken, hebben Viola en Jones een manier gevonden om real-time aan object detectie te doen. In de OpenCV bibliotheek is er ook een haar cascade classifier ge¨ımplementeerd. Deze wordt gebruikt om een extra controle te doen om voertuigen te tellen.
Hoofdstuk 3
Verwerking van de data Met de literatuurstudie in het achterhoofd kan er begonnen worden aan het ontwikkelen van het systeem. Een eerste analyse dat besproken werd, was het voorbereiden van de data - die afkomstig is van de camera - om er nadien voorgrond / achtergrond segmentatie op toe te passen. Zo bespreekt hoofdstuk 3.1 het bepalen van de specifieke regio(region of interest) waarop de analyse van het systeem gedaan wordt. Hoofdstuk 3.2 bespreekt de gebruikte manier om ruis uit een beeld te filteren. Nadien bespreekt hoofdstuk 3.3 welke methode er gekozen wordt om voorgrond / achtergrond segmentatie te doen. Omdat er door deze segmentatie ook ruis ontstaat, bespreekt hoofdstuk 3.4 de gebruikte operaties om deze ruis tegen te werken.
3.1
Region of interest
Een eerste algoritme dat gemaakt wordt, is voor het beperken van een frame, zodat enkel dat gebied van belang is. Dit gebied wordt ook wel een region of interest (ROI) genoemd. Deze region of interest maakt het mogelijk om maar de toekomende voertuigen te bestuderen. Omdat elk kruispunt een andere vorm heeft, is het nodig om per kruispunt een andere vorm te maken. Hiervoor wordt er gekozen om dit manueel aan te pakken. Wanneer de camera op de juiste positie wordt geplaatst, kan dan nadien deze region of interest worden opgemaakt.
Figuur 3.1: Aangeklikte punten om een region of interest te maken.
´ manier gekozen om deze te bepalen en te Om een region of interest op te maken, wordt er e´ en 39
40
3 Verwerking van de data
gaan gebruiken. Zo wordt er gebruik gemaakt van een masker waarover elk frame wordt gehouden. Zo’n masker bestaat uit 2 verschillende waarden. In dit masker gaan alle pixels met de waarde 255(wit) deel uitmaken van de region of interest en alle pixels met waarde nul niet. De reden waarom hier gewerkt wordt met een 8bit beeld in plaats van een binair beeld, wordt later nader verklaard. Om zo’n masker aan te maken, worden de gebieden - die een waarde krijgen van 255 eerst opgemaakt. De manier die hiervoor wordt gekozen, is door het aanklikken van punten op een beeld. Deze punten zijn dan de grenspunten van deze region of interest. Om deze punten aan te klikken, is er een functie geschreven om tijdens de initialisatie van het systeem te gebruiken. Om ervoor te zorgen dat het aanklikken van deze punten op een overzichtelijke manier gedaan wordt, wordt dit slechts gedaan op een enkel frame. Hiermee wordt bedoeld dat het eerste binnenkomend frame gebruikt wordt om deze punten op aan te klikken. Het wordt dus niet in feite op een videostroom toegepast. Tevens is er de mogelijkheid gemaakt om het hele frame als region of interest te kiezen. Zo wordt bij het aanklikken van nul punten het hele frame als region of interest gebruikt. Van zodra ´ punt is aangeklikt, is het de bedoeling om minstens vier punten aan te klikken. er minstens e´ en De reden hiervan is, dat wanneer er minder dan vier punten worden aangeklikt, dat er nooit een degelijke region of interest gevormd wordt. De programmacode voor het bepalen van deze region of interest is toegevoegd als bijlage. Deze bevindt zich in bijlage A.1
(a)
(b)
Figuur 3.2: Region of interest masker en toegepast op een frame.
De aangeklikte punten, die op figuur 3.1 met blauwe cirkels worden aangetoond, worden bijgehouden in een vector van punten. De bedoeling is om van deze vector van punten een polygoon te maken. Zo’n polygoon is een gesloten stelsel lijnsegmenten dat samen een plat vlak omsluiten. ¨ Hiermee worden er vlakken gecreeerd die verschillend zijn van een standaard figuur. Wanneer alle punten zijn aangeklikt, wordt deze polygoon vervolgens aangemaakt. De OpenCV bibliotheek bevat een functie genaamd ’approxPolyDP’ die - van deze vector van punten - een polygoon maakt. Deze functie resulteert in een andere vector van punten waarin alle punten van de contour van deze polygoon wordt bijgehouden. Om van deze contour een masker te maken, wordt er gebruik gemaakt van een andere functie uit de OpenCV bibliotheek. Deze functie genaamd ’fillConvexPoly’ geeft een gevuld vlak terug als resultaat. De waarden van pixels die binnenin dit vlak behoren, zijn gelijk aan 255. ´ is omdat er De reden waarom er hier voor de waarde 255 gekozen wordt en niet de waarde e´ en, nadien enkel maar een bitsgewijze AND nodig is om op het frame een region of interest te bepalen.
3 Verwerking van de data
41
Zo is figuur 3.2(b) het resultaat van een bitsgewijze AND operatie tussen een grijswaarde-beeld en figuur 3.2(a). Wanneer er voor een binair beeld gekozen wordt, is het nodig om een test uit te voeren welke waarde die bepaalde pixel heeft. Door het kiezen van een 8-bit beeld in plaats van een binair beeld is er meer geheugen nodig, maar werkt het algoritme hierdoor sneller.
Figuur 3.3: Verkleind venster met region of interest.
Het resultaat hiervan is dat er een region of interest is opgemaakt. Op deze region of interest kan vervolgens analyse op toegepast worden. Het bepalen van deze region of interest heeft nog niet gezorgd dat het frame hierdoor kleiner van formaat is geworden. De regio buiten de region of interest bestaat nu enkel maar uit zwarte pixels. Het is overbodig werk om deze pixels ook te analyseren. Voor het systeem is het bevorderlijk om de grootte van het frame te verkleinen. Deze verkleining wordt gedaan door de zwarte randen te verwijderen. Er wordt gekozen om het frame te verkleinen aan de hand van de aangeklikte punten. Hiervoor is er zelf een functie ’zoekKleinsteVenster’ geschreven, die de uiterste x en y waarde gaat zoeken. Zo wordt er in deze functie gezocht naar de kleinste/ grootste x en y waarde die de aangeklikte punten hebben. Indien deze uiterste waarden gekend zijn, wordt het gebied tussen deze waarden uitgeknipt. Op deze manier ontstaat er - zoals op figuur 3.3 getoond wordt - een rechthoek waarbinnen de volledige region of interest zich bevindt. Deze figuur is het resultaat van het verkleinen van figuur 3.2(b). Door het uitsnijden van elk frame tot op deze grootte, werkt het algoritme hierdoor ¨ efficienter dan wanneer het volledige frame geanalyseerd wordt. Zo is er een algoritme ontwikkeld waarmee de region of interest bepaald wordt. Hiermee wordt er gezorgd dat er enkel maar naar de toekomende voertuigen gekeken wordt en waardoor de overige voertuigen buiten beschouwing worden gebracht. Er is tevens een ander algoritme ontwikkeld, dat elk frame verkleind tot de uiterste punten van deze region of interest. Aan de hand van dit kleiner frame werkt het systeem sneller, zodat de doelstelling om het volledig real-time te maken behouden wordt. Eenmaal dit is gebeurt, wordt er een einde gemaakt aan de initialisatie van het systeem en worden verdere bewerkingen gedaan op een videostroom.
3.2
Ruis uit een beeld halen
Een beeld dat afkomstig is van een camera, is eventueel onderhevig aan ruis. In hoofdstuk 2.1 wordt er reeds gesproken over de verschillende vormen van ruis en ook over de mogelijke oplossingen tegen deze ruis. Deze twee opgenoemde oplossingen zijn het Gaussisch vervagen(Gaussian blur) of de mediaanfilter. In de meeste gevallen zijn de beelden vrij zijn van ruis, maar door externe storingen is het altijd mogelijk dat er ruis in een beeld komt. Om ervoor te zorgen dat het systeem
42
3 Verwerking van de data
ook correct werkt wanneer de beelden onderhevig zijn aan ruis, wordt er standaard aan ruisfiltering ´ van deze reeds opgenoemde oplossingen. gedaan. Zo wordt er gebruik gemaakt van e´ en Wanneer de beelden onderhevig zijn aan ruis, zorgt dat voor mindere resultaten. Daarom wordt deze ruis liefst ten allen tijde vermeden. Een eerste reeds besproken manier is het Gaussiaans vervagen. In de OpenCV bibliotheek is er een functie ’GaussianBlur’ ge¨ımplementeerd dat het Gaussiaans vervagen toe past op een beeld. Doordat het Gaussiaans vervagen een gewogen gemiddelde neemt van omliggende pixels, worden hierdoor de ruiswaarden gefilterd. Er wordt hier gekozen om een structuurelement met grootte van zeven op zeven te werken. Met deze grootte is de ruisonderdrukking naar behoren en verliest het frame niet al te veel details. Een tweede reeds besproken methode is de mediaanfilter. Deze methode - om ruis te onderdrukken - wordt veel gebruikt om salt’n pepper ruis weg te filteren. Deze methode berekend telkens de mediaan tussen omliggende pixelwaarden, zodat uitschieters als salt’n pepper ruis volledig uit het beeld gefilterd worden. Het enige probleem van deze methode, is dat er telkens een sorteeralgoritme wordt gebruikt. De pixelwaarden worden gesorteerd op grootte om hieruit de mediaan te halen. Zo’n sorteeralgoritme doet het systeem vertragen naar gelang de grootte van het structuurelement.
Figuur 3.4: Grafiek verschil in rekentijd Gaussiaans vervagen en mediaanfilter.
Om het verschil aan te tonen tussen beide algoritmes, wordt dit gedaan aan de hand van de grafiek op figuur 3.4. Deze grafiek toont het verschil aan tussen het Gaussiaans vervagen en de mediaanfilter op vlak van de benodigde rekentijd. Deze resultaten zijn gemiddelde waarden van de tijd die elk algoritme nodig had over 1000 frames. Zo valt er te zien dat er een enorm tijdsverschil is wanneer het structuurelement groter wordt dan drie. Wanneer er gebruik wordt gemaakt van de mediaanfilter, wordt de doelstelling om het real-time te houden moeilijker gemaakt. Omdat in de meeste gevallen de beelden ruisvrij zijn en deze ruis slechts voorkomt bij interne /
3 Verwerking van de data
43
externe storingen, wordt er gekozen voor het Gaussiaans vervagen om aan ruisfiltering te doen. Nu eenmaal de eventuele ruis uit het beeld is gehaald, wordt er een voorgrond / achtergrond segmentatie op deze beelden uitgeoefend, zodat de voertuigen uit de achtergrond herkend worden.
3.3
Implementeren van een voorgrond / achtergrond algoritme
Met een ruisvrij en kleiner beeld is de volgende stap om de voorgrond van de achtergrond te segmenteren. Om de plaatsen van de voertuigen in een frame te weten te komen, wordt er gebruik gemaakt van de beweging die deze voertuigen over de frames maken. Er wordt dus vervolgens een algoritme geschreven dat deze beweging over de frames detecteert en deze beweging gebruikt om een voorgrondbeeld van te maken. Zo wordt er in de literatuurstudie gesproken over vier verschillende methodes om aan voorgrond / achtergrond segmentatie te doen. Deze vier methodes maken allemaal gebruik van een achtergrondmodel. Zo’n model wordt opgebouwd aan de hand van de vorige frames. Eenmaal er een achtergrondmodel is opgemaakt, kan het huidige frame hiermee vergeleken worden, wat resulteert in een voorgrond beeld. Elk nieuw frame wordt tevens gebruikt om het achtergrondmodel bij te werken, zodat dit achtergrondmodel steeds actueel blijft. De reeds beschreven voorgrond / achtergrond segmentatie methodes zijn frame differencing (FD), running average (RA), approximated mediaan (AM) en de mixture of Gaussians (MOG). Zo gaat er ´ van deze methodes gebruikt worden in het systeem om de segmentatie toe te passen. slechts e´ en
Figuur 3.5: Grafiek verschil in rekentijd voor de verschillende segmentatie algoritmes.
Een eerste punt waarmee vergeleken wordt, is de uitvoertijd van elk algoritme. De doelstelling is om het systeem real-time te laten werken. Als er vanuit wordt gegaan dat de beelden van de camera een data-output heeft van 30 FPS, betekend dit dat het systeem er niet langer over mag
44
3 Verwerking van de data
doen dan 30 ms per frame. Wanneer deze 30 ms niet worden gehaald, werkt het systeem niet real-time op 30 FPS. Zo toont figuur 3.5 de rekentijden aan - dat elke methode nodig heeft bij een verschillende framegrootte - om voorgrond / achtergrond segmentatie toe te passen. De resultaten van deze grafiek worden opgesteld als gemiddelde waarden over 500 frames. Omdat de region of interest een verschillende grootte kan hebben en dus het te bestuderen frame ook verschillend kan zijn van grootte, wordt er over verschillende groottes van frames getest. Wat er uit deze grafiek wordt geconcludeerd, is dat elk algoritme een relatief lage uitvoertijd heeft. Ook valt er te zien dat frame differencing een extreem lage uitvoertijd heeft ten opzichte van de approximated mediaan of mixture of Gaussians. Op basis van deze resultaten worden er nog geen directe conclusies getrokken. Er wordt immers eerst nog naar de resultaten van de 4 verschillende methodes gekeken.
3 Verwerking van de data
45
(a) Frame differencing
(b) Frame differencing met threshold = 10
(c) Running average
(d) Running average met threshold = 30
(e) Approximated mediaan
(f) Approximated mediaan met threshold = 30
(g) Mixture of Gaussians
(h) Mixture of Gaussians met threshold = 130
Figuur 3.6: Voorgrond beelden van voertuigen met de verschillende methodes.
46
3 Verwerking van de data
Om een keuze te maken tussen de 4 verschillende methodes, wordt dit gedaan door de voorgrondbeelden te bestuderen. Zo vertoont figuur 3.6 voor elke methode een resulterend beeld van voorgrond / achtergrond segmentatie. De beelden uit de linker kolom zijn de resultaten waar nog geen threshold op toegepast is en de rechterkolom bevat beelden met voor elke methode ook een apart bepaalde thresholdwaarde. Zo valt er in de linker kolom te zien dat bij frame differencing, running average en approximated mediaan deze beelden nogal vaag zijn. Dat komt omdat deze beelden het resultaat zijn van een aftrekking tussen het frame en de gemaakte achtergrond. Bij mixture of Gaussians daarentegen zijn er hier drie verschillende pixelwaardes te zien, namelijk nul(zwart), 108(grijs) en 255(wit). Zo behoren de zwarte pixels bij de achtergrond, de witte pixels bij de voorgrond en de grijze pixels staan voor schaduwgebied van elk voertuig. Door bij de mixture of Gaussians de parameter ’fTau’ aan te passen, wordt het gebied van schaduw (grijze pixels) kleiner of groter. De variabele ’fTau’ wordt hierbij op een waarde 0,5 gezet. Dit wilt zeggen dat, als een pixel meer dan 2 keer donkerder is, deze niet gezien wordt als schaduw [14]. De resultaten die te zien zijn in de rechter kolom, zijn de beelden uit de linker kolom waarop een threshold op toegepast is. Elke methode heeft hierbij een verschillende thresholdwaarde. Zo is de thresholdwaarde van frame differencing, running average en approximated mediaan aan de lage kant, omdat het resultaat van een aftrekking ook altijd een lage waarde geeft. Bij de mixture of Gaussians ligt deze thresholdwaarde dan weer hoger, zodat het schaduwgebied mee als achtergrond wordt gezien. Door nu naar de verkregen blobs te kijken, is die van de mixture of Gaussians het meest volledig. De blobs van frame differencing bevatten vele onzuiverheden en zijn langer dan het voertuig werkelijk is. Dit komt door het gaan vergelijken van het huidige frame met x frames terug. Wanneer het voertuig rijdt, is de beweging van het voertuig groter over x frames en wordt de blob dus langer. Door deze vele onzuiverheden in elke blob wordt het moeilijk om de volledige blob van een voertuig te bepalen. Door deze onzuiverheden, maakt dat frame differencing niet geschikt is - ondanks de snelle rekentijd - om te gebruiken in dit systeem. Bij running average en approximated mediaan zijn er 2 blobs in de buurt van elk voertuig, omdat de schaduw hier voor een extra blob zorgt, komen er meer fouten in het systeem. Aangezien de mixture of Gaussians een schaduwdetectie heeft, is er voor elk voertuig slechts 1 blob aanwezig. Ondanks de mixture of Gaussians meer uitvoertijd nodig heeft, wordt er toch gekozen voor deze methode. Deze methode bevat meerdere optimalisaties en parameters, zodat het algoritme naar eigen systeem kan worden aangepast, waardoor de resultaten hierdoor beter zijn. Om ervoor te zorgen dat het achtergrondmodel eerst correct wordt opgebouwd, worden de eerste 200 frames niet gebruikt voor verdere analyse. Met nu een voorgrond / achtergrond segmentatie methode gekozen te hebben, worden de plaatsen van voertuigen herkend in een frame. Het enige probleem dat wel eens voordoet, is dat er ruis is ontstaan door de segmentatie. Vooraleer er verder geanalyseerd wordt op dit beeld, worden er eerst enkele morfologische operaties hierop toegepast, zodat deze ruis uit het voorgrondbeeld gefilterd wordt.
3.4
Morphologische operaties implementeren
Door de voorgrond / achtergrond segmentatie kunnen er individuele witte pixels ontstaan. Deze ruis ontstaat door gebruik te maken van een threshold. Zo kan het zijn dat bepaalde pixelwaarden
3 Verwerking van de data
47
net boven die thresholdwaarde komen, zodat ze mee als voorgrond gesegmenteerd worden. Om verdere analyse op dit voorgrondbeeld toe te passen, wordt deze ruis eerst verwijderd met behulp van morfologische operaties.
(a) Resultaat mixture of Gaussians
(b) Erosie met grootte 3x3
Figuur 3.7: Erosie toegepast op een voorgrond beeld.
Zoals te zien is op figuur 3.7(a) bevat deze figuur redelijk wat ruis. Deze ruis be¨ınvloed het volledige systeem en is dus nodig om deze eerst te verwijderen. In de literatuurstudie wordt er gesproken over erosie en dilatie die de ruis uit het voorgrondbeeld verwijderen. Een eerste stap is het verwijderen van de individuele witte pixels. Deze individuele pixels worden eenvoudig verwijderd aan de hand van erosie. De functie erosie is reeds in de OpenCV bibliotheek aanwezig en wordt in dit algoritme gebruikt. De erosie wordt gedaan met een vierkant als structuurelement en de grootte hiervan wordt experimenteel bepaald. ¨ Zo wordt er bij een structuurelement van grootte 4 op 4 pixels al teveel weggeerodeerd van de voertuigen. Bij een grootte van 2 op 2 pixels gaan er nog teveel witte individuele pixels aanwezig blijven. Wanneer de grootte van het structuurelement 3 op 3 is, zijn er geen witte individuele pixels ¨ meer aanwezig en worden de voertuigen ook niet al te veel weggeerodeerd. Deze grootte van structuurelement wordt voor erosie gekozen. Het resultaat van deze operatie wordt getoond op figuur 3.7(b).
(a) Resultaat na erosie
(b) Dilatie met grootte 5x5
¨ Figuur 3.8: Dilatie toegepast op het geerodeerde beeld.
¨ Omdat momenteel teveel pixels van de blobs van de voertuigen zijn weggeerodeerd, wordt er
48
3 Verwerking van de data
vervolgens de omgekeerde operatie gedaan, namelijk dilatie. Deze operatie zorgt ervoor dat de ¨ voertuigen - waarvan enkele pixels zijn weggeerodeerd - terug hun volledige vorm krijgen. Ook de operatie dilatie is als functie aanwezig in de OpenCV bibliotheek en wordt hiervoor gebruikt. Ook hier wordt er weer gekozen voor een vierkant als structuurelement. De grootte van dit structuurelement wordt tevens experimenteel bepaald. Om ervoor te zorgen dat de blobs terug groot genoeg worden, gaat de grootte van dit structuurelement minstens zo groot zijn als die bij erosie. Zo worden de beste resultaten verkregen al het structuurelement een grootte heeft van 5 op 5 pixels. De volgorde van deze twee operaties wordt ook wel opening genoemd. Indien er eerst wordt gekozen voor dilatie en vervolgens voor erosie, wordt dit closing genoemd. Closing is in dit geval niet ideaal, omdat dan de individuele witte pixels groter in het beeld gaan worden. Nu deze ruis uit het beeld is verwijderd, kunnen deze beelden verder worden geanalyseerd. Zo gaat de eerste stap het analyseren van de verkregen blobs zijn, zodat er een tracker ge¨ınitialiseerd kan worden. Hoe dit gedaan wordt, wordt in het volgende hoofdstuk besproken. In dit hoofdstuk is een eerste deel van het systeem ge¨ımplementeerd. Zo worden de beelden - die afkomstig zijn van de camera - eerst verkleind zodat enkel de rijvakken die van belang zijn, worden bestudeerd. Nadien worden deze beelden van eventuele ruis gefilterd, waarna er voorgrond / achtergrond segmentatie op toegepast wordt. Deze ruisfiltering wordt gedaan aan de hand van het Gaussiaans vervagen. De voorgrond / achtergrond segmentatie wordt gedaan met behulp van de mixture of Gaussians. Om de ruis - die afkomstig komt van de segmentatie - weg te filteren, wordt er gebruik gemaakt van erosie en dilatie. Het resultaat na deze operaties is dat er een voorgrond beeld is ontstaan waarop de voertuigen als voorgrond worden gezien en de rest als achtergrond. Door deze voorgrond / achtergrond segmentatie toe te passen, is het mogelijk om sneller de voertuigen te detecteren in een frame dan dat er gebruikt wordt gemaakt van voertuigdetectie op het volledige frame.
Hoofdstuk 4
Het volgen van voertuigen doorheen de frames Om voertuigen te tellen, is het nodig om deze doorheen het frame te volgen. Indien dit niet gedaan wordt, wordt er ook geen relatie tussen de verschillende blobs uit verschillende frames opgebouwd. Zonder een relatie tussen deze verschillende blobs is het tellen ook niet mogelijk. Om ervoor te zorgen dat de voertuigen wel degelijk gevolgd worden doorheen het frame, wordt er gebruik gemaakt van een tracker. Zo bespreekt hoofdstuk 4.1 de implementatie van de Kalman filter. Vervolgens bespreekt hoofdstuk 4.2 de gebruikte manier waarmee geteld wordt. Uiteindelijk bespreekt hoofdstuk 4.3 een voertuigdetector die als uitbreiding wordt gebruikt.
4.1
Implementatie van de Kalman filter
Om voertuigen doorheen het frame te volgen, is er een algoritme nodig die alle data in verband met deze voertuigen bijhoudt. In de literatuurstudie wordt er reeds gesproken dat er gekozen wordt voor de Kalman filter. Deze Kalman filter is de meest optimale keuze die gedaan kan worden, omdat deze ook voorspellingen doet wanneer er tijdelijk geen detecties meer zijn. Omdat er meerdere voertuigen aanwezig kunnen zijn in een frame, zijn hiervoor meerdere Kalman filters nodig om al deze voertuigen te volgen. Hoe deze Kalman filter wordt gebruikt, wordt in dit deel besproken. Aangezien de Kalman filter een punt tracker is, is het ook nodig om een punt te hebben om zo’n Kalman filter te initialiseren. Op deze moment is er een beeld gevormd waarop de voertuigen als voorgrond worden voorgesteld. Deze voorgrond bestaat uit meerdere blobs. Deze blobs representeren de voertuigen in een beeld. Om per voertuig een punt te gaan berekenen, wordt dit gedaan door telkens zijn representatieve blob te bestuderen. In de literatuurstudie wordt er reeds gesproken over het zwaartepunt van elke blob. Dit zwaartepunt wordt dan telkens per blob berekend, zodat een Kalman filter kan worden opgemaakt. 49
50
4 Het volgen van voertuigen doorheen de frames
Figuur 4.1: Structuur van de ge¨ıimplementeerde Kalman klassen.
Voor deze Kalman filters kunnen worden ge¨ınitialiseerd, wordt er eerst voor elke blob het zwaartepunt berekend. Zo wordt er in de literatuurstudie gesproken over de OpenCV functies ’findContours’ en ’moments’. Deze functies worden achtereenvolgens gebruikt voor het bepalen van het zwaartepunt van elke blob.De programmacode waarin deze functies gebruikt worden, is te zien in bijlage B.1. Zo gaat ’findContours’ de contouren van elke blob zoeken en bijhouden, waarna de ’moments’ methode deze data gaat analyseren om dan nadien een zwaartepunt terug te geven. Omdat de ’moments’ methode hiervoor ook de oppervlakte van elke blob berekend, wordt deze ook bijgehouden in een aparte variabele. Deze oppervlakte wordt nadien gebruikt om een dynamische bounding box te maken.
hoogte/breedte =
p oppervlakte + extra
(4.1)
Een bounding box is een rechthoek dat, op een frame, rond het voertuig wordt getrokken. Hiermee wordt aangetoond waar in het frame een voertuig is gedetecteerd. Om een dynamische bounding box te maken, is het nodig om de grootte van het voertuig te weten. Dit wordt gedaan aan de hand van de grootte van de overeenkomstige blob. Omdat er wordt gekozen dat de bounding box een vierkant is, wordt de grootte van deze bounding box bepaald door formule 4.1. De variabele extra wordt gebruikt, zodat de bounding box telkens iets groter is dan de blob. Deze variabele ’extra’ wordt op 30 pixels gezet, zodat er 30 pixels marge is op de hoogte en breedte. Deze 30 pixels is manueel bepaald, zodat de voertuigen het best omsloten worden.
Linkerbovenhoek = Point(zwaartepunt.x −
size size , zwaartepunt.y − ); 2 2
(4.2)
Om deze bounding box vervolgens te tekenen, wordt er gebruik gemaakt van het zwaartepunt. Dit punt ligt in de meeste gevallen ongeveer in het midden van elke blob. Omdat een rechthoek meestal getrokken wordt vanuit de linkerbovenhoek, is het nodig om dit punt eerst te bepalen. Zo berekend
4 Het volgen van voertuigen doorheen de frames
51
formule 4.2 de positie van de linkerbovenhoek. Van hier uit wordt er vervolgens een bounding box getrokken met de gekende groottes. Het is echter mogelijk dat zowel de linkerbovenhoek als de bounding box buiten het frame komen. Om dit op te lossen, wordt er hierop getest en bijgestuurd zodat de bounding box altijd op het frame past. Nu eenmaal de zwaartepunten gekend zijn, kunnen de Kalman filters aangemaakt en gebruikt worden. De structuur waarin alle verschillende variabelen bij elkaar horen, wordt getoond op figuur . Zo is er een overkoepelende klassen KalmanTrackers waarin een vector zit van KalmanTrack. Zo wordt er voor elk voertuig een aparte KalmanTrack aangemaakt en wordt deze op de vector gezet. Buiten de trackid, de oppervlakte en het aantal overgeslagen beelden houdt deze klasse ook nog een variabele van andere klasse bij, namelijk KalmanF. Deze klasse bevat onder andere het laatst bekende punt, een variabele deltaTime die gebruikt wordt in de transitiematrix van de Kalman filter, een variabele die bijhoudt of deze track al geteld is en ook de OpenCV klasse KalmanFilter. De variabele ’deltaTime’ in de overkoepelende klasse KalmanTrackers wordt experimenteel bepaald. Deze variabele wordt gebruikt bij de transitiematrix van de Kalman filter en wordt gebruikt als snelheid bij het berekenen van de voorspelling. (Zie bijlage B.2) Deze deltaTime wordt laag gekozen, zodat het voorspelde punt ook dicht bij het vorige punt ligt. De variabele ’distThres’ geeft aan wat de maximale afstand tussen track en detectie mag zijn. Zo is er berekend dat een rijvak gemiddeld 100 pixels breed is. Hierdoor wordt er gekozen om deze variabele op 60 te zetten, zodat detecties vanuit het ene rijvak niet gekoppeld kunnen worden aan deze van het andere rijvak. De variabele maxSkippedFrames - die aangeeft hoeveel frames een tracker zonder detectie mag blijven bestaan - wordt op 1 seconde of ook wel 30 frames gezet. Als laatste wordt de variabele maxTraceLength gebruikt om te bepalen hoe lang de detecties moeten worden bijgehouden. In dit geval wordt er gekozen om er maximum 20 bij te houden. Op deze manier is een tracker gemaakt op basis van de Kalman filter. Het enige probleem dat dit algoritme nog heeft, is het zoeken van correspondenties tussen detecties en tracks. Een voorgestelde methode is door middel van het Hongaars algoritme. Zo is er reeds een implementatie van dit Hongaars algoritme in C++[16], welke gebruikt wordt in dit systeem. De Kalman filter is ook deels gebaseerd op deze implementatie. Zo wordt er telkens gezocht naar de optimale toewijzing van detecties aan tracks op basis van de Euclidische afstand.
52
4 Het volgen van voertuigen doorheen de frames
Algorithm 2 Update van de Kalman filters 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
Maak kostenmatrix aan a.d.h.v. de Euclidische afstand; Doe optimale toewijzing met het Hongaars algoritme; if ( track is toegewezen) then if (afstand > distThresh) then push op vector niet toegewezen tracks; end if end if for (Elke toegewezen track) do track.skippedFrames = 0; update track met detectiepunt; end for for (Elke niet toegewezen track) do track.skippedFrames++; if (track.skippedFrames > maxSkippedFrames) then delete track; end if update track met voorspelling; end for for (Elke niet toegewezen detectie) do maak nieuwe track aan; end for
Met het Hongaars algoritme als laatste toevoeging, is de tracker volledig klaar om te worden gebruikt. Het is van essentieel belang dat deze Kalman filters op een correcte manier werken, omdat het telalgoritme hierop gebaseerd is. In pseudocode wordt er uitgelegd hoe deze Kalman filters worden geupdatet telkens er detecties zijn. Wanneer een track meer dan de maximale keer een ¨ frame achtereenvolgens heeft geskipped, dan wordt deze verwijderd uit de vector KalmanTracks. Voor elke nieuwe detectie die ook geen toewijzing heeft gekregen, wordt er een nieuwe track aangemaakt. Hiermee wordt de vector van type KalmanTrack die in de klasse KalmanTrackers zit dynamisch aangepast. Nu eenmaal het tracking algoritme op punt staat, kan er worden nagedacht om vervolgens de voertuigen te tellen. Deze tellingen worden in het volgende hoofdstuk besproken.
4.2
Het tellen van de voertuigen
Het uiteindelijke doel van deze masterthesis is het tellen van voertuigen aan een kruispunt. Zo moet er nog een algoritme geschreven worden die deze tellingen doet. Nu de voertuigen doorheen het beeld gevolgd worden en deze elk met een aparte tracker, kan er geteld worden aan de hand van deze trackers. De gegevens die deze trackers aan het telsysteem geven, zijn vectoren van punten waar elke ¨ tracker geweest is. Door deze vectoren te bestuderen, kan er op een efficiente manier geteld worden. Een eerste manier hoe deze tellingen worden gedaan, is door gebruik te maken van tellijnen. Een andere manier is door de vectoren van tracks grondig te bestuderen. Er gaat een ´ van deze methodes keuze gemaakt worden uit e´ en
4 Het volgen van voertuigen doorheen de frames
(a) De tellijnen aan een kruispunt.
53
(b) Voorbeeld hoe er geteld wordt.
Figuur 4.2: Voorbeel van de ligging van de tellijnen en wanneer er geteld wordt.
Een eerste manier die besproken wordt, is het tellen met behulp van tellijnen. Met tellijnen wordt er bedoeld dat er tijdens de initialisatie van het systeem lijnen worden getrokken, zodat wanneer een tracker, dat een voertuig voorstelt, voorbij zo’n lijn rijdt, er voor die specifieke richting wordt geteld. wanneer er een tracker - dat een voertuig voorstelt - voorbij zo’n lijn rijdt, er voor die specifieke richting wordt geteld. Op figuur 4.2(a) is er een voorbeeld te zien van tellijnen aan een kruispunt. Hierop is te zien dat elke lijn een bepaalde richting heeft en ze voor deze richting ook een aparte kleur hebben gekregen. Aangezien elk kruispunt verschillend is, worden deze lijnen ook per kruispunt apart getrokken. Een andere manier om voertuigen te tellen is door te kijken naar de geschiedenis van de tracker. Hiermee wordt bedoeld om te kijken naar de punten waar de tracker reeds is geweest. Zo wordt er bijvoorbeeld een verhouding tussen het laatst gekende punt en het laatst bijgehouden punt berekend. Deze verhouding of ratio bepaald dan welke richting het voertuig is opgereden. Deze vorm van tellen is heel gevoelig voor variatie van de tracker. Ook hebben de meeste kruispunten een verschillende vorm, waardoor er geen vaste ratio berekend kan worden voor elke richting. Hiervoor worden de ratio’s per kruispunt apart bepaald. Door de mogelijke variatie op de tracker en het apart bepalen van de ratio’s, is het praktischer om gebruik te maken van tellijnen. Deze tellijnen worden ook per kruispunt apart aangebracht, maar is beter bestand tegen variaties. De keuze die gemaakt wordt, is om te tellen met behulp van tellijnen. Doordat de verhoudingen per kruispunt apart bepaald moeten worden, gaat dit extra werk zorgen dat het systeem niet meer efficient is. Door gebruik te maken van tellijnen, is er maar weinig tijd nodig om deze op een correcte manier aan te brengen, zodat het systeem in een mum van tijd functioneert.
Figuur 4.3: De aangemaakte klasse voor de tellijnen.
Zo wordt er tijdens de initialisatie van het systeem ook een moment vrijgemaakt om deze lijnen te trekken. Tijdens deze moment worden deze tellijnen getrokken door met de muis op het frame te
54
4 Het volgen van voertuigen doorheen de frames
klikken. De programmacode waarop te zien is hoe dit gedaan wordt, is te zien in bijlage A.2. Het bepalen van de richting waarvoor de lijn staat wordt gedaan door op de overeenkomende toets te drukken. Wanneer er een fout wordt gemaakt tijdens het trekken van deze lijnen, is het ook mogelijk om deze lijnen weer te verwijderen zodat deze correct geplaatst worden. Zo wordt er ook uitgeprint op welke toetsen er allemaal gedrukt kunnen worden. Het trekken van de lijnen wordt gedaan op de region of interest, omdat buiten deze region of interest er geen belang wordt gehecht wat er gebeurd. Eenmaal alle lijnen zijn getrokken, kan het tellen beginnen. ´ van deze lijnen overschrijd. Dit wordt Het tellen op zich wordt gedaan wanneer een tracker e´ en getest door te kijken naar de positie het laatste bekende punt, wat op figuur 4.2(b) door een rode bol wordt aangegeven, en naar het laatste bijgehouden punt, wat op figuur 4.2(b) door een groene bol wordt aangegeven. Deze functie wordt voor elke track opgeroepen waarbij vergeleken wordt met elke tellijn. De pseudocode geeft aan op welke manier er geteld wordt.
Algorithm 3 De telfunctie 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
if ( track.toCount == True) then if ( rodeBol.yWaarde > groeneBol.yWaarde ) then for (Elke lijn) do if ( lijn.type == ’rechts’) then if ( rodeBol ligt links van deze lijn & groeneBol rechts van deze lijn) then track.toCount = false; rechts++; end if end if if ( lijn.type == ’rechtdoor’) then if ( rodeBol ligt onder deze lijn & groeneBol boven deze lijn) then track.toCount = false; rechtdoor++; end if end if if ( lijn.type == ’links’) then if ( rodeBol ligt rechts van deze lijn & groeneBol links van deze lijn) then track.toCount = false; links++; end if end if end for end if end if
Door middel van deze tellijnen is het tellen van voertuigen mogelijk gemaakt. Het trekken van deze lijnen op een beeld wordt simpelweg gedaan door met de muis het beginpunt en eindpunt aan te ´ klikken. Wanneer een van de tracks zo’n lijn overschrijdt, wordt er voor die bepaalde richting e´ en bijgeteld.
4 Het volgen van voertuigen doorheen de frames
4.3
55
Uitbreiding: de Haar cascade voertuig detector
Om ervoor te zorgen dat er enkel voertuigen worden geteld, wordt er als uitbreiding gebruik gemaakt van een voertuigdetector. Zo’n voertuigdetector, bestaande uit een classifier, gaat door middel van een voorgevormd model kijken of het wel degelijk om een voertuig gaat. Zo’n model wordt opgebouwd uit een reeks positieve en een reeks negatieve samples. Zo zullen de positieve samples telkens voertuigen bevatten en de negatieve samples alles behalve voertuigen. Aan de hand van deze samples wordt er een model getraind, waarmee nadien vergeleken kan worden. In de literatuurstudie wordt er reeds gesproken over een haar features gebaseerde cascade classifier. Deze classifier wordt reeds vaak gebruikt en ook in dit systeem wordt deze gebruikt als uitbreiding voor het tellen. Dit omdat deze classifier voertuigen kan detecteren uit verschillende kijkhoeken. Doordat het trainen van een model op zich al een thesis waard is, wordt er gebruik gemaakt van een reeds getraind model dat afkomstig is van [2]. De gegevens van dit model zijn opgeslagen in een xml bestand, die nadien worden ingelezen in het programma. De reden waarom er niet direct met een voertuigdetector wordt gewerkt, is om het systeem niet al te veel te vertragen. Zo is het ¨ efficienter om enkel naar de mogelijke plaatsen te kijken waar voertuigen zich voordoen. Daarom wordt er hier gebruik gemaakt van de laatste bekende positie van elk voertuig. zo wordt er telkens een voertuigdetectie uitgevoerd op de bounding box van elk voertuig. Deze bounding box wordt dynamisch bepaald en kan nooit relatief groot worden ten opzichte van het volledige frame. Door een voertuigdetectie toe te passen op alle bounding boxes en niet op het volledige frame, zorgt dit niet voor een grote vertraging van het systeem. Zo zijn er 2 mogelijke manieren om deze voertuigdetectie te implementeren. Enerzijds kijken of het om een voertuig gaat bij het tellen en anderzijds bijhouden hoelang het geleden is dat het voertuig nog eens gedetecteerd is. Er wordt in dit geval gekozen voor de tweede optie. Dit omdat bij het tellen het voertuig niet altijd even duidelijk meer is. Daarom wordt er gekozen om bij elke track een teller bij te houden. Deze teller onthoudt hoe lang het geleden is, dat de voertuigdetectie bij deze track een positief resultaat heeft gehad. Zo wordt er gekozen dat er maximum 1 seconde geen detectie meer mag zijn, anders wordt deze niet als voertuig geteld. Zo wordt er dus elke keer opnieuw gekeken naar alle bounding boxes en bij een positief resultaat wordt deze teller op ´ bijgeteld. Zie bijlage B.4 waarin er gekeken wordt of het om nul gezet en anders wordt er e´ en voertuigen gaat. Zo zijn er meerdere algoritmes ontwikkeld die het volgen en tellen van voertuigen mogelijk maakt. Het volgen van de voertuigen wordt gedaan aan de hand van een Kalman filter en het tellen door middel van tellijnen. Een extra uitbreiding wordt gedaan met een voertuigdetector. Deze detector gaat telkens weer kijken of het gaat om een voertuig, zodat enkel de voertuigen worden geteld.
Hoofdstuk 5
Evaluatie van de resultaten Uit voorgaande hoofdstukken is er een algoritme ontwikkeld dat voertuigen kan tellen ter hoogte van een kruispunt. Het is nu de bedoeling om te kijken of dit systeem ook op een correcte manier werkt. Daarom is het nodig om enkele testen uit te voeren, zodat vanuit deze resultaten eventuele verbeteringen worden aangebracht. Om resultaten met elkaar te vergelijken, wordt er een standaard gebruikt, die de waarden van deze testen kunnen beschrijven. Allereerst is het nodig om een ground truth op te maken. Zo bespreekt paragraaf 5.1 wat hiermee bedoeld wordt. Vervolgens bespreekt paragraaf 5.2 een mogelijke performantietest waarmee resultaten vergeleken worden en tevens ook de verkregen resultaten.
5.1
Het opmaken van een Ground truth
Om het systeem te testen, is er een referentie nodig om mee te vergelijken. Zo’n referentie wordt ook een ground truth genoemd. Een ground truth is in feite een nulmeting. Dit houdt in dat de voertuigen eerst handmatig geteld worden, zodat er exact geweten is hoeveel voertuigen er een bepaalde richting zijn opgereden. ¨ ¨ mogelijk Het creeren van een ground truth is heel tijdrovend. Daarom moet dit op een zo efficient gedaan worden. Hiervoor is er een apart C++ programma geschreven, om video’s te annoteren. Hoe dit programma in elkaar zit, wordt in deel 5.1.1 besproken.
5.1.1
Annotatie tool
Zo moet een ground truth 100% correct zijn, want anders kan er nooit op een juiste manier worden vergeleken. Problemen die hier kunnen voorkomen is dat de concentratie van de persoon verdwijnt na een lange periode van video’s te annoteren. Wanneer de concentratie weg is, kruipen er fouten in de ground truth. Dit moet ten allen tijde vermeden worden. Daarom wordt het programma zo opgebouwd, dat het bestand is tegen fouten. Zo wordt er gekozen om op basis van framenummers te annoteren. Een andere manier om dit te doen is door de centerpunten of contouren van elk voertuig te annoteren. Er wordt gekozen om met framenummers te werken, om zo te kijken of het voertuig op dat moment wel degelijk geteld wordt. Zo wordt tijdens het annoteren telkens het framenummer en richting bijgehouden, van zodra een voertuig op een bepaalde plaats rijdt. Vervolgens worden al deze gegevens naar een xml bestand geschreven, zodat deze later ingelezen 57
58
5 Evaluatie van de resultaten
kunnen worden. Het programma is zoals eerder gezegd geschreven in C++. Hoe dit programma is opgebouwd, wordt hieronder weergegeven in pseudocode. Algorithm 4 Annotatie programma 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
Open Filewriter; Open VideoCapture; while 1 do Neem frame van VideoCapture; if (frame.empty()) then Break; end if Klik met muis op het voertuig; if (rechts, rechtdoor of links) then Hou framenummer en richting bij; Schrijf weg naar xml via FileWriter; Sla frame op in map; end if if (’v’) then Doorspoelen = ! Doorspoelen; else if ’→’ then Ga naar volgend frame; else if ’←’ then Ga naar vorig frame; else if ’ESC’ then Break; end if end while Release VideoCapture; Release Filewriter;
Zo wordt in het begin van het programma een filewriter en een videocapture geopend. Er wordt dan in een while-lus gekomen, waarin de annotatie gedaan wordt. Wanneer er dan een voertuig geteld wordt, is het de bedoeling om met de muis te klikken op het voertuig, en dan de juiste knop in te drukken die overeenkomt met de opgereden richting. Het is pas mogelijk om een richting aan te duiden na het klikken met de muis. Zo kunnen er dus ook geen dubbele tellingen gebeuren. Dit is een van de redenen waarom er geklikt moet worden op het voertuig. Een andere reden is omdat het beter is om de concentratie van de persoon erbij te blijven houden. Op deze manier wordt er vermeden dat er foutieve gegevens in het xml bestand komen. Door op het pijltje naar links te duwen, wordt er naar een volgend frame gegaan. Indien er op het pijltje naar recht geduwd wordt, wordt er naar het vorige frame gegaan. Dit kan handig zijn als er frames te ver gegaan zijn. Vervolgens is het ook mogelijk om met de toets ´v´ de video verder af te spelen of terug te pauzeren, zodat - bij weinig verkeer - niet frame per frame op het pijltje gedrukt wordt om verder te gaan. Deze manier van annoteren zorgt ervoor dat het annoteren minder tijd in beslag neemt. Nu er eenmaal een ground truth is opgemaakt, wordt er nagedacht over de manier van vergelijken tussen de verschillende tests. In het volgende deel gaat het over Precision-recall, wat een veelgebruikte manier is om tests te vergelijken.
5 Evaluatie van de resultaten
5.2
59
Precision-recall performantie test
Met een foutloze ground truth, dat verkregen is van het annotatieprogramma, worden er nu metingen uitgevoerd op deze geannoteerde video. Deze metingen worden dan getest op performantie. Een veelgebruikte manier, dat een goed beeld kan geven van de performantie van het systeem, is door middel van precision-recall curves. Deze curves maken het mogelijk om verschillende tests met elkaar te vergelijken aan de hand van de eerder gemaakte ground truth. Hoe deze precisionrecall curves ge¨ınterpreteerd worden, wordt in dit deel nader verklaard.
Figuur 5.1: De confusion matrix.
Precision-recall maakt gebruik van de confusion matrix, die op figuur 5.1 te zien is. Op deze figuur is er te zien dat er gesproken wordt van true/false positives/negatives. Deze termen worden gebruikt wanneer:
• True Positive (TP): Zowel de meting als de ground truth zijn positief. Er is dus een auto gedetecteerd door het systeem en deze is bevestigd door de ground truth.
• False Positive (FP): Er is een voertuig gedetecteerd door het systeem, maar in de ground truth staat er niets van in. Deze meting is dus foutief, omdat het systeem denkt dat er een voertuig is gemeten, terwijl dat niet zo was.
• False Negative (FN): Volgens de ground truth rijdt er een voertuig voorbij, maar deze is niet gedetecteerd door het systeem.
• True Negative (TN): Er is zowel in de ground truth als in de meting geen detectie geweest. Deze laatste term zal voor dit systeem niet gebruikt worden, omdat enkel de detectie van zowel ground truth als meting van belang zijn. Nu deze termen nader verklaard zijn, wordt er gesproken over precision en recall. In het Nederlands ook wel de specificiteit en sensitiviteit genoemd. Bij precision gaat het over hoe nauwkeurig het systeem is, terwijl recall de gevoeligheid van het systeem aangeeft.
Precision =
TruePositive TruePositive + FalsePositive
(5.1)
Formule 5.1 toont dat precision afhankelijk is van de hoeveelheid true positives en de hoeveelheid false positives. Wanneer er geen false positives zijn, dan wordt de precision 100%. Bij recall
60
5 Evaluatie van de resultaten
wordt er aangegeven hoe gevoelig het systeem is en wordt door middel van onderstaande formule duidelijk gemaakt.
Recall =
TruePositive TruePositive + FalseNegative
(5.2)
Deze gevoeligheid van het systeem wordt bepaald door de hoeveelheid false negatives. Formule 5.2 geeft aan dat recall afhankelijk is van de true positives en de false negatives. Ook hier wordt er verondersteld dat, als er geen false negatives zijn, de recall hier 100% wordt. Het is belangrijk om op zowel precision als op recall goed te scoren. Dit kan best aangetoond worden aan de hand van een voorbeeld. Als er bijvoorbeeld een systeem een precision van 99% en een recall van 50% heeft, dan wilt dat zeggen dat het een nauwkeurig, maar gevoelig systeem is. De verkregen resultaten zullen 99% zeker voertuigen zijn, maar er worden maar 50% van de voorbijgereden voertuigen werkelijk gedetecteerd, wat niet ideaal is voor een telsysteem. Daarom is het streefdoel van een robuust systeem om zowel precision als recall dicht bij de 100% te krijgen. Zoals eerder gezegd werd, moeten de metingen vergeleken worden met de ground truth. Ook werd er al gesproken dat het framenummer werd bijgehouden bij zowel het opmaken van de ground truth als bij het meten door het systeem. Dit framenummer wordt nu gebruikt om de ground truth te vergelijken met de metingen. Hoe dit gedaan wordt, wordt in deel 5.2.1 besproken. Wanneer er dan geweten is hoe deze vergeleken gaan worden, worden de testen nadien vergeleken.
5.2.1
Het vergelijken van meting met ground truth
In dit deel wordt er besproken op welke manier de metingen nu vergeleken gaan worden met de opgemaakte ground truth. Door deze vergelijking te maken, wordt er een confusion matrix opgemaakt, waarin te staan komt hoeveel true positives, false positives en false negatives er zijn. ¨ Door een parameter van het systeem stelselmatig te laten varieren, ontstaan er meerdere confusion matrices. Aan de hand van deze matrices worden de verschillende precision- en recallwaarden berekend, die samen een precision-recall curve maken. ¨ Zo wordt een een precision-recall curve gemaakt voor een varierende deltaTime. Deze variabele, die gebruikt wordt in de transitiematrix van de Kalman filter, wordt gekozen omdat deze parameter als laatste wordt gebruikt voor het resultaat te bepalen. Om deze vergelijking te doen, is er een programma geschreven in Java. De reden waarom er hier plots met Java gewerkt wordt, is omdat er zowel van de ground truth, als voor de meting een xml bestand is opgemaakt dat nadien weer wordt ingelezen. Deze xml API werd tijdens mijn studies reeds besproken in Java en om hiervan dan ook gebruik te maken, wordt er gekozen om dit gedeelte in Java te schrijven. Dit programma gaat zowel de ground truth, als de meting vanuit xml inlezen en beide in een aparte List steken. Om de true-positives en false-positives te berekenen, wordt er ge¨ıtereerd over alle metingen en wordt er telkens gekeken of er voor deze meting een overeenkomstig resultaat in de ground truth is. Indien dit het geval is, is dit een true positive. Indien er geen overeenkomstig resultaat in de ground truth is gevonden, wordt dit als false-positive gezien. Om de false-negatives te zoeken, wordt er ditmaal ge¨ıtereerd over de ground truth en wordt er telkens naar een overeenkomstig resultaat gezocht in de metingen. Wanneer er voor de ground truth geen overeenkomstige meting is, wordt dit als false-negative gezien. ¨ Door nu de variabele deltaTime te doen varieren, worden verschillende confusion matrices opge´ precision- en e´ en ´ recallwaarde van berekend worden. maakt. Hiervan kan er dan telkens maar e´ en
5 Evaluatie van de resultaten
61
Wanneer deze waarden dan worden uitgezet op een plot en deze worden verbonden, ontstaat er een precision-recall curve. ´ variabele te veranderen, wat De precision-recall curve wordt opgemaakt door telkens maar e´ en in dit geval de ’deltaTime’ is. Aan de hand van deze curve kan de beste waarde voor deltaTime gevonden worden. Zo is het de bedoeling van een precision-recall curve om zo dicht mogelijk tot aan de rechterbovenhoek van de grafiek te bekomen. Wanneer precision op de y-as wordt voorgesteld en recall op de x-as, wilt dit zeggen dat beide waarden dan 100% zijn. Zo wordt de deltaTime gekozen door het dichtste punt van op deze plot te gebruiken. De waarde die voor deze deltaTime wordt gebruikt, is in dit geval de meest ideale waarde.
¨ Figuur 5.2: Precision-recall curve voor een varierende ’deltaTime’.
Zo wordt er een test uitgevoerd waarbij deze deltaTime van 0.01 tot 1 gaat over verschillende stappen . Deze test wordt op een relatief druk kruispunt uitgevoerd. Het eerste wat opvalt, is dat de verkregen resultaten teleurstellend zijn. Zo worden extreem lage precision- en recallwaarden verkregen uit het systeem. De maximumwaarde hieruit ligt om en bij de 1% voor zowel precision en recall. Een tweede punt van kritiek is de vorm van de grafiek. Deze is afwijkend van de normale vorm van een precision-recall curve. Wanneer er eerst wordt gekeken naar de cijfers, is er ontdekt dat deze resultaten niet onlogisch zijn. Het opmaken van de ground truth kan in feite nooit nauwkeurig genoeg zijn, om ze juist op dat framenummer vast te leggen. Hierop zit dus speling, wat in dit geval voor slechte resultaten zorgt. Wanneer er dan een interval wordt gebruikt, waarbinnen de detecties mogen liggen, gaan de resultaten dus ook beter worden. Zo wordt er een interval van 1 seconde of ook 30 frames gekozen, zodat een detectie tussen x − 30 en x + 30 frames mag liggen.
62
5 Evaluatie van de resultaten
¨ Figuur 5.3: Precision-recall curve voor een varierende ’deltaTime’ met interval = 30 frames.
Wanneer dit interval wordt gebruikt, dan wordt er een precision van rond de 91% en een recall van 93% bereikt. De vorm van deze grafiek lijkt ook al meer op een precision-recall curve. Op basis van deze resultaten wordt deltaTime op een waarde van 0.2 gekozen. Deze waarde geeft een precision van 91,9% en een recall van 93,5%. Deze resultaten zijn zoals verwacht beter dan zonder interval. Echter is het werken met een interval verre van ideaal. Het gebruik maken van een interval is een oplossing voor de variatie die tussen de ground truth en metingen gemaakt zijn, maar zegt zelf niets over de werking van het systeem. Er wordt wel verdergewerkt met dit interval van 30 frames, om zo confusion matrices te genereren. Zo wordt er per meting van deze confusion matrix een precision en recall waarde berekend, om zo verbeteringen aan het systeem te vergelijken.
(a) Opstelling van deze test.
(b) Confusion matrix.
Figuur 5.4: Opstelling en resultaten rustig verkeer.
Een eerste test is gedaan op een rustig kruispunt, waarbij de voertuigen individueel over het kruispunt rijden. Zo wordt ook de opstelling getoond op figuur 5.4(a). Met deze opstelling behoren alle rijvakken uit de op te meten richting tot de region of interest. Deze region of interest is alles wat binnen de blauwe lijnen valt. Hierbij worden resultaten behaald, die op figuur 5.4(b) worden weergegeven. Met een precision van 94% en een recall van 92% zijn deze eerste resultaten veelbelovend.
5 Evaluatie van de resultaten
63
Wanneer er gekeken wordt naar de oorzaak van het aantal false-positives en het aantal falsenegatives, dan wordt er gevonden dat er vijf fietsers over de lijn rijden om naar rechts te gaan, maar uiteindelijk wel rechtdoor rijden. Zo is er in de ground truth opgenomen dat deze fietsers rechtdoor rijden. Hierdoor ontstaat er per fietser een false-negative(niet gedetecteerd als rechtdoor) en een false-positive(gedetecteerd als naar rechts). Als deze waarden dan afgetrokken worden van de false-positives en false-negatives, dan worden er ook hogere precision en recall waarde verkregen. Een mogelijke manier om dit tegen te werken, is door gebruik te maken van een fietsdetector.
(a) Opstelling van deze test.
(b) Confusion matrix.
Figuur 5.5: Opstelling en resultaten rustig verkeer bis.
Een andere oorzaak is het verdwijnen van voertuigen in de achtergrond. Wanneer de voertuigen stil komen te staan aan een rood licht, dan gaan deze stelselmatig mee in de achtergrond verdwijnen. Hiervoor is er een logische oplossing gevonden. Zo wordt de region of interest verkleind tot enkel het gedeelte na de stoplijn. Wanneer de voertuigen dan stoppen aan het rode licht, gebeurt dit niet in de region of interest en wordt er dus geen rekening mee gehouden. De resultaten met de opstelling hiervan zijn te zien op figuur 5.5. Zo valt er te zien dat deze aanpassing voor betere resultaten zorgt. Een volgende test wordt gedaan op een iets drukker kruispunt, waarbij ook verkeer uit andere richtingen komt. Zo geeft deze test aan of dit verkeer al dan niet meegeteld wordt. Hier wordt er direct gebruik gemaakt van de kleinere region of interest, zodat de voertuigen niet in de achtergrond kunnen verdwijnen. De opstelling en resultaten worden ook weer getoond aan de hand van een figuur (figuur 5.6).
64
5 Evaluatie van de resultaten
(a) Opstelling van deze test.
(b) Confusion matrix.
Figuur 5.6: Opstelling en resultaten drukker verkeer.
Zo zijn de resultaten in dit geval ook veelbelovend. Met een precision van 92% en een recall van 93% heeft het verkeer uit andere richtingen hierbij weinig invloed. De meeste problemen komen van grote vrachtwagens die voor te grote blobs zorgen. Ook wanneer de voertuigen gelijktijdig vertrekken ontstaat er een grote blob, waardoor de kans bestaat dat een voertuig niet wordt meegeteld.
(a) Opstelling van deze test.
(b) Confusion matrix.
Figuur 5.7: Opstelling en resultaten drukker verkeer met voertuigdetector.
Zo wordt er vervolgens nog een extra uitbreiding aan dit systeem toegevoegd. Door middel van een voertuigdetector wordt er lokaal gekeken of het om voertuigen gaat. Zo wordt er pas geteld, als er minder dan 30 frames geleden de track als voertuig is gedetecteerd. Deze test wordt uitgevoerd op dezelfde video als voordien met het drukkere verkeer. Als er dan nu gekeken wordt naar de confusion matrix, dan valt er te zien dat er een precision van 100% is behaald. Dat wil zeggen dat bij elke detectie er ook een record in de ground truth is gevonden binnen dat interval van 30 frames. De recall waarde is hier dan weer teleurstellen. Met een waarde van 13% zijn er dus veel voertuigen niet geteld door het systeem. Een mogelijke reden is dat het model, waarmee vergeleken wordt, niet specifiek voor deze toepassing is gemaakt. Een andere reden is dat de region of interest klein
5 Evaluatie van de resultaten
65
van formaat is. Hierdoor is er maar een beperkte tijd om een voertuig te detecteren aan de hand van dit model. Door deze lage recall waarde, wordt deze uitbreiding verworpen uit het systeem.
(a) Opstelling van deze test.
(b) Confusion matrix.
Figuur 5.8: Opstelling en resultaten drukker verkeer met voertuigdetector.
Een laatste test die wordt uitgevoerd is op een kruispunt waar er meer verkeer uit de andere verschillende richtingen komen dan uit de te meten richting. Tevens zijn de omstandigheden ook minder ideaal. Zo ligt er een sneeuwlaag op het wegdek en wordt het ook nog eens donker. Voor deze laatste test wordt ook weer de opstelling en resultaten gegeven en dit aan de hand van figuur 5.8 Wanneer voor dit extreme geval de resultaten bekeken worden, zijn er veel false-positives. Dit kan enerzijds door de reflectie van de sneeuw komen, maar anderzijds ook door het verkeer uit andere richtingen. Ook de hoeveelheid false-negatives ten opzichte van true-positives ligt hoog. Hierdoor wordt er een lage recallwaarde bekomen. Zo werkt het systeem goed in het ideale geval en minder wanneer de omstandigheden niet ideaal zijn. Met mogelijke uitbreidingen kunnen de resultaten onder niet-ideale omstandigheden eventueel beter worden Deze verbeteringen komen in paragraaf 6.1 aan bod.
Hoofdstuk 6
Besluit Er is een systeem ontwikkeld dat voertuigen kan tellen aan een kruispunt met behulp van camera’s. De doelstelling om dit ook real-time te laten functioneren is bij deze ook gelukt. In dit hoofdstuk wordt een besluit genomen of de doelstellingen al dan niet behaald zijn, waarna nog mogelijke verbeteringen worden besproken in de future work. De conclusie van deze masterthesis is dat het niet al te simpel is om een robuust telsysteem te maken voor voertuigen met behulp van camerabeelden. Er zijn vele verschillende factoren waar rekening mee wordt gehouden, om er een robuust systeem van te maken. Zo heeft elk kruispunt een verschillende vorm en een verschillend aantal richtingen. Elke wagen heeft ook weer een verschillende vorm, kleur en grootte. Het systeem moet onder alle omstandigheden een gelijk resultaat weergeven, enz. Al deze factoren maken het niet eenvoudig om een goed systeem te ontwikkelen. Een eerste conclusie die getrokken wordt, is dat het testen van het systeem op vlak van framenummers niet echt mogelijk is. Doordat er bij het opmaken van de ground truth een menselijke fout wordt gemaakt, kunnen de metingen nooit op hetzelfde framenummer overeenkomen. Hiervoor moet er dus een alternatieve methode worden gebruikt. Wanneer er zoals in dit geval toch gebruik wordt gemaakt van framenummers om te vergelijken, waarbij een interval wordt gebruikt, lijken de resultaten goed te zijn voor er nog maar een jaar aan bezig te zijn. Zo wordt een precisie van 95% en een recall van 93% behaald wanneer er gewerkt wordt onder ideale omstandigheden. Wanneer er niet gewerkt wordt onder ideale omstandigheden, dan worden er nog teveel fouten gemaakt. Hierdoor is het systeem nog niet robuust genoeg om te gaan implementeren. Met behulp van enkele verbeteringen kan dit systeem eventueel wel gebruikt worden om het verkeer te tellen. Het gebruik maken van een voertuigdetector, om te kijken of het wel degelijk om voertuigen gaat, zorgt in dit geval voor mindere goede cijfers. Hierdoor wordt deze nog niet ge¨ımplementeerd in dit systeem. Een algemeen besluit dat hieruit getrokken wordt, is dat het wel degelijk mogelijk is om voertuigen met behulp van camera’s te tellen aan een kruispunt. Om dit ook op een robuuste manier te doen, moeten er nog wel wat verbeteringen aangebracht worden.
67
68
6.1
6 Besluit
Future work
Om van dit systeem een meer robuust systeem van te maken, zijn enkele aanpassingen nodig. Deze aanpassingen zijn door tijdsgebrek niet verder aan bod gekomen in het systeem. Een eerste aanpassing is het gebruik maken van een andere manier van annoteren en vergelijken. Zo wordt er voorgesteld om dit te doen aan de hand van de centerpunten van elk voertuig in een frame. Ook mogelijk is om de contouren van elk voertuig te bepalen, om zo tot een nog meer nauwkeurig resultaat te bekomen. Zo is er bijvoorbeeld ook nog geen algoritme ge´ımplementeerd om camera shaking tegen te werken. Vanaf wanneer een camera een kleine beweging maakt, maakt het systeem fouten. Deze fouten zijn nadelig op het systeem, waardoor er verkeerd geteld wordt. Wanneer een methode wordt ge¨ımplementeerd dat dit tegenwerkt, wordt het systeem robuust tegen camera shaking. Ook wordt er hier enkel maar gewerkt met visuele camera’s. Wanneer het donker wordt, gaan de beelden minder duidelijk worden en gaat het tellen nog moeilijk gaan. Hiervoor wordt er voorgesteld om gebruik te maken van infraroodcamera’s. Deze camera’s maken gebruik van het infrarode deel uit het elektromagnetische spectrum, zodat deze 24/24 kunnen functioneren. Zo kunnen deze infraroodcamera’s eventueel een beter resultaat geven bij de voorgrond / achtergrond segmentatie. Het maken van een goed model voor een voertuigdetector is ook een uitdaging. Nu wordt er gebruik gemaakt van een model dat gevonden werd op het internet. Zo kan een specifiek gemaakt model eventueel voor betere resultaten zorgen.
Figuur 6.1: Voorstel andere positie camera.
Een mogelijke oplossing om verkeer uit andere richtingen niet mee te tellen, is door een andere positie te kiezen voor de camera. Nu worden de camera’s aan de andere kant van het kruispunt geplaatst. Hierdoor be¨ınvloed het verkeer uit de andere richtingen de tellingen. Indien deze camera geplaatst wordt zoals op figuur 6.1, dan be¨ınvloed het verkeer uit andere richtingen deze metingen niet. Een laatste mogelijke uitbreiding is het gebruik maken van een GPU. Een GPU kan beter parallel werken, wat voor computervisie goed van pas komt, dan een CPU. Zo zijn alle testen uitgevoerd op een CPU. Deze uitbreidingen kunnen ervoor zorgen dat het systeem meer robuust wordt, zodat het mogelijk wordt om dit te gaan gebruiken.
Bibliografie [1] Agentschap
wegen en verkeer - verkeerstellingen. http://www.wegenenverkeer.be/ verkeer-en-mobiliteit/verkeersleefbaarheid/verkeerstellingen.html. [Online; accessed 16-October-2013].
[2] opencv-lane-vehicle-track.
https://code.google.com/p/opencv-lane-vehicle-track/ source/browse/trunk/bin/haar/cars3.xml?r=2, Dec. 2012. [Online; accessed 10-February2014].
[3] H. belang van Limburg. Verkeer online tellen met handcomputers. http://www.hbvl.be/limburg/ genk/verkeer-online-tellen-met-handcomputers.aspx. [Online; accessed 16-October-2013]. [4] D. P. Bertsekas. A new algorithm for the assignment problem. Mathematical Programming, 21(1):152– 171, 1981. [5] T. Bouwmans. Recent advanced statistical background modeling for foreground detection: A systematic survey. RPCS, 4(3):147–176, 2011. [6] A. K. Gary Bradski. Learning OpenCV: Computer Vision with the OpenCV Library. O’Reilly, 2008. [7] S. Gupte, O. Masoud, R. F. Martin, and N. P. Papanikolopoulos. Detection and classification of vehicles. Intelligent Transportation Systems, IEEE Transactions on, 3(1):37–47, 2002. [8] S. Hoornaert. Verkeersindicatoren hoofdwegennet vlaanderen 2012. januari-februari 2013 13004, Verkeerscentrum Vlaanderen, januari-februari 2012. [9] A. J. Lipton, H. Fujiyoshi, and R. S. Patil. Moving target classification and tracking from real-time video. In Applications of Computer Vision, 1998. WACV’98. Proceedings., Fourth IEEE Workshop on, pages 8–14. IEEE, 1998. [10] J. Losty and P. Watkins. Computer vision for industrial applications. Software & Microsystems, 2(5):130– 138, 1983. [11] R. C. T. Nilesh J Uke. Moving vehicle detection for measuring traffic count using opencv, 2013. [12] OpenCV. Opencv documentation. http://docs.opencv.org. [Online; accessed 21-May-2014]. [13] M. Piccardi. Background subtraction techniques: a review. In Systems, man and cybernetics, 2004 IEEE international conference on, volume 4, pages 3099–3104. IEEE, 2004. [14] A. Prati, I. Mikic, M. M. Trivedi, and R. Cucchiara. Detecting moving shadows: algorithms and evaluation. Pattern Analysis and Machine Intelligence, IEEE Transactions on, 25(7):918–923, 2003. [15] S. C. Sen-Ching and C. Kamath. Robust techniques for background subtraction in urban traffic video. In Electronic Imaging 2004, pages 881–892. International Society for Optics and Photonics, 2004.
69
70
BIBLIOGRAFIE
[16] A. Smorodov.
Multitarget-tracker + hungarian algorithm. https://github.com/Smorodov/ Multitarget-tracker/blob/master/HungarianAlg/HungarianAlg.h. [Online; accessed 27February-2014].
[17] C. Stauffer and W. E. L. Grimson. Adaptive background mixture models for real-time tracking. In Computer Vision and Pattern Recognition, 1999. IEEE Computer Society Conference on., volume 2. IEEE, 1999. [18] S. Suzuki et al. Topological structural analysis of digitized binary images by border following. Computer Vision, Graphics, and Image Processing, 30(1):32–46, 1985. [19] D. Tijd.
Fileprobleem stijgt meest in antwerpen. http://www.tijd.be/nieuws/politiek_ economie_belgie/Fileprobleem_stijgt_meest_in_Antwerpen.9427684-3136.art, Nov. [Online; accessed 16-October-2013].
[20] TRANSPORT and M. LEUVEN. Emissies van het wegverkeer in belgie¨ 1990-2030. Technical report, TRANSPORT And MOBILITY LEUVEN, http://www.tmleuven.be, 2006. [21] P. Viola and M. Jones. Rapid object detection using a boosted cascade of simple features. In Computer Vision and Pattern Recognition, 2001. CVPR 2001. Proceedings of the 2001 IEEE Computer Society Conference on, volume 1, pages I–511. IEEE, 2001. [22] G. Welch and G. Bishop. An introduction to the kalman filter, 1995. [23] Z. Zivkovic. Improved adaptive gaussian mixture model for background subtraction. In Pattern Recognition, 2004. ICPR 2004. Proceedings of the 17th International Conference on, volume 2, pages 28–31. IEEE, 2004.
Bijlage A
Programmacode initialisatie van het systeem Listing A.1: Het maken van een region of interest 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
void CallBackFuncRoiFrame ( int event , int x , int y , int flags , void * param ){ // Wanneer er met de linkse muisknop wordt geklikt -> onthoudt punt . if ( event == CV_EVENT_LBUTTONDOWN ){ Point2i punt = Point (x ,y ); ROI_Vertices_temp . push_back ( punt ); } } /* Deze functie zorgt voor het aanmaken van de ROI . De punten die aangeklikt worden , worden bijgehouden in een vector van punten Aan de hand van deze punten wordt een witte polygoon gemaakt , dat als masker dient . */ void makeROI ( Mat & frame , Mat & maskerROI , vector < Point > & ROI_Vertices , vector < Point > & ROI_Poly ){ cout cout cout cout
<< << << <<
" Klik op de plaatsen om een ROI te maken " << endl ; " Er moeten minstens 4 punten aangeklikt worden " << endl ; " Gebruik ’n ’ om nadien verder te gaan " << endl ; endl ;
// Lus die gebruikt wordt om een ROI te maken while (1) { // functie die de muisevents behandeld setMouseCallback (" ROI Window " , CallBackFuncRoiFrame ); char c = waitKey ( WAITFRAME ); // Naar volgende stap gaan if (c == ’n ’){ break ; } // 27 staat voor ESC else if (c == 27){ exit ( EXIT_FAILURE ); } // Tekenfunctie van cirkels en tekst op de reeds aangeklikte punten for ( int i =0; i < ROI_Vertices_temp . size (); i ++){ circle ( frame , ROI_Vertices_temp . at (i), 5, Scalar (255 ,0 ,0)); char buffer [50]; sprintf ( buffer ," h: %d , w: %d" , ROI_Vertices_temp . at (i ).x , ROI_Vertices_temp . at (i ). y );
71
72
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
A Programmacode initialisatie van het systeem
putText ( frame , buffer , ROI_Vertices_temp . at (i), 1, 1, Scalar (0 ,255 ,0)); } imshow (" ROI Window " , frame ); } ROI_Vertices = ROI_Vertices_temp ; // Als size == 0 ( niet geklikt ) -> Volledig frame nemen als ROI if ( ROI_Vertices . size () == 0){ Point2i punt = Point2i (0 ,0); ROI_Vertices . push_back ( punt ); punt = Point2i ( frame . cols ,0); ROI_Vertices . push_back ( punt ); punt = Point2i ( frame . cols , frame . rows ); ROI_Vertices . push_back ( punt ); punt = Point2i (0 , frame . rows ); ROI_Vertices . push_back ( punt ); } // Te weinig punten aangeklikt if ( ROI_Vertices . size () < 3){ cout << " Meer punten voor ROI nodig " << endl ; exit ( EXIT_FAILURE ); } // Polygoon aanmaken approxPolyDP ( ROI_Vertices , ROI_Poly , 1.0 , true ); // Polygoon opvullen met wit fillConvexPoly ( maskerROI , & ROI_Poly [0] , ROI_Poly . size () , 255 , 8, 0); }
Listing A.2: Het trekken van de tellijnen 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
void CallBackFunc ( int event , int x , int y , int flags , void * param ){ // Op de linkermuisknop gedrukt if ( event == CV_EVENT_LBUTTONDOWN ){ // Indien eerst op de ’r ’ gedrukt if ( rechts ){ lijn . Type = " Rechts "; lijn . TypeId = 0; } // Indien eerst op de ’r ’ gedrukt if ( rechtdoor ){ lijn . Type = " Rechtdoor "; lijn . TypeId = 1; } // Indien eerst op de ’y ’ gedrukt if ( links ){ lijn . Type = " Links "; lijn . TypeId = 2; } switch ( status ){ case 0: // Eerste klik is beginpunt cout << " BeginPunt " << endl ; lijn . BeginPunt .x = x; lijn . BeginPunt .y = y; status = 1; break ; case 1: // Tweede klik is eindpunt van de lijn cout << " Eindpunt " << endl ; lijn . EindPunt .x = x; lijn . EindPunt .y = y; getekend = true ; status = 0; lijnen . push_back ( lijn ); // Terug op nul zetten voor volgende lijn break ; default : break ;
A Programmacode initialisatie van het systeem
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
73
} } } // Het tekenen van de reeds bestaande lijnen void drawCountLines ( Mat & frame , vector < Line > lijnenTekenen ){ Scalar Colors []={ Scalar (255 ,0 ,0) , Scalar (0 ,255 ,0) , Scalar (0 ,0 ,255)};
for ( int i =0; i < lijnenTekenen . size (); i ++){ line ( frame , lijnenTekenen . at (i ). BeginPunt , lijnenTekenen . at (i ). EindPunt , Colors [ lijnenTekenen . at putText ( frame , lijnenTekenen . at (i ). Type , lijnenTekenen . at (i ). BeginPunt , 1, 2, Colors [ lijnenTeken } } // Functie die het trekken van de tellijnen behandeld void klikTellijnen ( Mat & frame , vector < Line > & ln ){ lijnen = ln ; Mat backup ; frame . copyTo ( backup ); cout << " Maak nu de tellijnen aan . Klik het beginpunt en het eindpunt aan van elke lijn ." << endl ; cout << "\ tVoor Rechts : ’r ’" << endl ; cout << "\ tVoor Rechtdoor : ’t ’" << endl ; cout << "\ tVoor Links : ’y ’" << endl ; cout << " Door op ’u ’ te duwen maak je je lijnen ongedaan ." << endl ; cout << " Met ’n ’ ga je verder ." << endl ; cout << endl ; while (1){ imshow (" lijnWindow " , frame ); if ( lijnen . size () > 0){ backup . copyTo ( frame ); drawCountLines ( frame , lijnen ); } setMouseCallback (" lijnWindow " , CallBackFunc ); char c = waitKey ( WAITFRAME ); // Klaar met lijnen trekken , volgende stap if (c == ’n ’){ ln = lijnen ; break ; } // 27 is ESC -> stoppen programma else if (c == 27){ exit ( EXIT_FAILURE ); } // Volgende lijn is voor rechts else if (c == ’r ’){ cout << " Rechts " << endl ; rechts = true ; rechtdoor = false ; links = false ; } // Volgende lijn is voor rechtdoor else if (c == ’t ’){ cout << " Rechtdoor " << endl ; rechts = false ; rechtdoor = true ; links = false ; } // Volgende lijn is voor links else if (c == ’y ’){ cout << " Links " << endl ; rechts = false ; rechtdoor = false ; links = true ;
74
103 104 105 106 107 108 109 110
A Programmacode initialisatie van het systeem
} // Alle lijnen wissen bij een fout else if (c == ’w ’){ lijnen . clear (); backup . copyTo ( frame ); } } }
Bijlage B
Programmacode verdere verloop programma Listing B.1: Het bestuderen van de blobs met behulp van findContours en Moments 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
/* Deze functie zoekt informatie uit de voorgrondbeelden om tot punten te bekomen die gebruikt worden voor de Kalman filters . Hier wordt gebruik gemaakt van de OpenCV functie findContours en moments . */ void berekenMoments ( Mat & foreground , vector < centerGrootte > & centArea ){ centArea . clear (); Mat temp ; foreground . copyTo ( temp ); // twee vectoren die nodig zijn voor de output van findContours vector < vector < Point > > contours ; vector < Vec4i > hierarchy ; // De contouren van elke blob bepalen findContours ( temp , contours , hierarchy , CV_RETR_CCOMP , CV_CHAIN_APPROX_SIMPLE ); // De momenten methode gebruiken om zwaartepunt te berekenen van elke blob double refArea = 0; bool objectFound = false ; // Indien er contouren gevonden zijn if ( hierarchy . size () > 0) { int numObjects = hierarchy . size (); // Wanneer er meer objecten gevonden zijn dan toegelaten is -> ruis ( niet verder verwerken ) if ( numObjects < MAX_NUM_OBJECTS ){ // Itereren over alle contours for ( int index = 0; index >= 0; index = hierarchy [ index ][0]) { Moments moment = moments (( cv :: Mat ) contours [ index ]); // De oppervlakte voor die blob double area = moment . m00 ; // Elke blob moet een minimale grootte hebben if ( area > MIN_OBJECT_AREA ){ centerGrootte cent ; Point2d centPunt ; centPunt .x = moment . m10 / area ; centPunt .y = moment . m01 / area ; cent . centerpunt = centPunt ;
75
76
44 45 46 47 48 49 50 51 52 53
B Programmacode verdere verloop programma
cent . area = area ; centArea . push_back ( cent ); objectFound = true ; } else objectFound = false ; } } } }
Listing B.2: De initialisatie van de Kalman filter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/* Hier wordt initialisatie van een Kalman filter gedaan , waarbij alle matrices correct worden ingevuld . dt : bepaald de gebruikte snelheid bij de prediction p : is het eerste bekende punt van deze Kalman filter */ KalmanF :: KalmanF ( Point2i p , float dt ){ deltatime = dt ; kalman = new KalmanFilter ( 4, 2, 0 ); kalman -> transitionMatrix = ( Mat_ < float >(4 , 4) <<
1 ,0 , deltatime ,0 , 0 ,1 ,0 , deltatime , 0 ,0 ,1 ,0 , 0 ,0 ,0 ,1);
// init ... lastResult = p; kalman -> statePre .at < float >(0) = p.x; // x kalman -> statePre .at < float >(1) = p.y; // y kalman -> statePre .at < float >(2) = 0; kalman -> statePre .at < float >(3) = 0; kalman -> statePost .at < float >(0)= p.x; kalman -> statePost .at < float >(1)= p.y; setIdentity ( kalman -> measurementMatrix ); setIdentity ( kalman -> processNoiseCov , Scalar :: all (1e -4)); setIdentity ( kalman -> measurementNoiseCov , Scalar :: all (1e -1)); setIdentity ( kalman -> errorCovPost , Scalar :: all (.1)); toCount = true ; } }
Listing B.3: Het telalgoritme 1 2 3 4 5 6 7 8 9 10 11 12 13 14
/* Deze functie is de effectieve telfunctie van dit systeem . Elke track wordt hier telkens getest of deze niet voorbij een tellijn is gepasseerd . Deze gaat bij het tellen ook informatie wegschrijven naar een xml bestand + een frame wegschrijven naar een map . */ void countAlgorithm ( Mat & frame , Mat & frameTonen , Point linkerbovenhoek , int & rechtsRijden , int & rechtdoorRijden , int & linksRijden , vector < Line > lijnen , Point2f bp , Point2f ep , KalmanTrack & track , int totaalCount , int frameCount , FileStorage & fs ){ Point2i beginPuntLijn ; Point2i eindPuntLijn ; // Als de track nog moet tellen if ( track .KF -> toCount == true ){
B Programmacode verdere verloop programma
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
77
// Rijdt de wagen naar beneden ? if ( bp .y > ep .y ){ record HuidigRecord ; // alle lijnen overlopen for ( int i =0; i < lijnen . size (); i ++){ beginPuntLijn = lijnen . at (i ). BeginPunt ; eindPuntLijn = lijnen . at (i ). EindPunt ;
// Is de lijn van type rechts ? if ( lijnen . at (i ). Type == " Rechts " ){ if ( ( bp .x > beginPuntLijn .x) && ( bp .x < eindPuntLijn .x) && ( bp .y > beginPuntLijn .y )) if (( ep .x > beginPuntLijn .x) && ( ep .y < eindPuntLijn .y )){ rechtsRijden ++; track .KF -> toCount = false ; // Variabele voor xml bestand HuidigRecord . count = totaalCount ; HuidigRecord . frameC = frameCount ; HuidigRecord . rechts = 1; HuidigRecord . rechtdoor = 0; HuidigRecord . links = 0; fs << " record " << HuidigRecord ; // Frame wegschrijven naar een map string fc = to_string ( frameCount ); string eind = " _rechts . jpg "; string path ="/ users / jeroen / desktop / frames / "+ fc + eind ; circle ( frame , bp , 25 , Scalar (255 ,0 ,0)); imwrite ( path , frameTonen ); cout << " Count : " << frameCount << " Rechts ." << endl ; } }
} else if ( lijnen . at (i ). Type == " Rechtdoor " ){ if ( ( bp .x > beginPuntLijn .x) && ( bp .x < eindPuntLijn .x) && ( bp .y > beginPuntLijn .y )) if (( ep .x > beginPuntLijn .x) && ( ep .y < eindPuntLijn .y )){ rechtdoorRijden ++; track .KF -> toCount = false ; // Variabele voor xml bestand HuidigRecord . count = totaalCount ; HuidigRecord . frameC = frameCount ; HuidigRecord . rechts = 0; HuidigRecord . rechtdoor = 1; HuidigRecord . links = 0; fs << " record " << HuidigRecord ; // Wegschrijven van frame naar map string fc = to_string ( frameCount ); string eind = " _rechtdoor . jpg "; string path ="/ users / jeroen / desktop / frames / "+ fc + eind ; circle ( frame , bp , 25 , Scalar (255 ,0 ,0)); imwrite ( path , frameTonen ); cout << " Count : " << frameCount << " Rechtdoor ." << endl ; } }
} // Anders links else if ( lijnen . at (i ). Type == " Links " ){ if ( ( bp .x > beginPuntLijn .x) && ( bp .x < eindPuntLijn .x) && ( bp .y > eindPuntLijn .y )){ if (( ep .x > beginPuntLijn .x) && ( ep .y < beginPuntLijn .y )){
78
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
B Programmacode verdere verloop programma
linksRijden ++; track .KF -> toCount = false ; // Variabele voor xml bestand HuidigRecord . count = totaalCount ; HuidigRecord . frameC = frameCount ; HuidigRecord . rechts = 0; HuidigRecord . rechtdoor = 0; HuidigRecord . links = 1; fs << " record " << HuidigRecord ; // Wegschrijven van frame naar map string fc = to_string ( frameCount ); string eind = " _links . jpg "; string path ="/ users / jeroen / desktop / frames / "+ fc + eind ; circle ( frame , bp , 25 , Scalar (255 ,0 ,0)); imwrite ( path , frameTonen ); cout << " Count : " << frameCount << " Links ." << endl ; } } } }
Listing B.4: Uitbreiding: De voertuigdetector 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
/* Dit deel van een functie , wordt gebruikt voor het zoeken van een voertuig door middel van een voertuigdetector */ // Laad xml bestand in cars . load ("/ users / jeroen / desktop / cars3 . xml " ); // Voor iedere track for ( int i =0;i < tracks . size (); i ++) { Mat cropped , gray ; Rect r; carsVector . clear (); centerGrootte trackCenterGrootte ; trackCenterGrootte . centerpunt = tracks . at (i)->KF -> lastResult ; trackCenterGrootte . area = tracks . at (i)-> area ; // Punt vergroten om in volledig frame te passen trackCenterGrootte . centerpunt = Point ( trackCenterGrootte . centerpunt .x + linkerBovenhoek .x , trackCenterGrootte . centerpunt .y + linkerBovenhoek .y ); getRectangleFromBigFrame ( frameTonen , trackCenterGrootte , r ); // rectangle ( frameTonen , r , Scalar (128 ,128 ,255)); // Grootte van de rechthoek mag niet te groot zijn if (r. height < 150 && r. width < 150){ frame (r ). copyTo ( cropped ); if ( cropped . cols > 0 && cropped . rows > 0){ cvtColor ( cropped , gray , CV_RGB2GRAY ); // Detecteren cars . detectMultiScale ( gray , carsVector , 1.2 , 3, CV_HAAR_FIND_BIGGEST_OBJECT , Size (10 ,10)); // Bij een detectie alles terug op nul zetten if ( carsVector . size () > 0){ tracks . at (i)-> skipped_frames = 0; tracks . at (i)->KF -> LastDetectionFrameCount = 0; } // Anders 1 bijtellen else { tracks . at (i)->KF -> LastDetectionFrameCount ++; } } else { tracks . at (i)->KF -> LastDetectionFrameCount ++;
B Programmacode verdere verloop programma
44 45 46 47 48 49
} } else { tracks . at (i)->KF -> LastDetectionFrameCount ++; } }
79
FACULTEIT INDUSTRIELE INGENIEURSWETENSCHAPPEN CAMPUS DE NAYER (@Thomas More) Jan De Nayerlaan 5 2860 SINT-KATELIJNE-WAVER, België tel. + 32 15 31 69 44
[email protected] www.iiw.kuleuven.be