Otsu 输出 returns 全黑或全白取决于黑白像素
Otsu output returns full black or white depending on black and white pixels
我自己实现的 otsu returns 质量好的二值化图像,但如果图像有 "more black" 像素,它 returns 是全黑图像,如果图像有 "more white" 像素 returns 全白图像。
我正在使用 drawable,如果我使用相机,它 returns 输出具有相同的想法(全黑或全白)。即使图像有更多的黑色或更多的白色,我如何正确地二值化图像?
(returns全黑或全白的图像可以通过sauvola二值化,因为我尝试比较和检查输出。我没有放sauvola输出以避免长post 但如果需要我可以 post。)
以下是 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;
我上周二得到了答案,但忘了 post。我明白了 运行.
@Morrison Chang 感谢您对我的代码的一点推动和澄清
Bitmap BWimg = Bitmap.createBitmap(gImg.getWidth(), gImg.getHeight(), gImg.getConfig());
int width = gImg.getWidth();
int height = gImg.getHeight();
int A, R, G, B, colorPixel;
double Wcv = 0, th = 0;
int[] tPXL = new int[256];
int[][] pxl = new int[width][height];
double Bw, Bm, Bv, Fw, Fm, Fv;
int np, ImgPix = 0, fth = 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.2126 * R) + (0.7152 * G) + (0.0722 * B) ); // (int) ( (0.299 * R) + (0.587 * G) + (0.114 * B) );
pxl[x][y] = gray;
tPXL[gray] = tPXL[gray] + 1;
ImgPix = ImgPix + 1;
}
}
// ----- histo-variance ----- //
for (int t = 0; t < 256; t++){
Bw = 0; Bm = 0; Bv = 0;
Fw = 0; Fm = 0; Fv = 0;
np = 0;
if (t == 0){ // all white/foreground as t0 ----- //
Fw = 1;
for (int d = 0; d < 256; d++) { //mean
Fm = Fm + (d * tPXL[d]);
}
Fm = Fm / ImgPix;
for (int e = 0; e < 256; e++) { //variance
Fv = Fv + (Math.pow((e - Fm), 2) * tPXL[e]);
}
Fv = Fv / ImgPix;
}
else { // main thresholding
for (int d = 0; d < (t-1); d++){ // BG weight & mean + BG pixel
Bw = Bw + tPXL[d];
Bm = Bm + (d * tPXL[d]);
np = np + tPXL[d];
}
Bw = Bw / ImgPix;
Bm = Bm / np;
for (int e = 0; e < (t-1); e++) { //BG variance
Bv = Bv + (Math.pow((e - Bm), 2) * tPXL[e]);
}
Bv = Bv / np;
for (int j = t; j < 256; j++) { // FG weight & mean + BG pixel
Fw = Fw + tPXL[j];
Fm = Fm + (j * tPXL[j]);
np = ImgPix - np;
}
Fw = Fw / ImgPix;
Fm = Fm / np;
for (int k = t; k < 256; k++) { //FG variance
Fv = Fv + (Math.pow((k - Fm), 2) * tPXL[k]);
}
Fv = Fv / np;
}
// within class variance
Wcv = (Bw * Bv) + (Fw * Fv);
if (t == 0){
th = Wcv;
}
else if (Wcv < th){
th = Wcv;
fth = t;
}
}
// set binarize pixel
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int fnpx = pxl[x][y];
colorPixel = gImg.getPixel(x, y);
A = Color.alpha(colorPixel);
if (fnpx > fth) { //R > fth
fnpx = 255;
BWimg.setPixel(x, y, Color.argb(A, fnpx, fnpx, fnpx));
}
else {
fnpx = 0;
BWimg.setPixel(x, y, Color.argb(A, fnpx, fnpx, fnpx));
}
}
}
return BWimg;
我自己实现的 otsu returns 质量好的二值化图像,但如果图像有 "more black" 像素,它 returns 是全黑图像,如果图像有 "more white" 像素 returns 全白图像。
我正在使用 drawable,如果我使用相机,它 returns 输出具有相同的想法(全黑或全白)。即使图像有更多的黑色或更多的白色,我如何正确地二值化图像?
(returns全黑或全白的图像可以通过sauvola二值化,因为我尝试比较和检查输出。我没有放sauvola输出以避免长post 但如果需要我可以 post。)
以下是 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;
我上周二得到了答案,但忘了 post。我明白了 运行.
@Morrison Chang 感谢您对我的代码的一点推动和澄清
Bitmap BWimg = Bitmap.createBitmap(gImg.getWidth(), gImg.getHeight(), gImg.getConfig());
int width = gImg.getWidth();
int height = gImg.getHeight();
int A, R, G, B, colorPixel;
double Wcv = 0, th = 0;
int[] tPXL = new int[256];
int[][] pxl = new int[width][height];
double Bw, Bm, Bv, Fw, Fm, Fv;
int np, ImgPix = 0, fth = 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.2126 * R) + (0.7152 * G) + (0.0722 * B) ); // (int) ( (0.299 * R) + (0.587 * G) + (0.114 * B) );
pxl[x][y] = gray;
tPXL[gray] = tPXL[gray] + 1;
ImgPix = ImgPix + 1;
}
}
// ----- histo-variance ----- //
for (int t = 0; t < 256; t++){
Bw = 0; Bm = 0; Bv = 0;
Fw = 0; Fm = 0; Fv = 0;
np = 0;
if (t == 0){ // all white/foreground as t0 ----- //
Fw = 1;
for (int d = 0; d < 256; d++) { //mean
Fm = Fm + (d * tPXL[d]);
}
Fm = Fm / ImgPix;
for (int e = 0; e < 256; e++) { //variance
Fv = Fv + (Math.pow((e - Fm), 2) * tPXL[e]);
}
Fv = Fv / ImgPix;
}
else { // main thresholding
for (int d = 0; d < (t-1); d++){ // BG weight & mean + BG pixel
Bw = Bw + tPXL[d];
Bm = Bm + (d * tPXL[d]);
np = np + tPXL[d];
}
Bw = Bw / ImgPix;
Bm = Bm / np;
for (int e = 0; e < (t-1); e++) { //BG variance
Bv = Bv + (Math.pow((e - Bm), 2) * tPXL[e]);
}
Bv = Bv / np;
for (int j = t; j < 256; j++) { // FG weight & mean + BG pixel
Fw = Fw + tPXL[j];
Fm = Fm + (j * tPXL[j]);
np = ImgPix - np;
}
Fw = Fw / ImgPix;
Fm = Fm / np;
for (int k = t; k < 256; k++) { //FG variance
Fv = Fv + (Math.pow((k - Fm), 2) * tPXL[k]);
}
Fv = Fv / np;
}
// within class variance
Wcv = (Bw * Bv) + (Fw * Fv);
if (t == 0){
th = Wcv;
}
else if (Wcv < th){
th = Wcv;
fth = t;
}
}
// set binarize pixel
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int fnpx = pxl[x][y];
colorPixel = gImg.getPixel(x, y);
A = Color.alpha(colorPixel);
if (fnpx > fth) { //R > fth
fnpx = 255;
BWimg.setPixel(x, y, Color.argb(A, fnpx, fnpx, fnpx));
}
else {
fnpx = 0;
BWimg.setPixel(x, y, Color.argb(A, fnpx, fnpx, fnpx));
}
}
}
return BWimg;