Vraag Beeldverwerking: verbetering van algoritmen voor herkenning van 'Coca-Cola Can'


Een van de meest interessante projecten waar ik de afgelopen jaren aan heb gewerkt, was een project over afbeelding verwerken. Het doel was om een ​​systeem te ontwikkelen om Coca-Cola te herkennen 'blikjes' (merk op dat ik het woord 'blikjes' benadruk, je zult zien waarom in een oogwenk). U kunt hieronder een voorbeeld bekijken, met het blikje herkend in de groene rechthoek met schaal en rotatie.

Template matching

Enkele beperkingen van het project:

  • De achtergrond kan erg luidruchtig zijn.
  • De kan zou kunnen hebben schaal of omwenteling of zelfs oriëntatie (binnen redelijke grenzen).
  • Het beeld kan enigszins vervaagd zijn (contouren zijn mogelijk niet helemaal recht).
  • Er zouden Coca-Cola-flessen in de afbeelding kunnen zijn en het algoritme zou alleen de kan!
  • De helderheid van de afbeelding kan erg variëren (u kunt dus niet te veel vertrouwen op kleurdetectie).
  • De kan kan gedeeltelijk aan de zijkanten of in het midden worden verborgen en mogelijk gedeeltelijk achter een fles worden verborgen.
  • Er kan geen zijn kan helemaal in de afbeelding, in welk geval je niets moest vinden en een bericht moest schrijven waarin dat stond.

Dus je zou kunnen eindigen met lastige dingen zoals deze (in dit geval had mijn algoritme totaal falen):

Total fail

Ik heb dit project een tijdje geleden gedaan en had veel plezier ermee, en ik had een behoorlijke implementatie. Hier zijn enkele details over mijn implementatie:

Taal: Gedaan in C ++ met OpenCV bibliotheek.

Pre-processing: Voor de beeldvoorverwerking, d.w.z. het transformeren van het beeld in een meer ruwe vorm om aan het algoritme te geven, gebruikte ik 2 methoden:

  1. Veranderend kleurdomein van RGB in HSV en filteren op basis van "rode" tint, verzadiging boven een bepaalde drempel om oranje-achtige kleuren te vermijden, en lage waarden filteren om donkere tonen te voorkomen. Het eindresultaat was een binaire zwart-witafbeelding, waarbij alle witte pixels de pixels zouden voorstellen die met deze drempel overeenkomen. Uiteraard is er nog steeds veel rotzooi in het beeld, maar dit vermindert het aantal dimensies waarmee je moet werken. Binarized image 
  2. Ruisfiltering met mediane filtering (waarbij de gemiddelde pixelwaarde van alle buren wordt ingenomen en de pixel met deze waarde wordt vervangen) om ruis te verminderen.
  3. Gebruik makend van Canny Edge Detection Filter om de contouren van alle items na 2 precedent-stappen te krijgen. Contour detection

Algoritme: Het algoritme zelf dat ik heb gekozen voor deze taak is overgenomen deze geweldig boek over feature-extractie en genoemd Gegeneraliseerde Hough-transformatie (behoorlijk verschillend van de reguliere Hough-transformatie). Het zegt in feite een paar dingen:

  • Je kunt een object in de ruimte beschrijven zonder de analytische vergelijking te kennen (wat hier het geval is).
  • Het is bestand tegen beeldvervormingen zoals schaling en rotatie, omdat het in principe uw beeld zal testen voor elke combinatie van schaalfactor en rotatiefactor.
  • Het maakt gebruik van een basismodel (een sjabloon) dat het algoritme zal "leren".
  • Elke pixel die in de contourafbeelding blijft, stemt op een andere pixel die naar verluidt het centrum (in termen van zwaartekracht) van uw object is, op basis van wat het heeft geleerd van het model.

Uiteindelijk krijg je een hittekaart van de stemmen, bijvoorbeeld hier stemmen alle pixels van de contour van het blik op het zwaartekrachtcentrum, dus je hebt veel stemmen in dezelfde pixel die overeenkomt met de in het midden en ziet een piek in de warmtekaart zoals hieronder:

GHT

Als je dat eenmaal hebt, kan een eenvoudige op drempelwaarde gebaseerde heuristiek je de locatie van de middelste pixel geven, waaruit je de schaal en rotatie kunt afleiden en dan je kleine rechthoek eromheen plotten (uiteindelijke schaal en rotatiefactor zullen uiteraard relatief zijn aan jouw originele sjabloon). In theorie tenminste ...

resultaten: Hoewel deze aanpak in de basishulzen werkte, ontbrak het op sommige gebieden ernstig:

  • Het is extreem langzaam! Ik benadruk dit niet genoeg. Bijna een volledige dag was nodig om de 30 testafbeeldingen te verwerken, uiteraard omdat ik een zeer hoge schaalfactor had voor rotatie en translatie, omdat sommige blikken erg klein waren.
  • Het was volledig verloren toen flessen in de afbeelding stonden en vond om de een of andere reden bijna altijd de fles in plaats van het blikje (misschien omdat flessen groter waren, dus meer pixels hadden, dus meer stemmen)
  • Fuzzy-afbeeldingen waren ook niet goed, omdat de stemmen op willekeurige locaties in het midden in pixels eindigden en zo eindigden met een zeer luidruchtige warmtekaart.
  • In-variantie in translatie en rotatie werd bereikt, maar niet in oriëntatie, wat betekent dat een blik dat niet direct tegenover het cameragebject stond, niet werd herkend.

Kun je me helpen mijn te verbeteren specifiek algoritme, gebruiken exclusief OpenCV functies, om het probleem op te lossen vier specifiek problemen genoemd?

Ik hoop dat sommige mensen er ook iets van zullen leren, ik vind immers dat niet alleen mensen die vragen stellen, moeten leren. :)


1390
2018-04-16 04:23


oorsprong


antwoorden:


Een alternatieve benadering zou zijn om features (keypoints) uit te pakken met behulp van de schaal-invariante kenmerktransformatie (SIFT) of Versnelde Robuuste functies (SURFEN).

Het is geïmplementeerd in OpenCV 2.3.1.

Je kunt een leuk codevoorbeeld vinden met behulp van functies in Features2D + Homografie om een ​​bekend object te vinden

Beide algoritmen zijn onveranderlijk voor schaling en rotatie. Omdat ze werken met functies, kun je het ook aan afsluiting (zolang er voldoende keypoints zichtbaar zijn).

Enter image description here

Afbeeldingsbron: voorbeeld van de handleiding

De verwerking duurt enkele honderden ms voor SIFT, SURF is iets sneller, maar niet geschikt voor real-time toepassingen. ORB gebruikt FAST, wat zwakker is met betrekking tot rotatie-invariantie.

De originele papieren


563
2018-04-16 05:17



Om dingen te versnellen, zou ik voordeel halen uit het feit dat je niet wordt gevraagd om een ​​willekeurig beeld / object te vinden, maar specifiek een met het Coca-Cola-logo. Dit is belangrijk omdat dit logo zeer onderscheidend is en een kenmerkende, schaal-invariante handtekening in het frequentiedomein moet hebben, met name in het rode kanaal van RGB. Dat wil zeggen, het afwisselend patroon van rood-naar-wit-tegen-rood ontmoet door een horizontale scanlijn (getraind op een horizontaal uitgelijnd logo) zal een onderscheidend "ritme" hebben wanneer het door de centrale as van het logo gaat. Dat ritme "versnelt" of "vertraagt" met verschillende schalen en oriëntaties, maar blijft evenredig equivalent. Je zou een paar dozijn dergelijke scanlines kunnen identificeren / definiëren, zowel horizontaal als verticaal door het logo en verschillende diagonaal, in een starburst-patroon. Noem dit de 'handtekening scanlijnen'.

Signature scan line

Zoeken naar deze handtekening in de doelafbeelding is een kwestie van het scannen van de afbeelding in horizontale stroken. Zoek naar een hoge frequentie in het rode kanaal (dit geeft aan dat je van een rood naar een wit gebied bent gegaan) en als je eenmaal hebt gevonden, kijk dan of dit wordt gevolgd door een van de frequentieritmes die in de trainingssessie zijn geïdentificeerd. Zodra een overeenkomst is gevonden, weet u meteen de oriëntatie en locatie van de scanregel in het logo (als u die dingen bijhoudt tijdens de training), zodat het onbelangrijk is om de grenzen van het logo te bepalen.

Ik zou verrast zijn als dit geen lineair-efficiënt algoritme was, of bijna niet. Het adres is duidelijk niet van toepassing op uw can-bottle-discriminatie, maar u hebt tenminste uw logo's.

(Update: voor flesherkenning zou ik op zoek gaan naar cola (de bruine vloeistof) naast het logo - dat wil zeggen, binnen de fles. Of, in het geval van een lege fles, zou ik zoeken naar een pet die altijd dezelfde basisvorm, grootte en afstand van het logo hebben en meestal allemaal wit of rood zijn. Zoeken naar een eliptische vorm in massieve kleur waarbij een dop moeten zijn, ten opzichte van het logo. Natuurlijk niet foutloos, maar je doel hier zou moeten zijn om de gemakkelijk degenen snel.)

(Het is een paar jaar geleden dat ik mijn beeldverwerkingsdagen heb gedaan, dus hield ik deze suggestie op een hoog niveau en conceptueel. Ik denk dat het enigszins een beeld kan vormen van hoe een menselijk oog zou kunnen werken - of op zijn minst hoe mijn hersenen dat doen!)


331
2018-04-17 21:06



Leuk probleem: toen ik naar je flessenafbeelding keek, dacht ik dat het ook een blik was. Maar als een mens, wat ik deed om het verschil te vertellen, is dat ik toen merkte dat het ook een fles was ...

Dus, om blikjes en flessen uit elkaar te houden, hoe zit het met het eenvoudigweg scannen van flessen eerst? Als u er een vindt, maskeert u het label voordat u op zoek gaat naar blikken.

Niet te moeilijk om te implementeren als je al blikjes doet. Het echte nadeel is dat het uw verwerkingstijd verdubbelt. (Maar vooruit denken aan toepassingen in de echte wereld, je zult uiteindelijk toch flessen willen kopen ;-)


132
2018-04-16 05:03



Is het niet moeilijk, zelfs voor mensen om een ​​onderscheid te maken tussen een fles en een blikje in de tweede afbeelding (op voorwaarde dat het transparante gedeelte van de fles is verborgen)?

Ze zijn bijna hetzelfde behalve een heel klein gebied (dat wil zeggen, de breedte aan de bovenkant van het blik is een beetje klein terwijl de verpakking van de fles overal dezelfde breedte heeft, maar een kleine wijziging toch?)

Het eerste dat me te binnen schoot, was om te controleren op de rode bovenkant van de fles. Maar het is nog steeds een probleem, als er geen dop voor de fles is of als deze gedeeltelijk verborgen is (zoals hierboven vermeld).

Het tweede ding dat ik dacht was over de transparantie van fles. OpenCV heeft een aantal werken over het vinden van transparante objecten in een afbeelding. Controleer de onderstaande links.

Kijk in het bijzonder om te zien hoe nauwkeurig ze glas detecteren:

Zie hun implementatieresultaat:

Enter image description here

Ze zeggen dat het de implementatie van het papier is "Een geodetisch actief contourkader voor het vinden van glas" door K. McHenry en J. Ponce, CVPR 2006.

Misschien helpt het een beetje, maar het probleem doet zich opnieuw voor als de fles is gevuld.

Dus ik denk dat je hier kunt zoeken naar het transparante lichaam van de flessen eerst of naar een rood gebied dat verbonden is met twee transparante objecten aan de zijkant, wat duidelijk de fles is. (Als u idealiter werkt, ziet een afbeelding er als volgt uit.)

Enter image description here

Nu kunt u het gele gebied verwijderen, dat wil zeggen het etiket van de fles en uw algoritme uitvoeren om het blikje te vinden.

Hoe dan ook, deze oplossing heeft ook verschillende problemen, zoals in de andere oplossingen.

  1. Het werkt alleen als uw fles leeg is. In dat geval moet u zoeken naar het rode gebied tussen de twee zwarte kleuren (als de Coca Cola-vloeistof zwart is).
  2. Een ander probleem als transparant gedeelte wordt bedekt.

Maar goed, als er geen van de bovenstaande problemen op de foto's zijn, lijkt dit op een betere manier.


101
2018-04-18 23:02



ik hou echt van Darren Cook's en uitleg van stapelaars voor dit probleem. Ik was in het midden van het gooien van mijn gedachten in een commentaar op die, maar ik geloof dat mijn aanpak te antwoord-vormig is om hier niet te vertrekken.

Kort samengevat hebt u een algoritme geïdentificeerd om te bepalen of een Coca-Cola-logo aanwezig is op een bepaalde locatie in de ruimte. U probeert nu, voor willekeurige oriëntaties en willekeurige schaalfactoren, een heuristiek te bepalen die geschikt is om Coca-Cola te onderscheiden blikjes van andere objecten, inclusief: flessen, billboards, advertenties, en Coca-Cola parafernalia allemaal geassocieerd met dit iconische logo. Je hebt niet veel van deze extra gevallen in je probleemstelling genoemd, maar ik denk dat ze van vitaal belang zijn voor het succes van je algoritme.

Het geheim hier is het bepalen van welke visuele functies een kan bevat of, via de negatieve ruimte, welke functies aanwezig zijn voor andere coloflessen die niet aanwezig zijn voor blikjes. Daartoe het huidige topantwoord schetst een basisaanpak voor het selecteren van "kan" als en alleen als "fles" niet wordt geïdentificeerd, hetzij door de aanwezigheid van een kroonkurk, vloeistof of andere soortgelijke visuele heuristieken.

Het probleem is dat dit kapot gaat. Een fles kan bijvoorbeeld leeg zijn en de aanwezigheid van een dop missen, wat leidt tot een vals positief resultaat. Of, het zou kunnen zijn een gedeeltelijke fles met extra functies verminkt, wat opnieuw leidt tot valse detectie. Onnodig te zeggen dat dit niet elegant is en ook niet effectief voor onze doeleinden.

Hiertoe lijken de meest correcte selectiecriteria voor blikken de volgende te zijn:

  • Is de vorm van het object silhouet, zoals je schetste in je vraag, correct? Zo ja, +1.
  • Als we aannemen dat er sprake is van natuurlijk of kunstmatig licht, detecteren we dan een chromen contour op de fles die aangeeft of deze van aluminium is gemaakt? Zo ja, +1.
  • Bepalen we dat het spiegelende eigenschappen van het object zijn correct, ten opzichte van onze lichtbronnen (illustratieve videolink op lichtbron detectie)? Zo ja, +1.
  • Kunnen we andere eigenschappen over het object bepalen die het als een blik identificeren, inclusief, maar niet beperkt tot, de topologische beeldverschuiving van het logo, de oriëntatie van het object, de plaatsing naast elkaar van het object (bijvoorbeeld op een vlak oppervlak zoals een tafel of in de context van andere blikjes) en de aanwezigheid van een treklipje? Zo ja, voor elk, +1.

Uw classificatie kan er dan als volgt uitzien:

  • Voor elke kandidaat-match tekent u een grijze rand als de aanwezigheid van een Coca-Cola-logo werd gedetecteerd.
  • Teken voor elke combinatie +2 een rode rand.

Hiermee wordt de gebruiker visueel zichtbaar gemaakt wat er is gedetecteerd, met de nadruk op zwakke positieven die mogelijk correct worden gedetecteerd als verminkte blikken.

De detectie van elke eigenschap heeft een heel andere tijd- en ruimtecomplexiteit en voor elke benadering een snelle doorgang http://dsp.stackexchange.com is meer dan redelijk om het meest correcte en meest efficiënte algoritme voor uw doeleinden te bepalen. Mijn bedoeling hier is puur en eenvoudig om dat te benadrukken detecteren of iets een blik is door een klein deel van de kandidaat-detectieruimte ongeldig te maken is niet de meest robuuste of effectieve oplossing voor dit probleem, en idealiter moet u dienovereenkomstig de juiste acties ondernemen.

En hey, gefeliciteerd de Hacker News-posting! Over het algemeen is dit een vrij geweldige vraag die de publiciteit waardig is. :)


41
2018-04-22 22:56



Kijken naar vorm

Neem een ​​glimlach in de vorm van het rode gedeelte van de bus / fles. Let op hoe het blik aan de top iets smaller wordt, terwijl het flesetiket recht is. U kunt onderscheid maken tussen deze twee door de breedte van het rode gedeelte over de lengte ervan te vergelijken.

Kijken naar hoogtepunten

Een manier om onderscheid te maken tussen flessen en blikjes is het materiaal. Een fles is gemaakt van plastic, terwijl een blik is gemaakt van aluminium metaal. In voldoende goed verlichte situaties zou het kijken naar de speculariteit een manier zijn om een ​​flessenetiket van een bliketiket te vertellen.

Voor zover ik kan nagaan, zou een mens zo het verschil tussen de twee soorten labels kunnen onderscheiden. Als de lichtomstandigheden slecht zijn, is er ongetwijfeld enige onzekerheid in het onderscheiden van de twee. In dat geval zou u de aanwezigheid van de transparante / doorzichtige fles zelf moeten kunnen detecteren.


35
2018-04-16 08:31



Neem een ​​kijkje op Zdenek Kalal's Predator-tracker. Het vereist enige training, maar het kan actief leren hoe het gevolgde object naar verschillende oriëntaties en schalen kijkt en doet het in realtime!

De broncode is beschikbaar op zijn site. Het is in MATLAB, maar misschien is er al een Java-implementatie gedaan door een communitylid. Ik heb het tracker-gedeelte van TLD met succes opnieuw geïmplementeerd in C #. Als ik het me goed herinner, gebruikt TLD Ferns als de keypoint-detector. Ik gebruik in plaats daarvan SURF of SIFT (al voorgesteld door @stacker) om het object opnieuw te genereren als het door de tracker is verloren. De feedback van de tracker maakt het gemakkelijk om in de loop van de tijd een dynamische lijst met sift / surf-sjablonen te bouwen die het met de tijd mogelijk maken om het object met een zeer hoge precisie te herstellen.

Als je geïnteresseerd bent in mijn C # -implementatie van de tracker, vraag het dan gerust.


31
2018-04-17 20:56



Als je niet beperkt bent tot alleen een camera die niet in een van je beperkingen zat, kun je misschien overstappen op het gebruik van een afstandsensor zoals de Xbox Kinect. Hiermee kunt u op diepte en kleur gebaseerde gekoppelde segmentatie van de afbeelding uitvoeren. Dit zorgt voor een snellere scheiding van objecten in de afbeelding. U kunt dan ICP-overeenkomsten of soortgelijke technieken gebruiken om zelfs de vorm van het blik aan te passen in plaats van alleen de omtrek of kleur ervan en gezien het feit dat het cilindrisch is, kan dit een geldige optie zijn voor elke oriëntatie als u een eerdere 3D-scan van het doelwit hebt. Deze technieken zijn vaak vrij snel, vooral wanneer gebruikt voor een dergelijk specifiek doel dat uw snelheidsprobleem zou moeten oplossen.

Ook zou ik kunnen suggereren, niet noodzakelijkerwijs voor nauwkeurigheid of snelheid, maar voor de lol kun je een getraind neuraal netwerk gebruiken op je hue-gesegmenteerde afbeelding om de vorm van het blik te identificeren. Deze zijn erg snel en kunnen vaak tot 80/90% nauwkeurig zijn. Trainen zou een beetje een lang proces zijn, omdat je het blik in elke afbeelding handmatig moet identificeren.


25
2018-04-16 04:54