DIGITALNA OBRADA SLIKE Softver za obradu slike Ognjen
DIGITALNA OBRADA SLIKE Softver za obradu slike Ognjen Joldžić, 21/04 Zlatko Dejanović, 16/04 Daniel Kurtjak, 50/04
Zadaci • • • kreirati softver za obradu slike (rad sa binarnim slikama) potrebne funkcije - isjecanje - brisanje - invertovanje - rotacija (za n*90°, slika u ogledalu) - detekcija iskošenja i ispravljanje - uklanjanje šuma proizvoljna tehnologija za implementaciju 2
Proširenja osnovnog zadatka • • • rad sa slikama u boji i sivim slikama rad sa histogramima morfologija dodavanje šuma konverzija tipova slika “undo” opcija 3
Osnovni koncepti implementacije • C# (. NET 2. 0) • modularni pristup • jednostavno unapređivanje Slika. Lib Morfološke operacije (Zlatko. dll) Geometrijske operacije (Ognjen. dll) Filtriranje (Kurtjak. dll) Detekcija zakrivljenja (Skew. Detection. dll) Osnovni interfejs 4
Podržani tipovi slika • • • bmp jpeg png gif tiff • moguća konverzija između svih tipova 5
Osnovni interfejs Glavni prozor Prozori za slike 6
Slika. Lib • biblioteka sa osnovnim klasama • distribucija u vidu. dll datoteke • objekti u osnovnoj klasi (Slika): - objekat klase Bitmap (. NET) - width (int) - height (int) - Img. Type (RGB, Gray, Binary) - ostale vrijednosti (buffer, max. Value, min. Value. . . ) 7
Osnovne operacije • Crop (isijecanje) - zadržavanje selektovanog dijela slike Slika rez = new Slika(sirina, visina, original. Image. Type); for (int i = ax, m = 0; i < ax + sirina; i++, m++) for (int j = ay, n = 0; j < ay + visina; j++, n++) if (original. Image. Type == img. Type. rgb) rez. set. Pixel. RGBAt(m, n, original. get. Pixel. RGBAt(i, j)); else rez. set. Pixel. At(m, n, original. get. Pixel. At(i, j)); return rez; 8
Osnovne operacije • Cut - funkcija “suprotna” crop - selektovani dio slike se odbacuje • Negativ - kreiranje inverzne slike - zavisi od tipa (u boji, siva, binarna) 9
Osnovne operacije • Rotacija za n*90° - n=± 1 - promjena dimenzija slike • Slika u ogledalu (flip) - u odnosu na vertikalnu osu - u odnosu na horizontalnu osu - dimenzije slike su iste 10
Osnovne operacije • Konverzija broja boja - RGB -> Siva -> Binarna - obrnuta konverzija nije moguća - neke funkcije moguće samo za određeni tip slike - jednostavni algoritmi za konverziju 11
Matematička morfologija • Strukturni element - opis - podešavanje - struktura u memoriji - primjer osnovnog strukturnog elementa: (-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 0), (0, 1), (1, -1), (1, 0), (1, 1) 12
Matematička morfologija • Dilatacija - proširivanje slike - osnovne ideje realizacije - funkcije get. First() i has. Next() - rubni pikseli - smještanje rezultata 13
Matematička morfologija public static Slika dilatacija(Slika slika) { if ((str. Element != null) && (str. Element. has. Element())) { Slika copy = slika. get. Img. Copy(); Slika s = new Slika(copy. Width, copy. Height, img. Type. binary); for (int i = 0; i < s. Width; i++) for (int j = 0; j < s. Height; j++) s. set. Pixel. At(i, j, 1); for (int i = 0; i < copy. Width; i++) for (int j = 0; j < copy. Height; j++) if (copy. get. Pixel. At(i, j) == 0) { element e = str. Element. get. First(); if (!(((e. x + i) < 0) || ((e. x + i) >= copy. Width) || ((e. y + j) < 0) || ((e. y + j) >= copy. Height))) s. set. Pixel. At((e. x + i), (e. y + j), 0); while (str. Element. has. Next()) { e = str. Element. get. Next(); if (!(((e. x + i) < 0) || ((e. x + i) >= copy. Width) || ((e. y + j) < 0) || ((e. y + j) >= copy. Height))) s. set. Pixel. At((e. x + i), (e. y + j), 0); } } slika = s; } else { Message. Box. Show("Strukturni element je prazan skup! Postavite strukturni element. ", "Greška"); } return slika; } 14
Matematička morfologija • Erozija - eliminisanje rubnih piksela slike - osnovne ideje slične kao kod dilatacije - uvođenje logičke promjenljive flag koja određuje da li će piksel biti iscrtan 15
Matematička morfologija public static Slika erozija(Slika slika) { if ((str. Element != null) && (str. Element. has. Element())) { Slika copy = slika. get. Img. Copy(); Slika s = new Slika(copy. Width, copy. Height, img. Type. binary); for (int i = 0; i < s. Width; i++) for (int j = 0; j < s. Height; j++) s. set. Pixel. At(i, j, 1); for (int i = 0; i < copy. Width; i++) for (int j = 0; j < copy. Height; j++) if (copy. get. Pixel. At(i, j) == 0) { bool flag = true; element e = str. Element. get. First(); if (!(((e. x + i) < 0) || ((e. x + i) >= copy. Width) || ((e. y + j) < 0) || ((e. y + j) >= copy. Height))) if (copy. get. Pixel. At((e. x + i), (e. y + j)) == 1) flag = false; while (str. Element. has. Next()) { e = str. Element. get. Next(); if (!(((e. x + i) < 0) || ((e. x + i) >= copy. Width) || ((e. y + j) < 0) || ((e. y + j) >= copy. Height))) if (copy. get. Pixel. At((e. x + i), (e. y + j)) == 1) { flag = false; break; } } if(flag) s. set. Pixel. At(i, j, 0); } slika = s; } else { Message. Box. Show("Strukturni element je prazan skup! Postavite strukturni element. ", "Greška"); } return slika; } 16
Matematička morfologija • Primjer (original, dilatacija, erozija): 17
Matematička morfologija • Otvaranje - erozija + dilatacija istim str. el. public static Slika otvaranje(Slika s) { return dilatacija(erozija(s)); } 18
Matematička morfologija • Zatvaranje - dilatacija + erozija istim str. el. public static Slika zatvaranje(Slika s) { return erozija(dilatacija(s)); } 19
Filtriranje • Filteri - uniformni - Gausov - median - Laplasov • Šumovi - salt & pepper 20
Filtriranje • osnovne ideje • obraćanje pažnje na rubne piksele funkcijom get. Img. Boundary() • analogija sa Matlab-om u realizaciji funkcija im. Filter() i f. Special() • podrazumijevani parametri 21
Filtriranje Salt & Paper Average Gauss Median Laplacian 22
Filtriranje public static Slika im. Filter(Slika slika, float[, ] kernel, int sirina, int visina, string ivicni. Tip) {. . . for (int i = 0; i < copy. Width; i++) for (int j = 0; j < copy. Height; j++) { float[, ] f = get. Img. Boundary(copy, sirina, visina, i, j, ivicni. Tip); float sum = 0; for (int ii = 0; ii < sirina; ii++) for (int jj = 0; jj < visina; jj++) sum += f[ii, jj] * kernel[ii, jj]; }. . . return slika; } public static float[, ] get. Img. Boundary(Slika slika, int sirina, int visina, int red, int kolona, string ivicni. Tip) { if (ivicni. Tip. Equals("zeros")) {. . . } else if (ivicni. Tip. Equals("symmetric")) {. . . } else if (ivicni. Tip. Equals("replicate")) {. . . } else if (ivicni. Tip. Equals("circular")) {. . . } return ret. Value; } 23
Filtriranje public static float[, ] f. Special(string type, int width, int height, float sigma, float alpha) { float[, ] f = new float[width, height]; if (type. Equals("average")) {. . . } else if (type. Equals("laplacian")) {. . . } else if (type. Equals("gaussian")) {. . . } return f; } 24
Filtriranje • Median filtar public static Slika medfilt 2(Slika slika, int sirina, int visina, string boundary. Type) { slika. make. Buffer(); Slika copy = slika. get. Img. Copy(); for (int i = 0; i < copy. Width; i++) for (int j = 0; j < copy. Height; j++) { float[, ] f = get. Img. Boundary(copy, sirina, visina, i, j, boundary. Type); for (int ii = 0; ii < sirina * visina - 1; ii++) for (int jj = ii; jj < sirina * visina; jj++) if (f[ii / sirina, ii % sirina] > f[jj /sirina, jj % sirina]) { float tmp = f[ii / sirina, ii % sirina]; f[ii / sirina, ii % sirina] = f[jj / sirina, jj % sirina]; f[jj / sirina, jj % sirina] = tmp; } slika. set. Pixel. At(i, j, f[sirina / 2, visina / 2]); } return slika; } 25
Filtriranje • Salt & pepper šum public static Slika im. Noise(Slika s, string noise. Type, float freq) { if (noise. Type. Equals("salt & pepper")) { int f = (int)(freq * 100); Random r = new Random(); for (int i = 0; i < s. Width; i++) for (int j = 0; j < s. Height; j++) { int rdm = r. Next(0, 100); if (rdm < f / 2) s. set. Pixel. At(i, j, 0); else if (rdm >= (100 - f / 2)) s. set. Pixel. At(i, j, 1); } return s; } throw new Exception("Nije dobar parametar"); } 26
- Slides: 26