0
$\begingroup$

I am trying to measure contrast of image by entropy of histogram of image.

Code for computing entropy

float measureContrast_inImage(Mat imagel) {

    Mat hist;
    /// Establish the number of bins
    int histSize = 256;
    /// Set the ranges ( for B,G,R) )
    float range[] = { 0, 256 };
    const float* histRange = { range };
    bool uniform = true; bool accumulate = false;
    /// Compute the histograms:
    calcHist(&imagel, 1, 0, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate);
    hist /= imagel.total();

    Mat logP;
    cv::log(hist, logP);

    cv::imshow("logP", logP);

    //Performs an element-wise multiplication or division of the two matrices
    float entropy = -1 * sum(hist.mul(logP)).val[0];

    cout << entropy << endl;

    //float entropy = 0;

    waitKey(0);
    return entropy;
}

Lena image enter image description here

But entropy is -nan(ind)

similarly, entropy is undefined for another Image.

enter image description here

Entropy is 5.29657 for another image. enter image description here

Is there any problem in my code.

I wonder that why in low contrast image, entropy is undefined. Kindly help me to figure out.

Edited

I computed histogram and get entropy by the following code and my entropy is 256

float entropy(Mat seq, Size size, int index)
{

    int cnt = 0;

    float entr = 0;

    float total_size = size.height * size.width; //total size of all symbols in an image

    for (int i = 0; i<index; i++)
    {

        float sym_occur = (float)seq.at<uchar>(0, i); //the number of times a sybmol has occured

        if (sym_occur>0) //log of zero goes to infinity

        {

            cnt++;

            entr += (sym_occur / total_size)*(log2(total_size / sym_occur));

        }
    }

    cout << "cnt: " << cnt << endl;

    return entr;
}

void imhist(Mat image, int histogram[])
{
    // initialize all intensity values to 0
    for (int i = 0; i < 256; i++)
    {
        histogram[i] = 0;
    }

    // calculate the no of pixels for each intensity values
    for (int y = 0; y < image.rows; y++)
        for (int x = 0; x < image.cols; x++)
            histogram[(int)image.at<uchar>(y, x)]++;
}

Mat histDisplay(int histogram[], const char* name)
{
    int hist[256];
    for (int i = 0; i < 256; i++)
    {
        hist[i] = histogram[i];
    }
    // draw the histograms
    int hist_w = 512; int hist_h = 400;
    int bin_w = cvRound((double)hist_w / 256);

    Mat histImage(hist_h, hist_w, CV_8UC1, Scalar(255, 255, 255));

    // find the maximum intensity element from histogram
    int max = hist[0];
    for (int i = 1; i < 256; i++) {
        if (max < hist[i]) {
            max = hist[i];
        }
    }

    // normalize the histogram between 0 and histImage.rows

    for (int i = 0; i < 256; i++) {
        hist[i] = ((double)hist[i] / max)*histImage.rows;
    }


    // draw the intensity line for histogram
    for (int i = 0; i < 256; i++)
    {
        /*line(histImage, cvPoint(bin_w*(i), hist_h),
        cvPoint(bin_w*(i), hist_h - hist[i]),
        Scalar(0, 0, 0), 1, 8, 0);*/
        line(histImage, cvPoint(bin_w*(i), hist_h),
            cvPoint(bin_w*(i), hist_h - hist[i]),
            Scalar(0, 0, 0));
    }

    // display histogram
    //namedWindow(name, CV_WINDOW_AUTOSIZE);
    //imshow(name, histImage);
    return histImage;
}

int main () {
    Mat image = imread("lena.png", CV_LOAD_IMAGE_GRAYSCALE);
    int hist[256];
    imhist(image, hist);
    Mat histImg = histDisplay(hist, "hist");

    float en = entropy(histImg, image.size(), 256);
}

I believe that it is still wrong. Please correct me .

$\endgroup$
  • $\begingroup$ You can put your code in a try-catch block and then you'll be able to catch the line that is causing the exception (just put a breakpoint somewhere in your catch block). $\endgroup$ – dsp_user Nov 29 '17 at 8:11
1
$\begingroup$

You are getting a nan returned because you are performing an operation that yields undefined result.

Based on your code, the only option I can see is the log operater that theoretically yields $-\infty$ when you attempt to take the logarithm of a 0-valued pixel. C++ will thus consider it not a number. Other functions I have seen for calculating entropy such as this example in octave, just ignore the zero pixels to solve these cases.

$\endgroup$
  • $\begingroup$ so you mean iterate every intensity frequency and check if it is > 0, $\endgroup$ – Abc Nov 29 '17 at 8:23
  • $\begingroup$ Correct, but since you shouldn't have to expect negative values I would just check for intensity values not equal to zero and throw exception if the are bellow. thus, you won't miss innapropriate images for the method. $\endgroup$ – David Bondesson Nov 29 '17 at 8:51
  • $\begingroup$ i tried it. but there is another problem i got .How can i share it? Should i edit my question? or i should post another question ? $\endgroup$ – Abc Nov 29 '17 at 10:19
  • $\begingroup$ Also, cam i use histogram in int values? $\endgroup$ – Abc Nov 29 '17 at 10:35
  • $\begingroup$ Please check me edited question. $\endgroup$ – Abc Nov 29 '17 at 10:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.