280 likes | 696 Views
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)
E N D
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
Proširenja osnovnog zadatka • rad sa slikama u boji i sivim slikama • rad sa histogramima • morfologija • dodavanje šuma • konverzija tipova slika • “undo” opcija
Osnovni koncepti implementacije • C# (.NET 2.0) • modularni pristup • jednostavno unapređivanje SlikaLib Morfološke operacije (Zlatko.dll) Geometrijske operacije (Ognjen.dll) Filtriranje (Kurtjak.dll) Detekcija zakrivljenja (SkewDetection.dll) Osnovni interfejs
Podržani tipovi slika • bmp • jpeg • png • gif • tiff • moguća konverzija između svih tipova
Osnovni interfejs Glavni prozor Prozori za slike
SlikaLib • biblioteka sa osnovnim klasama • distribucija u vidu .dll datoteke • objekti u osnovnoj klasi (Slika): - objekat klase Bitmap (.NET) - width (int) - height (int) - ImgType (RGB, Gray, Binary) - ostale vrijednosti (buffer, maxValue, minValue...)
Osnovne operacije • Crop (isijecanje) - zadržavanje selektovanog dijela slike Slikarez = newSlika(sirina, visina, original.ImageType); for (inti = ax, m = 0; i < ax + sirina; i++, m++) for (intj = ay, n = 0; j < ay + visina; j++, n++) if (original.ImageType == imgType.rgb) rez.setPixelRGBAt(m, n, original.getPixelRGBAt(i, j)); else rez.setPixelAt(m, n, original.getPixelAt(i, j)); return rez;
Osnovne operacije • Cut - funkcija “suprotna” crop - selektovani dio slike se odbacuje • Negativ - kreiranje inverzne slike - zavisi od tipa (u boji, siva, binarna)
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
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
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)
Matematička morfologija • Dilatacija - proširivanje slike - osnovne ideje realizacije - funkcije getFirst() i hasNext() - rubni pikseli - smještanje rezultata
Matematička morfologija public static Slika dilatacija(Slika slika) { if ((strElement != null) && (strElement.hasElement())) { Slika copy = slika.getImgCopy(); Slika s = new Slika(copy.Width, copy.Height, imgType.binary); for (int i = 0; i < s.Width; i++) for (int j = 0; j < s.Height; j++) s.setPixelAt(i, j, 1); for (int i = 0; i < copy.Width; i++) for (int j = 0; j < copy.Height; j++) if (copy.getPixelAt(i, j) == 0) { element e = strElement.getFirst(); if (!(((e.x + i) < 0) || ((e.x + i) >= copy.Width) || ((e.y + j) < 0) || ((e.y + j) >= copy.Height))) s.setPixelAt((e.x + i), (e.y + j), 0); while (strElement.hasNext()) { e = strElement.getNext(); if (!(((e.x + i) < 0) || ((e.x + i) >= copy.Width) || ((e.y + j) < 0) || ((e.y + j) >= copy.Height))) s.setPixelAt((e.x + i), (e.y + j), 0); } } slika = s; } else { MessageBox.Show("Strukturni element je prazan skup! Postavite strukturni element.", "Greška"); } return slika; }
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
Matematička morfologija public static Slika erozija(Slika slika) { if ((strElement != null) && (strElement.hasElement())) { Slika copy = slika.getImgCopy(); Slika s = new Slika(copy.Width, copy.Height, imgType.binary); for (int i = 0; i < s.Width; i++) for (int j = 0; j < s.Height; j++) s.setPixelAt(i, j, 1); for (int i = 0; i < copy.Width; i++) for (int j = 0; j < copy.Height; j++) if (copy.getPixelAt(i, j) == 0) { bool flag = true; element e = strElement.getFirst(); if (!(((e.x + i) < 0) || ((e.x + i) >= copy.Width) || ((e.y + j) < 0) || ((e.y + j) >= copy.Height))) if (copy.getPixelAt((e.x + i), (e.y + j)) == 1) flag = false; while (strElement.hasNext()) { e = strElement.getNext(); if (!(((e.x + i) < 0) || ((e.x + i) >= copy.Width) || ((e.y + j) < 0) || ((e.y + j) >= copy.Height))) if (copy.getPixelAt((e.x + i), (e.y + j)) == 1) { flag = false; break; } } if(flag) s.setPixelAt(i, j, 0); } slika = s; } else { MessageBox.Show("Strukturni element je prazan skup! Postavite strukturni element.", "Greška"); } return slika; }
Matematička morfologija • Primjer (original, dilatacija, erozija):
Matematička morfologija • Otvaranje - erozija + dilatacija istim str.el. public static Slika otvaranje(Slika s) { return dilatacija(erozija(s)); }
Matematička morfologija • Zatvaranje - dilatacija + erozija istim str.el. public static Slika zatvaranje(Slika s) { return erozija(dilatacija(s)); }
Filtriranje • Filteri - uniformni - Gausov - median - Laplasov • Šumovi - salt & pepper
Filtriranje • osnovne ideje • obraćanje pažnje na rubne piksele funkcijom getImgBoundary() • analogija sa Matlab-om u realizaciji funkcija imFilter() i fSpecial() • podrazumijevani parametri
Filtriranje Salt & Paper Average Gauss Median Laplacian
Filtriranje public static Slika imFilter(Slika slika, float[,] kernel, int sirina, int visina, string ivicniTip) { ... for (int i = 0; i < copy.Width; i++) for (int j = 0; j < copy.Height; j++) { float[,] f = getImgBoundary(copy, sirina, visina, i, j, ivicniTip); 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[,] getImgBoundary(Slika slika, int sirina, int visina, int red, int kolona, string ivicniTip) { if (ivicniTip.Equals("zeros")) {. . .} else if (ivicniTip.Equals("symmetric")) {. . .} else if (ivicniTip.Equals("replicate")) {. . .} else if (ivicniTip.Equals("circular")) {. . .} return retValue; }
Filtriranje public static float[,] fSpecial(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; }
Filtriranje • Median filtar public static Slika medfilt2(Slika slika, int sirina, int visina, string boundaryType) { slika.makeBuffer(); Slika copy = slika.getImgCopy(); for (int i = 0; i < copy.Width; i++) for (int j = 0; j < copy.Height; j++) { float[,] f = getImgBoundary(copy, sirina, visina, i, j, boundaryType); 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.setPixelAt(i, j, f[sirina / 2, visina / 2]); } return slika; }
Filtriranje • Salt & pepper šum public static Slika imNoise(Slika s, string noiseType, float freq) { if (noiseType.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.setPixelAt(i, j, 0); else if (rdm >= (100 - f / 2)) s.setPixelAt(i, j, 1); } return s; } throw new Exception("Nije dobar parametar"); }