5
#include <cv.h>
#include <highgui.h>
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <fstream>

using namespace std;

typedef struct histBundle {
double rCh[256];
double gCh[256];
double bCh[256];
}bundleForHist;

bundleForHist getHistFromImage (IplImage* img, int numBins) {
float range[] = {
    0, 
    numBins
};
float *ranges[] = { 
    range 
};

bundleForHist bfh;

CvHistogram *hist = cvCreateHist (1, &numBins, CV_HIST_ARRAY, ranges, 1);
cvClearHist (hist);
IplImage* imgRed   = cvCreateImage(cvGetSize(img), 8, 1);
IplImage* imgGreen = cvCreateImage(cvGetSize(img), 8, 1);
IplImage* imgBlue  = cvCreateImage(cvGetSize(img), 8, 1);
cvSplit(img, imgBlue, imgGreen, imgRed, NULL);
cvCalcHist(&imgRed, hist, 0, 0);
for (int i = 0; i < numBins; ++i) {
    bfh.rCh[i] = cvQueryHistValue_1D(hist, i);
}
cvClearHist(hist);
cvCalcHist(&imgGreen, hist, 0, 0);
for (int i = 0; i < numBins; ++i) {
    bfh.gCh[i] = cvQueryHistValue_1D(hist, i);
}
cvClearHist(hist);
cvCalcHist(&imgBlue, hist, 0, 0);
for (int i = 0; i < numBins; ++i) {
    bfh.bCh[i] = cvQueryHistValue_1D(hist, i);
}
cvClearHist(hist);
return bfh;
}

int main (int argc, char** argv) {
int c;
IplImage* img = NULL;
int frame_number = 0;
CvCapture* capture = cvCaptureFromAVI ("Cricketc1.avi");
assert(capture);
int fps = ( int )cvGetCaptureProperty( capture, CV_CAP_PROP_FPS );
cvNamedWindow ("Video", 0);

while (1) {
    //IplImage * img = cvLoadImage("C:\\Users\\ANIMES~1\\Desktop\\bw.jpg");
    img = cvQueryFrame(capture);
    frame_number++;
    if (img) {
        cvShowImage("Video", img);
        int numBins = 256;
        bundleForHist bfh;
        bfh = getHistFromImage (img, numBins);
        double totalForR = 0;
        double totalForG = 0;
        double totalForB = 0;
        double probR[256];
        double probG[256];
        double probB[256];
        for (int i = 0; i < numBins-1; ++i) {
            totalForR += bfh.rCh[i];
            totalForG += bfh.gCh[i];
            totalForB += bfh.bCh[i];
        }
        double lengthHistogram = totalForR + totalForG + totalForB;
        for (int i = 0; i < 256; ++i) {
            probR[i] = bfh.rCh[i]/(double)lengthHistogram;
            probG[i] = bfh.gCh[i]/(double)lengthHistogram;
            probB[i] = bfh.bCh[i]/(double)lengthHistogram;
            //file << bfh.rCh[i] << "\t" << bfh.gCh[i] << "\t" << bfh.bCh[i] << "\t" << probR[i] << "\t" << probG[i] << "\t" << probB[i] << "\n";
        }

        double entropyR = 0.0;
        double entropyG = 0.0;
        double entropyB = 0.0;
        for (int i = 0; i < numBins; ++i) {
            entropyR += probR[i]*log(probR[i]);
            entropyG += probG[i]*log(probG[i]);
            entropyB += probB[i]*log(probB[i]);
        }
        cout << frame_number << "\t" << (-1.0)*(entropyR + entropyG + entropyB) << endl;
    }
    c = cvWaitKey(1000/fps);
    if (c == 27)
        break;
}
//cvReleaseImage(&img);
cvReleaseCapture(&capture);
cvDestroyWindow("Video");
return 0;
}

OUTPUT:

.
.
254     -1.#IND
255     -1.#IND
256     -1.#IND
257     -1.#IND
258      5.5686
.
.

I first found the image entropy, which came out to be correct. but nearly 80 % of the frame entropies for the video are coming out to be -1.#IND.

This is the video ....download

What could be going wrong?

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Animesh Pandey
  • 5,900
  • 13
  • 64
  • 130
  • 2 seconds looking into the code shows that you are doing `entropy = blah`. That is not how entropy is calculated, you need to do a sum so you want `entropy += blah`. – mmgp Dec 17 '12 at 19:42
  • Oh! I am sorry ... I did that but still I am getting the output as `-1.#QNAN` ..... – Animesh Pandey Dec 17 '12 at 19:45
  • More 2 seconds looking into it and I see you are returning a local variable at `calcHistProb` and treating it as a pointer later in your program. I really doubt you compile this without getting warnings, and you are ignoring the warnings. Fix all these language issues without ignoring warnings, and edit your code. – mmgp Dec 17 '12 at 19:50
  • @mmgp I have edited the code and all the warnings have been resolved. But still that error is coming .... ! – Animesh Pandey Dec 17 '12 at 20:16
  • referring to this [link](http://stackoverflow.com/questions/7476177/why-the-return-value-of-double-is-1-ind) ... They say there is an illegal operation ... but I cannot find any ... !!!! – Animesh Pandey Dec 17 '12 at 20:19
  • I checked an I found that the index 255 is zero for all the float arrays... this is causing the error .... but I dont know how to correct that ... – Animesh Pandey Dec 17 '12 at 20:37
  • Note that you corrected your original code with the answer, but now this question is meaningless for someone visiting it. You should consider editing your post to actually include the wrong code, so people can understand the meaning of the answer. – mmgp Dec 19 '12 at 19:37

1 Answers1

3

It might be the case that prob[i] = 0 for some i, therefore you are calculating log(0) which is undefined. To fix that you simply discard such "probabilities":

for (int i = 0; i < numBins; ++i) {
    if (prob[i])
        entropy += prob[i]*log(prob[i]);
}

For the other error you found regarding the 0 value in the bin 255, that is due to the range you specified. OpenCV considers the range for the relevant function as [start, end), so specifying a range of [0, 255) is going to ignore the end value of 255. What you want is to keep both 0 and 255, therefore:

float range[] = {0, numBins};
mmgp
  • 18,901
  • 3
  • 53
  • 80
  • I have solved that 0 value problem for an image, I am asking that then how can an error be there for a video .... ???? – Animesh Pandey Dec 18 '12 at 16:34
  • The code wasn't properly fixed in the one that handles the video. – mmgp Dec 18 '12 at 17:05
  • See, you are still doing `probR[i]*log(probR[i]);` and etc in your current code. You are not checking for `probR[i] == 0` before applying `log`. – mmgp Dec 19 '12 at 02:47
  • oh! I had done that .... forgot to post it on the comments ... Everything is fine now ... ! THnks... – Animesh Pandey Dec 19 '12 at 13:42
  • What criteria should I put in while loop so that after the video it automatically breaks out of the loop ? I do not want any cvWaitKey() to do the job! – Animesh Pandey Dec 19 '12 at 20:15
  • `cvQueryFrame` returns NULL after the last frame. – mmgp Dec 19 '12 at 20:24
  • I used that and it solved my problem ... but I noticed on thing that when using `while (cvQueryFrame(capture))` reduced my total frames. The video contains 1250 frames. Using cvQueryFrame, the frame rate of the video changes randomly and loop runs only for 625 frames. It seemed that the video tried to adjust itself in 625 frames. But when I use `while(1)` it shows all frames with same delay. What could be the reason ?? – Animesh Pandey Dec 19 '12 at 20:56