Aanleiding

OhNo is een logische mobiele puzzel waarin je cirkels aanklikt totdat ze blauw of rood zijn. Blauwe cirkels kunnen andere blauwe cirkels zien in hun eigen rij en kolom. Rode cirkels blokkeren dat zicht. De nummers op blauwe cirkels geven aan hoeveel blauwe cirkels zij uiteindelijk moeten kunnen zien.

Ik speelde het spel vaak in mijn vrije tijd en vroeg mij af of ik er een bot voor kon maken. Het doel was om de puzzel automatisch te herkennen, op te lossen en vervolgens snel genoeg in te vullen om een hoge tijd op de leaderboard te halen.

Het project sloot goed aan bij mijn minor Computer Vision and Data Science. In die periode werkte ik veel met beeldverwerking in Python, zoals het filteren van onderdelen uit foto's op basis van kleur, vorm en andere visuele eigenschappen.

Spelregels

Blauwe cirkels kijken in hun rij en kolom

Rode cirkels blokkeren het zicht

Getallen tonen
zichtbare buren

23131

Deze 2 mist nog twee blauwe cirkels

23131

Deze twee moeten blauw worden

23131

Voor de bot moest ik de regels vertalen naar programmeerbare constraints. Een onbekende cirkel kan blauw of rood worden. Als een blauwe cirkel te weinig zichtbare blauwe cirkels heeft, moeten sommige onbekende posities blauw worden. Als het aantal al klopt, moeten de overige zichtbare plekken juist rood worden om extra blauwe cirkels te voorkomen.

Beeldherkenning

De eerste stap was het herkennen van de cirkels op het scherm. Daarvoor heb ik de cirkels eerst geisoleerd door te filteren op hun kleuren. De blauwe, rode en lege cirkels hebben herkenbare kleurwaarden, waardoor ze uit de screenshot gehaald konden worden zonder dat de rest van de app belangrijk was.

Na het kleurfilteren heb ik blob detectie gebruikt om de posities van de cirkels te bepalen. De gevonden cirkelposities zijn daarna omgezet naar een grid. Hiervoor heb ik een bucket-sort-achtige aanpak gebruikt: posities worden in rijen en kolommen gegroepeerd op basis van hun schermcoordinaten.

Als laatste stap in de herkenning heb ik OCR gebruikt om de nummers op de blauwe cirkels uit te lezen. Daarna wist de bot waar de cirkels stonden en welke regels bij de genummerde blauwe cirkels hoorden.

Algoritme

Na het herkennen van het bord wordt de puzzel als datastructuur opgebouwd. Iedere cel krijgt een positie, een kleurstatus en eventueel een nummer. Vanuit die structuur kan het algoritme per blauwe cirkel bepalen welke andere cirkels zichtbaar zijn totdat een rode cirkel of de rand van het bord bereikt wordt.

Het oplossen bestaat uit het herhaald toepassen van logische regels. Wanneer een genummerde blauwe cirkel nog exact genoeg onbekende zichtposities heeft om aan het nummer te voldoen, kunnen die plekken blauw worden. Wanneer het nummer al gehaald is, kunnen de overgebleven zichtposities rood worden.

Deze aanpak paste goed bij mijn interesse in algoritmes. De beeldherkenning leverde de input op, maar daarna moest de herkende data betrouwbaar worden vertaald naar puzzelregels en automatische beslissingen.

Demo

Demo van de OhNo puzzelbot die een puzzel automatisch invult
De demo laat zien hoe de bot de puzzel herkent, oplost en daarna met een autoclicker de juiste cirkels invult. De opname is bewust vertraagd, zodat zichtbaar blijft wat er gebeurt.

Nadat de oplossing is bepaald, gebruikt de bot een autoclicker om de gevonden keuzes in de mobiele app toe te passen. Daardoor wordt het project een volledige pipeline: van screenshot naar grid, van grid naar oplossing en van oplossing naar automatische invoer.

De cirkels worden geplaatst in de volgorde waarin de solver de puzzel oplost. In de vertraagde demo is die volgorde goed te volgen; op volledige snelheid duurde de invoer minder dan 1 seconde. Daarmee sta ik nu op plaats 3 van de leaderboard.

Wat ik geleerd heb

  • Hoe kleurfiltering en blob detectie gebruikt kunnen worden om onderdelen uit een screenshot te herkennen.
  • Hoe je losse schermcoordinaten omzet naar een bruikbaar grid voor verdere logica.
  • Dat OCR pas nuttig wordt wanneer de input goed genoeg is voorbereid en geisoleerd.
  • Hoe je spelregels kunt vertalen naar constraints die een algoritme automatisch kan toepassen.
  • Hoe computer vision, algoritmiek en automatisering elkaar kunnen versterken in een klein maar compleet project.

Links en downloads

Andere projecten