【问题标题】:CImg: Image binarization result failsCImg:图像二值化结果失败
【发布时间】:2016-02-15 01:43:56
【问题描述】:

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

很长一段时间以来,我一直在寻找代码中的任何错误,但没有发现任何对我来说似乎有问题的地方。

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

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

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

【问题讨论】:

    标签: c++ image algorithm image-processing


    【解决方案1】:

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

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

    【讨论】:

    • 非常感谢。它终于起作用了!难怪指针问题可以显着改变情况......
    猜你喜欢
    • 1970-01-01
    • 2014-06-07
    • 2017-02-20
    • 2015-05-20
    • 1970-01-01
    • 2020-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多