Matematiska institutionen, LTH, 20 november 2003 Flervariabelanalys, inriktning bildbehandling, datorövning 1 Laborationen består av två delar. I den första använder vi det numeriska beräkningsprogrammet Matlab och i den andra använder vi beräkningsprogrammet Maple som stöder symbolisk beräkningar som till exempel beräkning av partiell derivata av funktioner av flera variabler. 1 Matlab I vissa versioner kan man inte skriva in tecknen [ och ], vilka används ganska mycket i matlab. Du kan få in dem i matlab tex genom att skriva [ ] i ditt shell och sen göra cut and paste in i matlab-fönstret. Olika bildformat Precis som för videofilmer och musik finns det många lagringssätt för bilder. Även om man begränsar sig till digital lagring finns det ett otal olika format. Vi skall nu se på några vanliga sådana. Börja med att studera en bildfil som heter kalle.pgm till din katalog. Bilden är lagrad i asciiformat. Den är alltså fullt läsbar även för människor, även om det inte är så lätt att på så sätt se vad bilden föreställer. Titta på filen genom kommandot: less kalle.pgm avsluta programmet med q. Vad tror du att de fyra första raderna betyder? Vad betyder resten av datan? Det finns en uppsjö av rutiner som konverterar mellan olika bildformat. Ett mycket bekvämt sätt att konvertera mellan olika bildformat är med hjälp av programmet xv. Att visa en bild med programmet xv Titta på filen kalle.pgm genom att skriva ~fredrik/xv kalle.pgm & När du är nöjd kan du gå ur genom att skriva q i bildfönstret. Kopiera filen mkalle.gif till din katalog. Bilden är lagrad på gif-format, vilket inte är särskilt läsbart för människor, men ger filer av mindre storlek. Se på filen med less mkalle.gif 1
Filen är benär till skillnad från kalle.pgm. Jämför filernas storlek genom kommandot ls -l Skriv sedan ~fredrik/xv mkalle.gif & så syns förhoppningsvis bilden på skärmen (fast inte särskilt tydligt). Lägg märke till att du kan avläsa enskilda pixlars koordinater och värde bara genom att peka på dem och trycka ned vänsterknappen. Tryck med högerknappen någonstans i xv-s bildfönster så öppnas xv-s kontrollpanel. Här finns en hel del funktioner. Bland annat kan man spara bilden på olika format genom att trycka på save-knappen. Vi kommer att använda Matlab en hel del i våra laborationer. Det finns en Matlabrutin som kan läsa in bilder, men bara om de är sparade på pgm-format. Spara bilden i pgm-format på din katalog, genom att välja pbm (ascii) och greyscale i xv-s kontrollpanel xv save. Man kan också klippa ut en del av bilden genom att först markera en fyrkant av bilden med mittenknappen och sen trycka på crop-knappen i kontrollpanelen. Förstora sedan bilden genom att trycka på Image Size och sen Double Size i kontrollpanelen några gånger. Notera speciellt att xv använder pixelreplikering när den förstorar bilder. Gråskaletransformationer i xv Labhandledaren på bilden är mycket för mörk och har dålig kontrast. Tryck på Windows och sen Color Editor i kontrollpanelen så öppnas färgpanelen. I delfönstret intensity kontrollerar man hur olika gråskalenivåer ska ritas på skärmen. Testa vad som händer genom att ändra i detta delfönster. Ta tag i de små boxarna med vänster musknapp och och drag! Testa också histogramutjämning med knappen HistEq. Vad svarar grafen i intensityfönstret nu emot? Testa även knappen Norm. Hur tror du att den fungerar? Du kan avsluta xv genom att trycka på quit i kontrollpanelen. Gör det nu. Konversion till Matlab Matlab är en programmeringsmiljö framförallt för numeriska matrisberäkningar. En bild kan ju betraktas som en matris där varje element svarar mot en pixel. Starta matlab genom att skriva matlab & För laborationerna finns ett matlab-kommando readpgm som läser in bilder i pgmformat till matriser. Skriv: >> help readpgm så får du mer information. Ladda nu in en bild, t ex genom: >> kalle=readpgm( kalle.pgm ) 2
Genom att sätta semikolon efter kommandot slipper du se Matlab skriva ut resultatet, som i det här fallet blir en ganska stor matris. Ladda även in en lite mindre bild. >> tolv=[1 2 3;4 2 6;7 8 7;2 11 10] Du kan ta reda på vilka matriser du för tillfället har inlagda i Matlab och hur stora de är med kommandot >> whos Att titta på en bild inifrån Matlab Som nämnts i introduktionen till laborationerna så använder sig våra maskiner av färgtabeller istället för att låta pixelvärdena direkt styra intensiteten i varje bildpunkt. I Matlab kan man specificera dessa tabeller själv. Prova följande kommandon: >> map=(0:11) /11*[1 1 1] >> colormap(map) >> image(tolv) Den första raden skapar en färgpalett med 12 olika färger. Varje rad har tre element som styr andelen rött, grönt respektive blått. I detta fall valdes den första som helt svart och de övriga i gråskalenivå upp till den tolfte som är helt vit. Den andra raden talar om för Matlab att vi vill använda paletten map. Skriv gärna >> help colormap Den tredje är ett kommando för att visa matrisen tolv som en bild. Skriv gärna >> help image för att få mer information. Vad händer om du nu skriver >> colormap((0:11) /11*[1 0 0]) Ersätt [1 0 0] med [0 1 0] och [0 0 1]. Prova även >> colormap(rand(12,3)) några gånger. Titta nu på matrisen kalle med kommandona >> image(kalle) >> colormap(gray(255)) Hur fungerar gray? Vilka andra fördefinierade färgskalor finns? Observera att bilderna visas med origo i övre vänstra hörnet. Det finns andra rutiner i Matlab för att illustrera en matris. Rita upp kalle med 3
>> mesh(kalle) Matrisen/bilden ritas nu verkligen som ett grånivålandskap där pixelelementets värde styr både höjd och gråskala. Om du inte får fram någon graf så prova istället med >> meshc(kalle) Du ser nu landskapet lite snett uppifrån. Kommandot view ändrar synvinkeln. Prova >> view([-20 50]) >> view([-190 70]) >> view([0 90]) Observera att mesh använder ett koordinatsystem med origo längst ner till vänster. Vänd nu bilden rätt. Det finns ett lokalt kommado show som fungerar ungefär som image. Genom kommandot >> show(kalle) skapas ett nytt fönster med bilden kalle i ungefär samma storlek som den skulle haft i xv, d v s en pixel på skärmen motsvarar en pixel i kalle. Du kan stänga sådana fönster med >> close Nivåkurvor Ladda in bilden på Lena och titta på den. >> lena = readpgm( lena.pgm ); >> imagesc(lena) >> colormap gray Vi tolkar ju bilden som ett grånivålandskap. Det ger att finns nivåkurvor. Rita ut dessa med contour. Vad gör kommandot axis ij? >> contour(lena); >> axis ij Om det finns skrivare i närheten så skriv ut bilden på papper och rita in gradienten på några ställen i bilden. Hur hänger gradienten och nivåkurvorna ihop? Kantdetektering Man kan använda sig av partiell derivata i x och y-led för att detektera kanter. Vi tänker oss här att x-axeln pekar åt höger i bilden och y-axeln nedåt. Partiell derivata detekterar kanter i en av axelriktningarna. Absolutbeloppet at gradienten däremot detekterar kanter i alla riktningar. Funktionen kantdetektering ger som resultat tre bilder. Vilken bild är resultatet av partiell derivata i x-led, y-led och gradienten? 4
>> [a,b,c] = kantdetektering(lena); Bilderna kan göras binära genom att skriva >> abinar = a < troskel; där variabeln troskel väljs lämpligt. Prova med lite olika värden för bästa resultet. Upprepa trösklingen för bilerna b och c också. Titta på den binära bilden med tex imagesc. Skala om bilder Ibland vill man förstora eller förminska en bild. Tänk efter vilka problem som uppkommer om du vill göra gatubilden 3.72 gånger bredare och 4.1 gånger högre. Hur ska man bestämma de nya pixelvärdena? Det finns många olika sätt att göra det på. Tre sådana finns implementerade i kommandot imresize. Läs mer i >> help imresize Optionerna nearest (som är default ), bilinear och bicubic väljer mellan respektive pixelreplikering, bilineär interpolation och kubisk splineinterpolation. Till c optionen kan även en parameter anges, 0.5 till 1.0 brukar bli bra. Förstora kalle med de olika metoderna och jämför, t ex med >> show(kalle) >> show(imresize(kalle,1.5)); >> show(imresize(kalle,[200 100], bilinear )); >> show(imresize(kalle,[200 100], bicubic )); Generera nu följande bild i Matlab. >> prickig=zeros(30,40); >> prickig(2:2:30,2:2:40)=256*ones(15,20); >> show(prickig) Resultatet blir kanske inte riktigt vad man väntar. Anledningen är interferens mellan pixlarna på datorskärmen och pixlarna i bildfilen. Förstora bildfönstret med musen och se vad som händer! Skala nu bilden prickig med en faktor 1.6 (med imresize) med de tre olika metoderna ovan. Vad händer med skarpa kanter i de olika fallen? Är någon metod klart sämst eller klart bäst, eller kan de tänkas vara bra i olika fall? Hur skulle en algoritm fungera som förstorade en bild riktigt snyggt? 5
2 Maple Allmänt om Maple Maple är ett mycket mångsidigt program, och man kan ägna mycket tid åt att utforska dess användningsmöjligheter. Dess mångsidighet gör det samtidigt svårare att använda än tex Matlab. Liksom de flesta programpaket uppgraderas Maple relativt ofta. Versionerna skiljer sig något åt, och anvisningarna nedan är gjorda för Maple6. Mer information om Maple än vad som ryms i denna korta introduktion kan man finna i det inbyggda hjälpsystemet samt i en stort antal skrifter och böcker. På institutionen har utgivits en utförligare introduktion (mest avsedd för envariabelanalys) Andersson Nilsson, Maplehandboken (1995). Den beskriver version MapleVR3 och finns att hämta via http://www.maths.lth.se/matematiklu/personal/goran_a/maple/mh.html. Där finns också länkar till mer information. Starta Maple på UNIX-system genom att ge kommandot maple -x, eller, på vissa maskiner, xmaple &. På Windows-maskiner brukar finnas en Maple-ikon. Placera Maplefönstret, som strax kommer upp, på lämpligt ställe. Man går ur Maple genom att välja Exit i File-menyn. Behöver man avbryta någon process kan man använda en stop-knapp på menyraden. Hjälp Maple har ett omfattande inbyggt hjälpsystem. Om man klickar på Help i menyraden, så får man tillgång till hjälpfunktioner. Dessa fungerar på lite olika sätt, beroende på vilken Mapleversion man kör, men brukar vara lätta att använda. Plocka fram hjälpen för exp och constant. Observera i det senare fallet särskilt de symboliska konstanterna I, Pi och infinity. Dessa är reserverade namn, som inte får användas till annat. Observera att Maple skiljer på stora och små bokstäver. Talet e skrivs exp(1). Man kan också få hjälp genom att skriva ett sökord föregånget av ett frågetecken, t ex?exp,?inifcn. I slutet på varje hjälptext finns exempel och hänvisningar till andra kommandon som kan vara av nytta. Grundläggande kommandon och aritmetiska beräkningar I Maplefönstret hittar du en prompt >, som betyder att Maple väntar på ett kommando. Skriv in 7+5; och tryck på Enter, så utförs summationen. Observera att varje kommando till Maple måste avslutas med ett semikolon ;, utan detta händer ingenting. Detta gör att man kan slå in långa formler som inte får plats på en rad. Skriver man kolon : så utförs operationen, men resultatet kommer inte upp på skärmen. Kontrollera att Maple kan fungera som en vanlig räknedosa. Prova i tur och ordning 2-3*5; 1/2+1/3; sqrt(4)*sqrt(3); Observera att Maple ger exakta svar, inte närmevärden. 6
Närmevärden erhålles genom kommandot evalf;, som står för evaluate using floating point arithmetic. För att få ett närmevärde för den senast utförda beräkningen (2 3 i vårt fall) kan man skriva evalf(%); Man kan naturligtvis också skriva evalf(sqrt(4)*sqrt(3));. På samma sätt kan resultatet av den näst senaste beräkningen åberopas genom %%, etc. En annan praktisk detalj i Maple är möjligheten att gå tillbaka till gamla kommandon på skärmen med pil-upp och pil-ner tangenterna, ändra i kommandona och utföra dem på nytt. Man kan också använda musen för att snabbt flytta sej till olika delar av skärmen. Testa genom att gå tillbaka till kommandot 1/2+1/3; och gör en annan bråkberäkning genom att ändra siffror. När det gäller kommandot evalf så kan man ur hjälpfunktionen, som nås med?evalf, utläsa att man genom ett andra argument kan ange med hur många siffror man vill ha svaret. Använd detta för att få ett värde på π med 1000 decimaler, evalf(pi,1000);. Variabler Maple kan inte bara räkna med tal utan också med variabler och med funktioner. Detta gör att ett Maplesystem blir större och ofta mer invecklat att programmera än ett vanligt programmeringspråk, men också oerhört mycket mera kraftfullt. Ge kommandot (x+1)^3;. Maple svarar med samma sak. Som svar på expand(%); så utvecklar Maple uttrycket enligt binomialteoremet. Prova även med expand((a-b)*(a+b)); expand(x*(x+1)*(x+2)*(x+3)); expand(cos(x+y)); Som bekant vill man ofta gå åt andra hållet, och faktoruppdela ett givet uttryck. Detta görs med kommandot factor. Prova detta på de polynomuttryck som du fick ovan. Ett annat kommando för förenkling är simplify. Prova detta genom att skriva simplify(1/(x-1)+1/(x+1)); Maple gör inte alltid det man önskar. Ett annat kommando man kan ha nytta av för att göra omskrivningar är normal. Tilldelningssatser Man kan tilldela en variabel ett värde, numeriskt eller symboliskt. Tilldelningssymbolen är liksom i Pascal och Simula :=. Prova med x:=2;. Kommandot x; ger nu variabelvärdet 2. Prova också med (x+1)^2;. En variabel som fått ett värde behåller detta tills man går ur Maple eller ger den ett annat värde. För att ta bort värdet kan man använda kommandot x:= x ;, som gör att Maple tolkar bokstaven x som en variabel, betecknad x, inte som variabelns värde. Det är lätt att glömma bort att man gett en variabel ett värde tidigare, vilket kan leda till obegripliga resultat av räkningar. Vill man ta bort alla värden på variabler och helt och hållet börja om från början skriver man restart;. Variabler kan förutom numeriska värden även ha Mapleuttryck som värden. Genom tilldelningskommandot 7
f:=(x+1)^3; så sätter vi f lika med (x + 1) 3. (Blir svaret 27 så tag bort det tidigare värdet från x och försök igen.) Man kan sedan räkna vidare med f och skriva t ex f^2; och expand(f^2);. Om man vill beräkna värdet av uttrycket f^2 för t ex x=2 utan att varaktigt tilldela x ett värde så kan man skriva subs(x=2,f^2); Funktioner Maple kan hantera inte bara analytiska uttryck, som vi sett exempel på ovan, utan även funktioner. Dessa kan definieras på flera olika sätt. Det för våra ändamål enklaste påminner om beteckningen för en funktion g. Ge kommandot g:= x->(x+1)^3; x g(x) Nu kan funktionsvärden beräknas på det sätt man är van vid. Prova t ex med g(0);, g(-1);, g(a); och g(y+z);. Anmärkning Man måste noga hålla isär begreppen funktion och funktionsuttryck, där det senare behandlades under rubriken Tilldelningssatser ovan. För säkerhets skull upprepar vi skillnaden: Om vi ger ett värde till F genom tilldelningen F:=exp(x)-sin(x); så är F ett uttryck med variabeln x inbyggt. Om vi i stället ger F ett värde genom F:=x->exp(x)-sin(x); så är F en funktion, där x bara används för att definiera en regel, och där man skulle kunna använda vilken annan symbol som helst. Funktioner är mycket mer flexibla, men ibland något mer svårhanterliga än funktionsuttryck. Det finns lyckligtvis ett enkelt sätt att göra om ett uttryck till en funktion, nämligen genom att använda kommandot unapply. Till exempel ger kommandot F:=unapply(exp(x)-sin(x),x); samma sak som F:=x->exp(x)-sin(x);. Maple klarar också funktioner av flera variabler. Funktionen h(x, y) = x 2 y 3 + x 2 y 3 definieras i Maple på följande sätt: h := (x,y) -> x^2-y^3+x^2*y^3; Vad ger h(0,0); och h(3,2);? Derivation Derivator beräknas med kommandot diff. Användningen framgår ur exemplen diff(x^3+2*x^2,x); diff(tan(x),x); 8
Andraderivator beräknas enligt diff(tan(x),x,x); På samma sätt beräknas derivator av högre ordning, där antalet x anger ordningen. För detta finns ett kortare skrivsätt. Beräkna fjärdederivatan av tan(x) genom att skriva diff(tan(x),x\$4);. Prova även att förenkla svaret med hjälp av factor(%);. Vi kan också derivera det tidigare definierade funktionsuttrycket f och funktionen g genom att skriva diff(f,x); resp diff(g(x),x); Tänk ut vad som kommer ut ur kommandona diff(f,y);, diff(g,x);, diff(g(y),y); och prova om det stämmer. Anmärkning. Maple har också en derivationsoperator D, se?d. Pröva tex D(g); och D(sin);. Man kan även lätt beräkna partiella derivator. Till exempel får man h x och h y för funktionen h ovan genom kommandona diff(h(x,y),x); diff(h(x,y),y); Högre derivator fås genom uppräkning av variabelnamnen. Pröva t ex diff(h(x,y),x,y); Gränsvärden Gränsvärden beräknas med kommandot limit, prova limit(sin(x)/x,x=0); limit((sqrt(1+x))/exp(x),x=infinity); 9