2015-11-13 125 views
0

我試圖使用Otsu的方法來計算閾值。示例圖像是8位,灰度,bmp文件。Otsu閾值

直方圖用於通過以下產生的圖像:

/* INITIALIZE ARRAYS */ 
for(int i = 0; i < 255; i++) occurrence[i] = 0; 
for(int i = 0; i < 255; i++) histogram[i] = 0; 

/* START AT BEGINNING OF RASTER DATA */ 
fseek(input_img, (54 + 4 * color_number), SEEK_SET); 

/* READ RASTER DATA */ 
for(int r = 0; r <= original_img.rows - 1; r++) { 
    for(int c = 0; c <= original_img.cols -1; c++) { 
     fread(p_char, sizeof(char), 1, input_img); 
     pixel_value = *p_char; 
     /* COUNT OCCURRENCES OF PIXEL VALUE */ 
     occurrence[pixel_value] = occurrence[pixel_value] + 1; 
     total_pixels++; 
    } 
} 

for(int i = 0; i <= 255; i++) { 
    /* TAKES NUMBER OF OCCURRENCES OF A PARTICULAR PIXEL 
    * AND DIVIDES BY THE TOTAL NUMBER OF PIXELS YIELDING 
    * A RATIO */ 
    histogram[i] = (float) occurrence[i]/(float) total_pixels; 
} 

直方圖然後被傳遞在主要起作用otsu_method

threshold_value = otsu_method(histogram, total_pixels); 

功能otsu_method

int otsu_method(float *histogram, long int total_pixels) { 
    double omega[256], myu[256]; 
    double max_sigma, sigma[256]; 
    int threshold; 

    omega[0] = histogram[0]; 
    myu[0] = 0.0; 

    for(int i = 1; i < 256; i++) { 
     omega[i] = omega[i - 1] + histogram[i]; 
     myu[i] = myu[i - 1] + i * histogram[i]; 
    } 

    threshold = 0; 
    max_sigma = 0.0; 

    for(int i = 0; i < 255; i++) { 
     if(omega[i] != 0.0 && omega[i] != 1.0) 
      sigma[i] = pow(myu[255] * omega[i], 2)/(omega[i] * (1.0 - omega[i])); 
     else 
      sigma[i] = 0.0; 
     if(sigma[i] > max_sigma) { 
      max_sigma = sigma[i]; 
      threshold = i; 
     } 
    } 

    printf("Threshold value: %d\n", threshold); 

return threshold; 
} 

而基於二值化圖像閾值:

void threshold_image(FILE* input_file, FILE* output_file, unsigned long vector_size, int threshold_value) { 
    unsigned char* p_char; 
    unsigned char dummy; 
    struct_img  binary_img; 
    unsigned char* binary_data; 

    dummy = '0'; 
    p_char = &dummy; 

    binary_img.data = malloc(vector_size * sizeof(char)); 
    if(binary_img.data == NULL) printf("Failed to malloc binary_img.data\n"); 

    binary_data = binary_img.data; 

    /* CONVERT PIXEL TO BLACK AND WHITE BASED ON THRESHOLD VALUE */ 
    for(int i = 0; i < vector_size - 1; i++) { 
     fread(p_char, sizeof(char), 1, input_file); 
     if(*p_char < threshold_value) *(binary_data + i) = 0; 
     else *(binary_data + i) = 255; 
     fwrite((binary_data + i), sizeof(char), 1, output_file); 
    } 

    /* FREE ALLOCATED MEMORY */ 
    free(binary_data); 
} 

程序輸出:

Reading file 512gr.bmp 
Width: 512 
Height: 512 
File size: 263222 
# Colors: 256 
Vector size: 262144 
Total number of pixels: 262144 
Threshold value: 244 

我覺得244是不是正確計算的閾值,因爲當所有像素功能threshold_image值化圖像轉換爲黑色。

如果我跳過otsu_method並從用戶輸入函數threshold_image中獲得閾值,可以正常工作。

功能otsu_method是複製粘貼的代碼,因此我對變量或條件並不清楚。 我正在學習圖像處理,並試圖找出基本知識。任何關於Otsu算法的信息和關於我的代碼的任何反饋都會有所幫助。

回答

0

我發現是什麼原因造成的問題,改變功能otsu_method:

int otsu_method(float *histogram, long int total_pixels) { 
    double probability[256], mean[256]; 
    double max_between, between[256]; 
    int threshold; 

    /* 
    probability = class probability 
    mean = class mean 
    between = between class variance 
    */ 

    for(int i = 0; i < 256; i++) { 
     probability[i] = 0.0; 
     mean[i] = 0.0; 
     between[i] = 0.0; 
    } 

    probability[0] = histogram[0]; 

    for(int i = 1; i < 256; i++) { 
     probability[i] = probability[i - 1] + histogram[i]; 
     mean[i] = mean[i - 1] + i * histogram[i]; 
    } 

    threshold = 0; 
    max_between = 0.0; 

    for(int i = 0; i < 255; i++) { 
     if(probability[i] != 0.0 && probability[i] != 1.0) 
      between[i] = pow(mean[255] * probability[i] - mean[i], 2)/(probability[i] * (1.0 - probability[i])); 
    else 
     between[i] = 0.0; 
     if(between[i] > max_between) { 
      max_between = between[i]; 
      threshold = i; 
     } 
    } 

    return threshold; 
} 

真正的不同:

between[i] = pow(mean[255] * probability[i] - mean[i], 2)/(probability[i] * (1.0 - probability[i])); 

程序輸出:

Reading file 512gr.bmp 
Width: 512 
Height: 512 
File size: 263222 
# Colors: 256 
Vector size: 262144 
Total number of pixels: 262144 

Threshold value: 117 
Probability: 0.416683 
Mean: 31.9631 
Between varaince: 1601.01