2015-11-13 2 views
1

Итак, проблема в моем следующем коде заключается в том, что результат бинаризации изображения становится слишком темным. (Был даже пример изображения, у которого бинарное изображение становится полностью черным.)CImg: результат бинаризации изображения не получается

Я долгое время искал любую ошибку в своем коде и не нашел ни одного, что кажется мне проблематичным.

Ниже изображение, которое я хочу бинаризации:

Image before binarized - in my code is named: "hildebrantmed.bmp"

Ниже результирующее бинарное изображение:

Image after binarized

Прежде чем я покажу вам мой исходный код, здесь являются " правила "в бинаризации изображения (так как это назначение, которое я недавно получил):

  1. Мне не разрешено использовать любые другие библиотеки, кроме CImg.
  2. Язык программирования для использования - C/C++. Ничего другого.
  3. Как правило, метод Otsu является выбором. Однако мне может быть позволено использовать другие алгоритмы, если это лучше.

Наконец, вот мой исходный код:

#include <iostream> 
#include <CImg.h> 

using namespace std; 
using namespace cimg_library; 

/** 
* Generate histogram of the grayscale image 
*/ 
int * generate_histogram(CImg<unsigned char> img) 
{ 
    int histogram[256]; 

    // initialize default values for histogram 
    for (int i = 0; i < 256; i++) 
    { 
     histogram[i] = 0; 
    } 

    // increment intensity for histogram 
    for (int i = 0; i < img.height(); i++) 
    { 
     for (int j = 0; j < img.width(); j++) 
     { 
      int gray_value = img(j, i, 0, 0); 
      histogram[gray_value]++; 
     } 
    } 

    return histogram; 
} 

/** 
* Find threshold value from the grayscale image's histogram 
*/ 
int otsu_threshold(CImg<unsigned char> img) 
{ 
    int * histogram = generate_histogram(img); // image histogram 

    int total = img.width() * img.height(); // total pixels 

    double sum = 0; 

    int i; 
    for (i = 0; i < 256; i++) 
    { 
     sum += i * histogram[i]; 
    } 

    double sumB = 0; 
    int wB = 0; 
    int wF = 0; 

    double var_max = 0; 
    int threshold = 0; 

    for (i = 0; i < 256; i++) 
    { 
     wB += histogram[i]; 
     if (wB == 0) continue; 

     wF = total - wB; 
     if (wF == 0) continue; 

     sumB += (double)(i * histogram[i]); 

     double mB = sumB/wB; 
     double mF = (sum - sumB)/wF; 

     double var_between = (double)wB * (double)wF * (mB - mF) * (mB - mF); 

     if (var_between > var_max) 
     { 
      var_max = var_between; 
      threshold = i; 
     } 
    } 

    return threshold; 
} 

/** 
* Main function 
*/ 
int main(int argc, char * argv[]) 
{ 
    // retrieve image from its path 
    CImg<unsigned char> img("hildebrantmed.bmp"); 

    const int width = img.width(); 
    const int height = img.height(); 

    // initialize a new image for img's grayscale 
    CImg<unsigned char> gray_img(width, height, 1, 1, 0); 

    // from RGB divided into three separate channels 
    CImg<unsigned char> imgR(width, height, 1, 3, 0); 
    CImg<unsigned char> imgG(width, height, 1, 3, 0); 
    CImg<unsigned char> imgB(width, height, 1, 3, 0); 

    // for all (x, y) pixels in image 
    cimg_forXY(img, x, y) 
    { 
     imgR(x, y, 0, 0) = img(x, y, 0, 0), 
     imgG(x, y, 0, 1) = img(x, y, 0, 1), 
     imgB(x, y, 0, 2) = img(x, y, 0, 2); 

     // separate the channels 
     int R = (int)img(x, y, 0, 0); 
     int G = (int)img(x, y, 0, 1); 
     int B = (int)img(x, y, 0, 2); 

     // obtain gray value from different weights of RGB channels 
     int gray_value = (int)(0.299 * R + 0.587 * G + 0.114 * B); 
     gray_img(x, y, 0, 0) = gray_value; 
    } 

    // find threshold of grayscale image 
    int threshold = otsu_threshold(gray_img); 

    // initialize a binary image version of img 
    CImg<unsigned char> binary_img(width, height, 1, 1, 0); 

    // for every (x, y) pixel in gray_img 
    cimg_forXY(img, x, y) 
    { 
     int gray_value = gray_img(x, y, 0, 0); 

     // COMPARE gray_value with threshold 
     int binary_value; 

     // gray_value > threshold: 255 (white) 
     if (gray_value > threshold) binary_value = 255; 
     // gray_value < threshold: 0 (black) 
     else binary_value = 0; 

     // assign binary_value to each of binary_img's pixels 
     binary_img(x, y, 0, 0) = binary_value; 
    } 

    // display the images 
    CImgDisplay src_disp(img, "Source image"); 
    CImgDisplay gray_disp(gray_img, "Grayscale image"); 
    CImgDisplay binary_disp(binary_img, "Binary image"); 

    while (!src_disp.is_closed() && !gray_disp.is_closed() && !binary_disp.is_closed()) 
    { 
     src_disp.wait(); 
     gray_disp.wait(); 
    } 

    return 0; 
} 

Если вы обнаружите, что другой алгоритм будет работать лучше, пожалуйста, предоставьте с помощью алгоритма и исходного кода в вашем ответе. Спасибо за внимание.

ответ

0

Ошибка: вы пытаетесь установить return указатель массива, который фактически уничтожается, как только заканчивается функция generate_histogram. Для того, чтобы она работала правильно, вы должны поставить указатель на массив из вызывающей функции, что-то вроде:

{ 
//[....] 
int histogram[256]; 
generate_histogram(img, histogram); 
//[....] 
} 

int * generate_histogram(CImg<unsigned char> img, int* arHistogram) 
{ 
//[....] 
} 
+0

Спасибо так много. Он работает наконец! Неудивительно, что проблема с указателями может значительно изменить картину ... –

+0

Рад, что я мог бы помочь, я все еще сам ученик низкого уровня. –

Смежные вопросы