Я исследовал, как рассчитать оптимальный порог для ImageJ, и нашел это объяснение порогового значения Otsu , которое, как мне показалось, имело смысл для меня использовать.
У меня естьХотя я пытался реализовать его, и после некоторой мысли я нашел ошибку в способе вычисления веса и среднего, и теперь он находит оптимальный порог 77, который для изображения монеты мне подходит, поскольку он почти полностью разделяет фониз монет (и вы сможете автоматически считать монеты или измерять их по размеру, ectr)
новое изображение монеты с оптимальным порогом
это такжеПохоже, что это изображение работает очень хорошо, даже если оно имеет различную интенсивность света: рисовое изображение с различной интенсивностью
Я вполне доволен найденным решением, но если у вас естьобратная связь или может найти что-то еще, это было бы здорово!Это домашнее задание было тяжелым, но я многому научился у него :)
public float calculateMeanFG(int[] histogram, int t) {
float sumI = 0;
int total = 0;
//cumulate the histogram for < 256
for (int i = t; i < 256; i++) {
sumI += histogram[i] * i;
total = i;
}
return sumI / total;
}
public float calculateMeanBG(int[] histogram, int t) {
float sumI = 0;
//cumulate the histogram for < t
for (int i = 0; i < t; i++) {
sumI += histogram[i] * i;
}
return sumI;
}
public float calculateWeightFG(int[] histogram, int t, int total) {
int sum = 0;
for (int i = t; i < 256; i++) {
sum += histogram[i];
}
return sum / total;
}
public int[] getHistogram(ImageProcessor ip, int height, int width) {
byte[] outP = ((byte[]) ip.getPixels()).clone();
int[][] inDataArr = new int[width][height];
int[] histogram = new int[256];
int idx = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// fill in values
inDataArr[x][y] = outP[idx];
if (inDataArr[x][y] < 0) {
inDataArr[x][y] += 256;
} // if
histogram[inDataArr[x][y]] += 1; // count grayscale occurrences
idx++;
} // for x
} // for y
return histogram;
}
public int[][] convergeOptThresh(int[][] imgArr, int width, int height) {
int BG_VAL = 0;
int FG_VAL = 255;
int[] histogram = getHistogram(ip, height, width);
// total number of pixels
int total = imgArr.length;
// cumulative hist
float sum = 0;
for (int i = 0; i < 256; i++)
sum += i * histogram[i];
float sumBG = 0; // sum background
float weightBG = 0;
float weightFG = 0;
float varMax = 0;
int threshold = 0;
for (int t = 0; t < 256; t++) {
weightBG = calculateMeanBG(histogram, t);
weightBG /= total;
weightFG = calculateWeightFG(histogram, t, total);
if ((int)weightFG == 0)
break;
sumBG += (float) (t * histogram[t]);
float meanBG = sumBG / t;
float meanFG = calculateMeanFG(histogram, t);
// calculate between class variance
float varBetween = weightBG * weightFG * (meanBG - meanFG) * (meanBG - meanFG);
// check if new max found
if (varBetween > varMax) {
varMax = varBetween;
threshold = t;
}
}
IJ.log("optimal threshold: " + threshold);
int[][] retArr = new int[width][height];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
if (imgArr[x][y] <= threshold) {
retArr[x][y] = BG_VAL;
} else {
retArr[x][y] = FG_VAL;
}
}
}
return retArr;
}