Projekt i bildanalys: Snakes Sofia Åberg, F98 HT-01 Handledare: Anders Heyden
1. Inledning Inom datorseende vill man ofta segmentera ut objekt som man sedan vill följa i en bildsekvens. En segmenteringsteknik som används för detta är aktiva konturer-snakes. Kortfattat kan sägas att denna teknik fungerar så att man i bilden lägger ut en kontur runt det objekt som man vill segmentera ut. Denna kontur styrs av en energifunktion som beror på snakens såväl som bildens egenskaper. Precis som fysikaliska system vill snaken minimera sin energi, vilket leder till att den sluter sig kring objektet i bilden. Denna rapport kommer i avsnitt att ge en bakomliggande teori om energifunktionen och hur denna kan minimeras. Sedan, i avsnitt 3, kommer en enkel implementering av en snake att redovisas, med tillhörande exempel.. Aktiva konturer och energifunktioner En snake är en kurva vilken man lägger ut i bilden runt det objekt som man vill segmentera ut. Denna kurva är aktiv såtillvida att den påverkas av krafter som får den att ändra sin form. Dessa krafter kan härledas ur en energifunktion som är kopplad till kurvan. Krafterna har sådan storlek och riktning att de strävar efter att minimera kurvans energi, precis som i verkliga fysikaliska system. Matematiskt representeras snaken av en parametriserad kurva v(s). v ( s) = ( x( s), y( s)), där s [ 0, 1] (1) Denna styrs av en energifunktion som kan skrivas som 1 ( E v( s)) + E ( v( s)) E ( v( s)) ) ds Esnake = inre ( bild + villkor () 0 Här är Einre den inre energin i snaken som beror på hur den är sträckt och böjd, ett mått på hur olika saker i bilden, exempelvis konturer, påverkar snaken och mått på yttre villkor som användaren har lagt på. Ebild E villkor ett Inre energin Snakens inre energi beror bara på dess form och är helt oberoende av hur bilden ser ut. Snakens vilja att minimera sin inre energi kommer att leda till att krafter verkar på den som vill dra ihop den. Om vi bara hade haft den inre energin att ta hänsyn till hade alltså snaken successivt omslutit ett mindre och mindre område. Den inre energin kan delas upp i olika delar. En del kan sägas styra de elastiska egenskaperna hos snaken varvid man kan likna den vid ett gummiband som deformeras på olika sätt. Detta energibidrag kan skrivas som
E elastisk dv = α ( s) (3) ds där α (s) kan tolkas som elasticiteten längs snaken. Den andra delen av den inre energin utgörs av böjningsenergi. Snaken liknas vid ett metallband med en viss styvhet som ska böjas till. Denna energi beror på krökningen på kurvan och kan skrivas som E böjning d v = β ( s) (4) ds där β (s) kan tolkas som styvheten längs kurvan. Bildenergi För att kunna segmentera ut ett objekt i en bild måste givetvis snaken påverkas av krafter från bilden. Bildenergin utgörs av en eller flera komponenter, exempelvis vill man kanske att snaken ska dras till kanter eller linjer. Om man vill att snaken ska dras till mörka linjer eller områden kan man definiera en linjeenergi som E linje = I( x, y) (5) där I(x, y) betecknar intensiteten i punkten (x, y). På liknande sätt kan en kantenergi definieras som gör att snaken dras till kanter, d.v.s. punkter där gradienten är stor. E kant = I( x, y) (6) Minimering av energifunktionen Att minimera energifunktionen är ett långt ifrån trivialt problem och det finns många olika tillvägagångssätt. En metod bygger på att man hela tiden tar ett litet steg i gradientens motsatta riktning (steepest-descent method). Denna har dock nackdelen att det tar väldigt lång tid innan man når ett minimum. Ett annat sätt är att så kallad dynamisk programmering där man i varje steg prövar alla möjligheter och väljer den som ger den minsta energin. Nackdelen med denna är att den är väldigt beräkningskrävande. Ett mer empiriskt sätt är att direkt ta fram de krafter som verkar på snaken och ta ett steg i denna riktning. Ett gemensamt problem för de olika metoderna är att det är svårt att bestämma viktparametrarna för de olika energislagen. Dessutom är hela problemställningen mycket känslig för brus vilket ytterligare komplicerar det hela.
3. Implementering av en snake I detta avsnitt beskrivs en implementering av en snake. Syftet med denna är att få en ökad förståelse för hur en snake fungerar och, kanske framförallt, att det verkligen fungerar. Utgångspunkten i denna implementering är att man betraktar de krafter som energifunktionen ger upphov till. När man väl vet kraften kan man ta ett steg i dess riktning och på så vis kommer förhoppningsvis energin att stegvis minimeras. När man implementerar en snake betraktar man inte hela kurvan utan ett ändligt antal punkter på denna, s.k. kontrollpunkter. Genom att diskretisera de krafter som verkar på snaken kan man beräkna den kraft som verkar på var och en av dessa punkter. Den elastiska energin på snaken ges av ekvation (3). Då kan den elastiska kraften i x-led på den i:te kontrollpunkten skrivas som: F x _ elastisk, i = K1 + 1 (( 1 ) + ( )). (7) Ett liknande uttryck gäller givetvis för kraften i y-led. Den elastiska kraften strävar efter att krympa snaken eftersom den försöker minimera avståndet mellan punkterna. Detta syns tydligt i figuren nedan. Figur1. Snaken krymper successivt under inverkan av den elastiska kraften. I ekvation (4) ser man att böjenergin beror på krökningen på kurvan. Om man disktretiserar denna kan man uttrycka kraften på den i:te kontrollpunkten som:
F K (6x 4x 4x + x x ). (8) böj _ x, i = i i+ 1 i 1 i+ + i Även här får man ett analogt uttryck för kraften i y-led. Böjkraften strävar efter att kurvan ska vara jämn och inte ha några vassa kanter. Detta illustreras i figur. Figur. Böjkraften strävar efter att ta bort vassa kanter på kurvan. När det gäller bildenergier finns det många olika saker man kan ta hänsyn till. I denna implementering har endast linje- och kantenergier tagits med. Ekvation (5) ger uttrycket för linjeenergin. Ett enkelt sätt att implementera linjekraften är att appromera denna med gradienten I( + 1, yi ) I( 1, yi ) F line, i = (9) I(, yi + 1) I(, yi 1) Om vi har en bild med konstant bildgradient borde alltså snaken röra sig odeformerad mot mörkare eller ljusare områden beroende på hur vi väljer tecken när vi definierar linjeenergin. Ett positivt tecken gör att snaken vill röra sig mot mörkare områden och ett negativt gör att den vill röra sig mot ljusare. Detta visas i figur3.
Figur3. Linjekraften gör att snaken rör sig mot det mörka området. Kantenergin given av ekvation 6 försöker binda snaken till områden med hög gradient. Kantkraften kan skrivas som I( + 1, yi ) I( 1, yi ) F kant, i = (10) I(, yi + 1) I(, yi 1) Den totala kraften som verkar på snaken fås som en sammanvägning av de olika delkrafterna. Snakens uppförande beror starkt på vilka vikter som väljs för de olika krafterna, vilket gör den väldigt känslig. Det är väldigt lätt att snaken blir instabil och helt urartar. Detta är inte bara ett problem med just denna implementeringen utan gäller helt allmänt för snakes. Hur fungerar då snaken för en riktig bild? Betrakta följande bild med blodceller, figur 4. Säg att man önskar segmentera ut en av de svarta cirklarna. Börja med att placera ut en snake runt den intressanta cellen. Kör sedan programmet ett antal interationer med lämpligt valda parametrar. Resultatet ser vi i i figur 5. Snaken lägger sig fint runt den önskade cellen.
Figur4. Snaken placeras ut runt den önskade blodcellen. Figur5. Efter ett antal intertioner har snaken segmenterat ut den önskade cellen.
Snakes används ju ofta i datorseendesammanhang när man vill tracka ett objekt, d.v.s. följa det i en bildsekvens. Antag nu att man har en bildsekvens med en bil och vill studera hur den rör sig. Kanske har man då anledning att segmentera ut navet på ett av hjulen för att sedan studera hur det rör sig. I figur 6 visas ett hjul och en initierad snake. Efter ett antal iterationer, återigen med väl valda parametrar, så har man segmenterar ut navet, se figur 7. Den här implementeringen är dock inte så bra som man kan tro. Det är svårt att välja lämpliga parametrar och den fungerar dåligt på objekt med godtycklig form. För att den ska fungera bör objekten vara elliptiska. Ändå fungerar den bra med tanke på det enkla tillvägagångssättet. Koden till programmet finns med som en bilaga till denna rapport. Figur6. Ett hjul med en initierad snake.
Figur7. Resultat efter ett antal iterationer. 4. Sammanfattning För att segmentera ut objekt i en bild kan man använda sig av snakes. En snake är en kurva som man placerar ut i bilden runt det objekt som man vill segmentera ut. Problemet att få denna kurva att sluta sig kring objektet är ett optimeringsproblem där man vill minimera en med snaken sammanhörande energifunktion. Detta problem kan lösas på många olika sätt. I denna rapport har ett sätt redovisats där man beräknar de krafter som verkar på snaken. Denna enkla modell fungerar för att segmentera ut elliptiska objekt, men den är väldigt känslig för små parametervariationer. Snakes är en relativt ny metod och används framförallt inom datorseende när man vill följa ett objekt i en bildsekvens. 5. Referenser [1] -D Deformable Template Models: A Review (Yu Zhong) http://www.dai.ed.ac.uk/cvonline/local_copies/zhong1/zhong.html [] Active or fleble contour models (Andrew Wallace och Sarah Price) http://www.dai.ed.ac.uk/cvonline/local_copies/marble/medium/snakes/snakes.htm
[3] Active Contour Models (Snakes) (David Young) http://www.dai.ed.ac.uk/cvonline/local_copies/young/vision7.html [4] Snakes: an active model (Ramani Pichumani) http://www.dai.ed.ac.uk/cvonline/local_copies/ramani1/node31.html [5] Active contour models - snakes (Milan Sonka, Vaclav Hlavac, and Roger Boyle) http://www.icaen.uiowa.edu/~dip/lecture/understanding.html [6] Implementation of Snakes (Jose Gerardo Gonzalez) http://www.cc.gatech.edu/classes/cs73_97_spring/participants/gonzalez/midterm/report/node3.html Bilaga: Programkod function [snake]=contour(snake,absgrad,im,alfa,beta,gamma,delta) K1=1; K4=0.05; step=1; nbrsnas=size(snake,); extendsnake=[snake(:,nbrsnas-1:nbrsnas) snake snake(:,1:)]; for i=1:nbrsnas Fel(:,i)=*K1*(extendsnake(:,i+1)-*extendsnake(:,i+)+extendsnake(:,i+3)); Fbend(:,i)=*K4*(6*extendsnake(:,i+)-4*extendsnake(:,i+3)- 4*extendsnake(:,i+1)+extendsnake(:,i+4)+extendsnake(:,i)); Fline(:,i)=[im(snake(1,i)+1,snake(,i))-im(snake(1,i)-1,snake(,i));im(snake(1,i),snake(,i)+1)- im(snake(1,i),snake(,i)-1)]; Fedge(:,i)=[-absgrad(snake(1,i)+1,snake(,i))+absgrad(snake(1,i)-1,snake(,i));- absgrad(snake(1,i),snake(,i)+1)+absgrad(snake(1,i),snake(,i)-1)]; if sqrt(fedge(1,i)^+fedge(,i)^)>1.e-4 Fedge(:,i)=Fedge(:,i)/sqrt(Fedge(1,i)^+Fedge(,i)^); end end Ftot=alfa*Fel-beta*Fbend-gamma*Fedge-delta*Fline; snake=round(snake+step*ftot); hold off colormap(gray(56)) image(im); hold on plot(snake(,:),snake(1,:),'-r',snake(,:),snake(1,:),'.b')