我自己实现的 otsu 返回高质量的二值化图像,但如果图像具有“更多黑色”像素,则返回全黑图像,如果图像具有“更多白色”像素,则返回全白图像。
我使用drawable,如果我使用相机,它会以相同的想法返回输出(全黑或全白)。即使图像有更多的黑色或更多的白色,如何正确二值化图像?
(当我尝试比较和检查输出时,以全黑或全白返回的图像可以通过 sauvola 进行二值化。我没有放 sauvola 输出以避免长时间发布,但如果需要,我可以发布它。)
以下是 Otsu 上的一些输出:
大津二值化码
Bitmap BWimg = Bitmap.createBitmap(gImg.getWidth(), gImg.getHeight(), gImg.getConfig());
int width = gImg.getWidth();
int height = gImg.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;
// pixel check for histogram
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
colorPixel = gImg.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
Fx[gray] = gray;
Fy[gray] = Fy[gray] + 1;
Fw = Fw + 1;
Fp = Fp + 1;
}
else { // black - background
Bx[gray] = gray;
By[gray] = By[gray] + 1;
Bw = Bw + 1;
Bp = Bp + 1;
}
ImgPix = ImgPix + 1;
}
}
//BG hist
Bw = Bw / ImgPix; //BG weight
int i;
for (i = 0; i < Bx.length; i++) { //BG mean
Bm = Bm + (Bx[i] * By[i]);
Bm = Bm / Bp;
}
for (i = 0; i < Bx.length; i++) { //BG variance
Bv = Bv + (Math.pow((Bx[i] - Bm), 2) * By[i]); // (Bx[i]-Bm) * (Bx[i]-Bm)
}
Bv = Bv / Bp;
//FG hist
Fw = Fw / ImgPix; //BG weight
for (i = 0; i < Bx.length; i++) { //BG mean
Fm = Fm + (Fx[i] * Fy[i]);
}
Fm = Fm / Fp;
for (i = 0; i < Bx.length; i++) { //BG variance
Fv = Fv + (Math.pow((Fx[i] - Fm), 2) * Fy[i]); // (Fx[i]-Fm) * (Fx[i]-Fm)
}
Fv = Fv / Fp;
// within class variance
Wcv = (Bw * Bv) + (Fw * Fv);
//int gray2 = 0;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
colorPixel = gImg.getPixel(x, y);
A = Color.alpha(colorPixel);
R = Color.red(colorPixel);
G = Color.green(colorPixel);
B = Color.blue(colorPixel);
//int gray2 = (int) ((0.2989 * R) + (0.5870 * G) + (0.1140 * B));
int gray2 = (R + G + B);
if (gray2 > Wcv) {
gray2 = 255;
}
else {
gray2 = 0;
}
BWimg.setPixel(x, y, Color.argb(A, gray2, gray2, gray2));
}
}
return BWimg;