Multi otsu(multi-thresholding) with openCV

后端 未结 6 1610
忘掉有多难
忘掉有多难 2020-12-02 23:53

I am trying to carry out multi-thresholding with otsu. The method I am using currently is actually via maximising the between class variance, I have managed to get the same

6条回答
  •  时光取名叫无心
    2020-12-03 00:36

    To extend Otsu's thresholding method to multi-level thresholding the between class variance equation becomes:

    Please check out Deng-Yuan Huang, Ta-Wei Lin, Wu-Chih Hu, Automatic Multilevel Thresholding Based on Two-Stage Otsu's Method with Cluster Determination by Valley Estimation, Int. Journal of Innovative Computing, 2011, 7:5631-5644 for more information.

    http://www.ijicic.org/ijicic-10-05033.pdf

    Here is my C# implementation of Otsu Multi for 2 thresholds:

    /* Otsu (1979) - multi */
    
    Tuple < int, int > otsuMulti(object sender, EventArgs e) {
        //image histogram
        int[] histogram = new int[256];
    
        //total number of pixels
        int N = 0;
    
        //accumulate image histogram and total number of pixels
        foreach(int intensity in image.Data) {
            if (intensity != 0) {
                histogram[intensity] += 1;
                N++;
            }
        }
    
        double W0K, W1K, W2K, M0, M1, M2, currVarB, optimalThresh1, optimalThresh2, maxBetweenVar, M0K, M1K, M2K, MT;
    
        optimalThresh1 = 0;
        optimalThresh2 = 0;
    
        W0K = 0;
        W1K = 0;
    
        M0K = 0;
        M1K = 0;
    
        MT = 0;
        maxBetweenVar = 0;
        for (int k = 0; k <= 255; k++) {
            MT += k * (histogram[k] / (double) N);
        }
    
    
        for (int t1 = 0; t1 <= 255; t1++) {
            W0K += histogram[t1] / (double) N; //Pi
            M0K += t1 * (histogram[t1] / (double) N); //i * Pi
            M0 = M0K / W0K; //(i * Pi)/Pi
    
            W1K = 0;
            M1K = 0;
    
            for (int t2 = t1 + 1; t2 <= 255; t2++) {
                W1K += histogram[t2] / (double) N; //Pi
                M1K += t2 * (histogram[t2] / (double) N); //i * Pi
                M1 = M1K / W1K; //(i * Pi)/Pi
    
                W2K = 1 - (W0K + W1K);
                M2K = MT - (M0K + M1K);
    
                if (W2K <= 0) break;
    
                M2 = M2K / W2K;
    
                currVarB = W0K * (M0 - MT) * (M0 - MT) + W1K * (M1 - MT) * (M1 - MT) + W2K * (M2 - MT) * (M2 - MT);
    
                if (maxBetweenVar < currVarB) {
                    maxBetweenVar = currVarB;
                    optimalThresh1 = t1;
                    optimalThresh2 = t2;
                }
            }
        }
    
        return new Tuple(optimalThresh1, optimalThresh2);
    }
    

    And this is the result I got by thresholding an image scan of soil with the above code:

    (T1 = 110, T2 = 147).

    Otsu's original paper: "Nobuyuki Otsu, A Threshold Selection Method from Gray-Level Histogram, IEEE Transactions on Systems, Man, and Cybernetics, 1979, 9:62-66" also briefly mentions the extension to Multithresholding.

    https://engineering.purdue.edu/kak/computervision/ECE661.08/OTSU_paper.pdf

    Hope this helps.

提交回复
热议问题