Как я могу улучшить результат моего самостоятельно реализованного алгоритма otsu?
Я сделал свою собственную реализацию Оцу для своего проекта. Я следовал математическому алгоритму, чтобы сделать это. Я пытался использовать гистограмму, но мне было трудно, поэтому я просто следовал ее логике. Как я могу точно бинаризовать его? Мой текущий выход только полностью черный или полностью белый?
Что я уже пробовал:
I made my own implementation of Otsu for my project. After hours of experimenting on how can I make the image to black-white after getting the within class variance. Here is my full working code and some output. Here is my code: Otsu.java Bitmap tempImg = (Bitmap) original; Bitmap OImg = Bitmap.createBitmap(tempImg.getWidth(), tempImg.getHeight(), tempImg.getConfig()); int width = tempImg.getWidth(); int height = tempImg.getHeight(); int A, R, G, B,colorPixel; for (int x = 0; x < width; x++) { //original image to grayscale for (int y = 0; y < height; y++) { colorPixel = tempImg.getPixel(x, y); A = Color.alpha(colorPixel); R = Color.red(colorPixel); G = Color.green(colorPixel); B = Color.blue(colorPixel); R = (R + G + B) / 3; G = R; B = R; OImg.setPixel(x, y, Color.argb(A, R, G,B )); } } return OImg; } public static Bitmap Botsu(Bitmap gImg){ Bitmap tempImg = (Bitmap) gImg; Bitmap BWimg = Bitmap.createBitmap(tempImg.getWidth(), tempImg.getHeight(), tempImg.getConfig()); int width = tempImg.getWidth(); int height = tempImg.getHeight(); int A, R, G, B, colorPixel; // histo-thresh double Wcv = 0; int[] Bx = new int[256]; int[] By = new int[256]; int[] Fx = new int[256]; int[] Fy = new int[256]; double Bw =0, Bm =0, Bv =0, Bp = 0; double Fw =0, Fm =0, Fv =0, Fp = 0; int c = 0, ImgPix = 0, ImgPixB = 0, ImgPixF = 0, newPixel = 0; // pixel check for histogram for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { colorPixel = tempImg.getPixel(x, y); A = Color.alpha(colorPixel); R = Color.red(colorPixel); G = Color.green(colorPixel); B = Color.blue(colorPixel); int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B); if (gray > 128) { // white - foreground for (int z=0; z<Fx.length; z++){ if (Fx[z] == gray){ c++; } } if (c==1){ Fy[gray] = Fy[gray]+1; //y axis - counter for pixels for each x } else{ Fx[x] = gray; //x axis - 0-255 Fy[gray] = Fy[gray]+1; } }//By[Bx[x]] else{ // black - background for (int z=0; z<Bx.length; z++){ if (Bx[z] == gray){ c++; } } if (c==1){ By[gray] = By[gray]+1; //y axis - counter for pixels for each x } else{ Bx[x] = gray; //x axis - 0-255 By[gray] = By[gray]+1; } } } } for (int b=0; b<By.length; b++){ ImgPixB = ImgPixB + By[b]; } for (int f=0; f<Fy.length; f++){ ImgPixF = ImgPixF + Fy[f]; } ImgPix = ImgPixB + ImgPixF; //bg part hist for (int i=0; i<By.length; i++){ //weight Bw = Bw + By[i]; } Bw = Bw/ImgPix; for (int i=0; i<By.length; i++){ //pixel sum Bp = Bp + By[i]; } for (int i = 0; i<Bx.length; i++){ //mean Bm = Bm + (Bx[i]*By[Bx[i]]); } Bm = Bm/Bp; for (int i=0; i<Bx.length; i++){ //variance Bv = Bv + (Math.pow((Bx[i]-Bm),2)*By[Bx[i]]); // (Bx[i]-Bm) * (Bx[i]-Bm) } Bv = Bv/Bp; //fg part hist for (int i=0; i<Fy.length; i++){ //weight Fw = Fw + Fy[i]; } Fw = Fw/ImgPix; for (int i=0; i<Fy.length; i++){ //pixel sum Fp = Fp + Fy[i]; } for (int i = 0; i<Fx.length; i++){ //mean Fm = Fm + (Fx[i]*Fy[Fx[i]]); } Fm = Fm/Fp; for (int i=0; i<Fx.length; i++){ //variance Fv = Fv + (Math.pow((Fx[i]-Fm),2)*Fy[Fx[i]]); // (Bx[i]-Bm) * (Bx[i]-Bm) } Fv = Fv/Fp; // within class variance Wcv = (Bw * Bv) + (Fw * Fv); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { colorPixel = tempImg.getPixel(x, y); A = Color.alpha(colorPixel); R = Color.red(colorPixel); G = Color.green(colorPixel); B = Color.blue(colorPixel); //int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B); int gray2 = (int) (Wcv * R + Wcv * G + Wcv * B); if (gray2 > 128) { gray2 = 255; } else if (gray2 <129){ gray2 = 0; } BWimg.setPixel(x, y, Color.argb(A, gray2, gray2, gray2)); } } return BWimg; `x[z]` is for x-axis and`y[gray] ` is for y-axis. I based this on the graph on [Lab Book][1] x = 0-255 y = how many pixels is on a certain color shade
Вывод: (я добавил 2 значения if-else, которые я экспериментировал, которые показали 3 разных выхода. Другие значения вернут только несколько черных точек или просто чистое белое изображение.)
if (gray2 > 128) { gray2 = 255; } else if (gray2 < 129){ gray2 = 0; }
Выход 1
Выход 2
if (gray2 > 64 && gray2 < 129) { gray2 = 255; } else if (gray2 < 65){ gray2 = 0; }
Выход3