Skip to content
Snippets Groups Projects

Otsu's Thresholding-Algorithmus

  • Clone with SSH
  • Clone with HTTPS
  • Embed
  • Share
    The snippet can be accessed without any authentication.
    Authored by Bökelmann, Stephan
    otsu.c 2.87 KiB
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    /**
     * @brief Berechnet das Histogramm eines Graustufenbildes.
     * 
     * @param image Zeiger auf das Bild.
     * @param width Breite des Bildes.
     * @param height Höhe des Bildes.
     * @param histogram Array zur Speicherung des Histogramms (256 Werte).
     */
    void calculateHistogram(unsigned char* image, int width, int height, int* histogram) {
        for (int i = 0; i < 256; i++) {
            histogram[i] = 0;
        }
    
        for (int i = 0; i < width * height; i++) {
            histogram[image[i]]++;
        }
    }
    
    /**
     * @brief Führt Otsu's Thresholding auf einem Graustufenbild durch.
     * 
     * @param image Zeiger auf das Bild.
     * @param width Breite des Bildes.
     * @param height Höhe des Bildes.
     * @return Der optimale Schwellenwert.
     */
    int otsuThreshold(unsigned char* image, int width, int height) {
        int histogram[256];
        calculateHistogram(image, width, height, histogram);
    
        int total = width * height;
        float sum = 0;
        for (int t = 0; t < 256; t++) {
            sum += t * histogram[t];
        }
    
        float sumB = 0;
        int wB = 0;
        int wF = 0;
        float maxVariance = 0;
        int threshold = 0;
    
        for (int t = 0; t < 256; t++) {
            wB += histogram[t];
            if (wB == 0) {
                continue;
            }
            wF = total - wB;
            if (wF == 0) {
                break;
            }
    
            sumB += (float)(t * histogram[t]);
            float mB = sumB / wB;
            float mF = (sum - sumB) / wF;
    
            float variance = (float)wB * (float)wF * (mB - mF) * (mB - mF);
    
            if (variance > maxVariance) {
                maxVariance = variance;
                threshold = t;
            }
        }
    
        return threshold;
    }
    
    /**
     * @brief Segmentiert ein Bild basierend auf einem Schwellenwert.
     * 
     * @param image Zeiger auf das Bild.
     * @param width Breite des Bildes.
     * @param height Höhe des Bildes.
     * @param threshold Der Schwellenwert.
     */
    void segmentImage(unsigned char* image, int width, int height, int threshold) {
        for (int i = 0; i < width * height; i++) {
            image[i] = (image[i] > threshold) ? 255 : 0;
        }
    }
    
    int main() {
        // Beispielbild (Graustufenbild)
        unsigned char image[] = {
            52, 55, 61, 59, 79, 61, 76, 61,
            62, 59, 55, 104, 94, 85, 59, 71,
            63, 65, 66, 113, 144, 104, 63, 72,
            64, 70, 70, 126, 154, 109, 71, 69,
            67, 73, 68, 106, 122, 88, 68, 68,
            68, 79, 60, 70, 77, 66, 58, 75,
            69, 85, 64, 58, 55, 61, 65, 83,
            70, 87, 69, 68, 65, 73, 78, 90
        };
        int width = 8;
        int height = 8;
    
        int threshold = otsuThreshold(image, width, height);
        printf("Optimaler Schwellenwert: %d\n", threshold);
    
        segmentImage(image, width, height, threshold);
    
        printf("Segmentiertes Bild:\n");
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                printf("%d ", image[i * width + j]);
            }
            printf("\n");
        }
    
        return 0;
    }
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Finish editing this message first!
    Please register or to comment