Рассчитать бинарный оптимальный порог ImageJ на основе среднего / заднего фона - PullRequest
0 голосов
/ 30 января 2019

Я исследовал, как рассчитать оптимальный порог для 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;
}

1 Ответ

0 голосов
/ 31 января 2019

не уверен, что это ты имел ввиду?извините - еще новичок в SO>. <</p>

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;
}
...