Q:

Error Using CvMoments to calculate the HU moments

I am doing my FYP and I am a bit new to both OpenCV and C++. I have looked for info regarding CvMoments and all i found (in theory examples that work) do not solve my problem. I want to load a set of images ("1.png" to "5.png") and write the HU moments into a text file. The code is as shows:
CvMoments moments;
CvHuMoments hu_moments;
char filename[80] = "";

ofstream myfile;
myfile.open ("HU_moments.txt");

for (int i=0;i<5;i++){
    sprintf(filename,"%u.png",i);
    IplImage* image = cvLoadImage(filename);

    cvMoments(image,&moments);
    cvGetHuMoments(&moments, &hu_moments);

    myfile << "Hu1: " << hu_moments.hu1 <<
              "Hu2: " << hu_moments.hu2 <<
              "Hu3: " << hu_moments.hu3 <<
              "Hu4: " << hu_moments.hu4 <<
              "Hu5: " << hu_moments.hu5 <<
              "Hu6: " << hu_moments.hu6 <<
              "Hu7: " << hu_moments.hu7 << ".\n";
    cvReleaseImage(&image);
}
myfile.close();

The problem occurs when i get to cvMoments(image,&moments). I get: 
Unhandled exception at 0x759fb9bc in Viewer.exe: Microsoft C++ exception: cv::Exception at memory location 0x002fce00..
I have tried declaring moments as a pointer (with its corresponding melloc) but still i get the same error. The funny thing is if i click the option to continue debugging (5 times, one for each loop) i will get results that are printed into my text file. i am using visual studio 2008.
I hope someone knows what is going on here and how to solve.

A:

You are calling it right, but I suspect that your problem is that the previous call is failing:
IplImage* image = cvLoadImage(filename);

You need to check the result of cvLoadImage() and make sure that you are passing a valid argument to cvMoments():
IplImage* image = cvLoadImage(filename);
if (!image)
{
   cout << "cvLoadImage() failed!" << endl;  
   // deal with error! return, exit or whatever
}

cvMoments(image, &moments);

It's also a good idea to check if myfile was successfully opened.
The root of the problem, according to my crystal ball, is a misconception of where you should put the files that the application needs to load when its executed from Visual Studio, and that would be the directory where your source code files are. 
If you put the image files on the same directory as the source code, you should be OK.
On the other hand, when you execute your application manually (by double clicking the executable), the image files need to be in the same directory as the executable.
EDIT:
I'm convinced that cvMoments() takes a single-channel image as input. This example doesn't throw any exceptions:
CvMoments moments;
CvHuMoments hu_moments;

IplImage* image = cvLoadImage(argv[1]);
if (!image)
{   
    std::cout << "Failed cvLoadImage\n";
    return -1; 
}   

IplImage* gray = cvCreateImage(cvSize(image->width, image->height), image->depth, 1); 
if (!gray)
{   
    std::cout << "Failed cvCreateImage\n";
    return -1; 
}   

cvCvtColor(image, gray, CV_RGB2GRAY);

cvMoments(gray, &moments, 0); 
cvGetHuMoments(&moments, &hu_moments);

cvReleaseImage(&image);
cvReleaseImage(&gray);

Before converting the colored image to gray, I was getting:
OpenCV Error: Bad argument (Invalid image type) in cvMoments, file OpenCV-2.3.0/modules/imgproc/src/moments.cpp, line 373
terminate called after throwing an instance of 'cv::Exception'
OpenCV-2.3.0/modules/imgproc/src/moments.cpp:373: error: (-5) Invalid image type in function cvMoments

