← Terug naar Blog
Machine learningComputer visionAudio & DSP

Zoals veel van jullie wel weten ben ik naast mijn werk bij TNO fervent vogelaar. Toen ik hier een paar jaar geleden voor het eerst mee begon, deed ik wat ik meestal doe met nieuwe hobby’s: ik downloadde en gebruikte alle vogel-apps op de markt, realiseerde me dat geen enkele precies werkte zoals ik wilde, en bouwde mijn eigen app.

Dat werd Limosa (naar de nationale vogel van Nederland, de Grutto): een sociale vogel-app om waarnemingen vast te leggen met foto’s, video en geluid, ze te delen met andere vogelaars, en met een UI die is geoptimaliseerd voor gebruik in het veld.

Een Pestvogel die een besje eet in een struik
Pestvogel Bombycilla garrulus 94%
De score komt uit de vergelijking met de referentiebibliotheek, niet uit een model dat zelf een getal noemt. Bekijk de waarneming.

Een van de complexere functies die andere vogel-apps wél bieden is soortherkenning: je maakt een foto, video of geluidsopname, en de app vertelt je om welke soort het gaat. Die wilde ik natuurlijk ook. In deze blogpost leg ik uit hoe ik mijn eerste naïeve aanpak, het aanroepen van een algemene AI via een API, heb vervangen door een zelf-gehoste pijplijn die zowel op mijn server als on-device draait, beter presteert dan het origineel, en waarvoor ik geen eigen model hoefde te trainen, zonder in te leveren op licenties en privacy.

De makkelijke manier

De voor de hand liggende manier kostte een middag: neem wat de gebruiker heeft ingestuurd, een foto, video of geluidsopname, geef het aan een algemene multimodale AI via een API, vraag om welke soort het gaat, en toon het antwoord. Het werkt, en je hebt het zo draaien. Voor veel producten is dat een prima aanpak, maar in mijn geval schoot het op een paar punten tekort.

Ik heb het niet gehouden, om redenen die zich bleven opstapelen:

  • Om te beginnen vereist deze aanpak dat ik de data van mijn gebruikers naar een derde partij stuur. Dat omvat foto’s, video’s en geluidsopnames, plus GPS-locaties die worden gebruikt om het antwoord van de AI te verbeteren, aangezien sommige soorten alleen in bepaalde gebieden voorkomen. Dat is veel gevoelige data om af te staan voor één label.
  • De dienst is een black box: hij kan het mis hebben, en je komt er niet achter waarom. Je kunt de trainingsdata niet inzien, je kunt niet zien wat hij weet, en je kunt het niet repareren als hij een fout maakt.
  • Het maakt een volledig offline modus onmogelijk: het model draait op de servers van iemand anders, en je kunt het niet op het toestel zelf draaien.
  • Elke aanvraag kost geld, en de prijzen zijn niet transparant. Je kunt van tevoren niet weten wat het gaat kosten om het model op de data van je gebruikers te draaien.

Beschrijf eerst, vergelijk daarna

In plaats van een model in één keer te vragen welke soort er op een foto staat, kun je die vraag ook opknippen: eerst de media omzetten in iets wat je kunt vergelijken, en daarna pas vergelijken. Dat lijkt een omweg, maar het haalt de black box uit het midden van het proces.

Gebruik daarvoor een model dat alleen beschrijft hoe een geluid of afbeelding eruitziet: als een lijst getallen, een embedding. Twee opnames van dezelfde soort komen dicht bij elkaar te liggen in die ruimte, terwijl een andere soort verder weg valt. Het model leert nooit ook maar één soortnaam.

En daar zit het verschil dat alles mogelijk maakt: dit soort embedding-modellen kun je gewoon downloaden, met licenties die commercieel gebruik toestaan. Een generiek AI-model achter een API kun je niet downloaden en niet zelf hosten, dus blijf je altijd afhankelijk van die ene dienst. Een embedder draait op mijn eigen server, of zelfs op de telefoon.

Daarnaast bouw je een kleine referentiebibliotheek: je berekent de embedding van een handvol bevestigde voorbeelden per soort en middelt die tot één referentievector per soort. Geen trainingsronde, gewoon een gemiddelde. Om iets nieuws te herkennen bereken je de embedding en zoek je de dichtstbijzijnde referentie. De dichtstbijzijnde wint, en hoeveel dichterbij die ligt dan de nummer twee bepaalt de betrouwbaarheid. Die komt dus uit de vergelijking zelf, en is niet door het model verzonnen.

Een vereenvoudigde 2D-embeddingruimte: elke soort vormt een cluster van voorbeeldpunten rond een gemiddelde referentiemarkering, en een nieuwe foto wordt gekoppeld aan de dichtstbijzijnde referentie.

Het ding dat een foto of geluid omzet in een embedding heet de embedder, oftewel de trunk van het model. Daar bestaan kant-en-klare, downloadbare versies van met de juiste licenties: Perch voor geluid, BioCLIP 2 voor beelden.

Neem je een volledig kant-en-klare classifier, dan krijg je naast die trunk ook een getrainde head: de laag die de embeddings koppelt aan een vaste lijst soorten. In die head zit veruit het grootste deel van de bestandsgrootte.

Door alleen die trunk te gebruiken en er zelf een lijst met referentie-embeddings naast te zetten, hoef je dat volledige model niet binnen te halen. Bij Perch scheelt dat enorm: het hele model is zo’n 407 MB, en het overgrote deel daarvan is die head die 14.000 soorten kent. Wat overblijft is de trunk van 23 MB, met de referentiebibliotheek en de vergelijking daar zo’n 1,6 MB bovenop.

Voor beeld ligt dat anders: daar is de trunk zelf een groot netwerk, ongeveer 300 MB. Die download je één keer, en daarna werkt ook fotoherkenning volledig offline.

Er zit nog een tweede voordeel aan, dat wat minder opvalt. Omdat de head nu een bibliotheek van referentievectoren is in plaats van één grote getrainde brok, hoef ik niet iedere gebruiker die hele bibliotheek mee te geven. Een vogelaar in Nederland heeft de referenties voor de vogels van Australië niet nodig, dus de app kan de gedeelde trunk één keer meesturen en daarna alleen het regionale deel dat past bij waar je bent. Dat deel kan groeien, soort voor soort, zonder dat iemand een model opnieuw traint of opnieuw downloadt, en het houdt de download per gebruiker klein.

Niets hiervan is mijn uitvinding. Toen ik eenmaal begon te lezen, ontdekte ik dat elk onderdeel al een naam had in de literatuur. Het embed-en-vergelijk-idee is Prototypical Networks for Few-shot Learning (Snell, Swersky & Zemel, NeurIPS 2017), dat classificeert op afstand tot een klasse-prototype in plaats van een getrainde beslisgrens, en dat de auteurs zelfs op vogels hebben getest. De audio-embedder die ik gebruik, Perch 2.0 (van Merriënboer et al., Google DeepMind, 2025), omschrijft zichzelf als getraind “with self-distillation using a prototype-learning classifier”, precies dezelfde vorm. Aan de beeldkant is er een directe match in BioCLIP 2 (Gu et al., NeurIPS 2025), dat expliciet ondersteunt om te classificeren tegen een kleine support-set in plaats van een vaste getrainde head. En het idee om locatie en seizoen mee te wegen gaat terug op Presence-Only Geographical Priors (Mac Aodha, Cole & Perona, ICCV 2019), waarbij BirdNET er een productieversie van draait op eBird-data.

Het is dus allemaal bestaand, gepubliceerd werk, deels van hetzelfde team waarvan ik het model op het toestel draai. Door het zo samen te stellen krijg ik een pijplijn zonder trainingsstap, een betrouwbaarheidsscore die daadwerkelijk iets betekent, en volledige controle over de soortenlijst.

Locatie meewegen

Er is nog één signaal dat de moeite waard is: waar en wanneer de waarneming is gedaan. Veel soorten komen alleen in bepaalde regio’s of seizoenen voor, en omdat Limosa de GPS-locatie van elke waarneming vastlegt, weet de app of een kandidaat hier gewoon voorkomt of ver buiten zijn normale verspreidingsgebied valt.

Een Koereiger in een Nederlandse berm met hoog gras en bloemen
Koereiger Ardea ibis 91%
Koereiger, herkend met de AI van Limosa. Bekijk de waarneming.

Het ligt voor de hand om alles wat onwaarschijnlijk is voor het gebied uit te sluiten, maar daarmee druk je juist de dwaalgasten weg: de zeldzame vogels die ver van huis opduiken, en dat zijn vaak precies de waarnemingen waar een vogelaar het meest enthousiast over is. Locatie krijgt daarom nooit een veto. Het kan de score van een onzekere gok wat verlagen, of een waarschijnlijke soort een duwtje omhoog geven, maar een zekere match komt er altijd doorheen, hoe onwaarschijnlijk de vogel ook is. Een echte zeldzaamheid die je daadwerkelijk hebt gefotografeerd, wordt gewoon herkend.

Eén pijplijn, drie soorten media

Dezelfde pijplijn voor elk medium: foto, geluid en video gaan elk in één gedeelde embed-en-vergelijk-pijplijn, die een gerangschikte soortenlijst met betrouwbaarheid oplevert.

Omdat herkenning nu neerkomt op embedden en vergelijken, gaan foto, geluid en video allemaal door dezelfde machinerie. Geluidsherkenning draait op het toestel, dus die werkt in het veld zonder verbinding. Foto gebruikt dezelfde aanpak, zowel in de web-app als in de telefoon-app. En video kwam er bijna gratis bij zodra de andere twee er waren: een video is niet meer dan een handvol frames, dus ik neem er een paar, bereken hun embeddings en vergelijk. Dat kost een fractie van een model over de hele clip laten redeneren.

Er was geen groter of geavanceerder model voor nodig. Wat nodig was, is een referentiebibliotheek in plaats van een getrainde classifier, en een betrouwbaarheidsscore die uit de vergelijking zelf voortkomt. Dezelfde kleine embedders verwerken alle drie de soorten media, zowel op mijn server als op de telefoon.

Wil je het in actie zien? Probeer het op je eigen waarnemingen: open de web-app op app.limosa.online, of ga naar limosa.online om de app te downloaden en meer te lezen.

Dit gaat eigenlijk niet over vogels

Niets hiervan is echt vogelspecifiek. Vervang de referentiebibliotheek en dezelfde pijplijn beantwoordt de vraag “zit X in dit medium?” voor wat je maar wilt: het juiste product op een foto, een defect in een lasnaad, een bepaalde spreker in een opname. Bereken de embedding van het medium, vergelijk die met een handvol bevestigde voorbeelden, en lees de betrouwbaarheid rechtstreeks af uit de vergelijking.

Als je zoiets op een eigen probleem zou willen loslaten, hoor ik het graag. Of neem contact op als je een tweede paar ogen wilt op een model of codebase.

Limosa Software

Freelance software- & AI-ontwikkeling: web, mobiel, back-ends en de automatisering eromheen. Inclusief het werken met geodata, en een sterke focus op privacy & security. Gevestigd in Nederland, wereldwijd actief.

Verbinden

© 2026 Limosa Software. Alle rechten voorbehouden.