CImg:图像二值化结果失败

时间:2015-11-13 13:03:37

标签: c++ image algorithm image-processing

因此,以下代码中的问题是图像二值化的结果变得太暗。 (甚至有一个示例图像我的二进制图像变成全黑。)

我一直在搜索我的代码中的任何错误很长一段时间,并且没有发现任何看起来对我来说有问题。

下面是我要二值化的图片:

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

下面是生成的二进制图像:

Image after binarized

在我向您展示我的源代码之前,这里是图像二值化中的“规则”(因为这是我最近得到的一项任务):

  1. 我不允许使用除CImg之外的任何其他库。
  2. 使用的编程语言是C / C ++。不是别的。
  3. 通常,Otsu的方法是选择。但是,如果它更好,我可能会被允许使用其他算法。
  4. 最后,这是我的源代码:

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

    如果您发现其他算法效果更好,请在答案中提供算法和源代码。谢谢你的关注。

1 个答案:

答案 0 :(得分:0)

第一个错误:您尝试return一个数组的指针,它会在generate_histogram函数结束后立即被销毁。 为了使其正常工作,您应该从调用函数提供指向数组的指针,如:

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

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