c ++中的函数不能计算正确的结果,但是在添加cout时它会给出正确的结果

时间:2013-06-12 09:19:06

标签: c++ function opencv ofstream

#include <stdio.h>  // For printf()
#include <cv.h>     // Main OpenCV library.
#include <highgui.h>    // OpenCV functions for files and graphical windows.
#include<ml.h>
#include<fstream>
using namespace std;
using namespace cv;

class imagepro {
    int MOMpq(int p, int q, float xt, float yt, float* x, float* y, int size) {

        float u[size];
        float v[size];

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

            u[i] = x[i];
            v[i] = y[i];
        }

        for (int i = 0; i < size; i++) {
            u[i] = u[i] - xt;
            v[i] = v[i] - yt;

        }

        for (int i = 0; i < size; i++) {
            u[i] = pow(u[i], p);
            v[i] = pow(v[i], q);
        }
        float mpq = 0;

        for (int j = 0; j <= size; j++) {
            mpq = mpq + (u[j] * v[j]);
        }

        return mpq;
    }
public:

    void getFeatures(Mat img, long double* feat) {

        float x[img.rows * img.cols];
        float y[img.rows * img.cols];
        int k = 0;
        for (int i = 0; i < img.rows; i++) {
            for (int j = 0; j < img.cols; j++) {
                int n = (int) img.at<uchar>(i, j);
                if (n == 255) {
                    x[k] = i;
                    y[k] = j;
                    k++;
                }

            }
        }

        //find COG
        float a1 = 0;
        float b1 = 0;
        for (int i = 0; i < k; i++) {
            a1 = a1 + x[i];
            b1 = b1 + y[i];
        }
        float arr[2];
        arr[0] = a1 / k;
        arr[1] = b1 / k;
        //find moments
        float m00 = MOMpq(0, 0, arr[0], arr[1], x, y, k);
        float m20 = MOMpq(2, 0, arr[0], arr[1], x, y, k);
        float m02 = MOMpq(0, 2, arr[0], arr[1], x, y, k);
        float m11 = MOMpq(1, 1, arr[0], arr[1], x, y, k);
        float m30 = MOMpq(3, 0, arr[0], arr[1], x, y, k);
        float m03 = MOMpq(0, 3, arr[0], arr[1], x, y, k);
        float m21 = MOMpq(2, 1, arr[0], arr[1], x, y, k);
        float m12 = MOMpq(1, 2, arr[0], arr[1], x, y, k);
        float m22 = MOMpq(2, 2, arr[0], arr[1], x, y, k);
        float m13 = MOMpq(1, 3, arr[0], arr[1], x, y, k);
        float m31 = MOMpq(3, 1, arr[0], arr[1], x, y, k);
        float m04 = MOMpq(0, 4, arr[0], arr[1], x, y, k);
        float m40 = MOMpq(4, 0, arr[0], arr[1], x, y, k);

        //Find Affine moments invariants

        //cout<<m00<<" "<<m20<<" "<<m02<<" "<<m11<<"\n";

        long double I1 = ((m02 * m20) - (m11 * m11)) / (pow(m00, 4));

        long double I2 = ((m30 * m30 * m03 * m03) - (6 * m03 * m30 * m21 * m12)
                + (4 * m30 * (pow(m12, 3))) + (4 * m03 * (pow(m21, 3)))
                - (3 * m21 * m21 * m12 * m12)) / ((long double) pow(m00, 10));

        long double I3 = ((m20 * m21 * m03) - pow(m12, 2)
                - (m11 * m30 * m03 - m21 * m12)
                + (m02 * m12 * m30 - (pow(m21, 2))))
                / ((long double) pow(m00, 7));

        long double I4 = ((long double) pow(m20, 3) * pow(m03, 2)
                - ((long double) 6 * pow(m20, 2) * m11 * m12 * m03)
                - ((long double) 6 * pow(m20, 2) * m02 * m21 * m03)
                + ((long double) 9 * pow(m20, 2) * m02 * pow(m12, 2))
                + ((long double) 12 * m20 * m21 * m03 * pow(m11, 2))
                + ((long double) 6 * m02 * m20 * m30 * m03 * m11)
                - ((long double) 18 * m20 * m02 * m11 * m21 * m12)
                - ((long double) 8 * pow(m11, 3) * m03 * m30)
                - ((long double) 6 * pow(m02, 2) * m20 * m30 * m12)
                + ((long double) 9 * pow(m02, 2) * pow(m21, 2) * m20)
                + ((long double) 12 * m02 * m30 * m12 * pow(m11, 2))
                - ((long double) 6 * m11 * m30 * m21 * pow(m02, 2))
                + ((long double) pow(m02, 3) * pow(m30, 2)))
                / ((long double) pow(m00, 11));

        long double I5 = ((m40 * m04 * m22) + (2 * m22 * m13 * m31)
                - (m40 * pow(m13, 2)) - (m04 * pow(m31, 2)) - pow(m22, 3))
                / pow(m00, 9);

        long double I6 = ((m40 * m04) - (4 * m13 * m31) + (3 * m22 * m22))
                / ((long double) pow(m00, 6));

        //cout<<I1<<" "<<I2<<" "<<I3<<","<<I4<<","<<I5<<","<<I6<<" \n";
        //cout<<"";

        feat[0] = I1;
        feat[1] = I2;
        feat[2] = I3;
        feat[3] = I4;
        feat[4] = I5;
        feat[5] = I6;

    }

};

int main() {

    char* filename = "caps.txt";

    ifstream readFile(filename);
    string line;
    string str = "OCR/EnglishHnd/English/Hnd/";

    ofstream outputFile("features.txt",
            std::ios_base::app);

    if (readFile.is_open()) {

        while (readFile >> line) {
            string location = line;
            long double feat[6];
            Mat im_gray = imread(str + line, CV_LOAD_IMAGE_GRAYSCALE);
            Mat img_bw = im_gray > 128;
            threshold(img_bw, img_bw, 0, 255, CV_THRESH_BINARY_INV);

            resize(img_bw, img_bw, Size(256, 256));

            imagepro obj;
            obj.getFeatures(img_bw, feat);
            //obj=NULL;
            cout << feat[0] << " " << feat[1] << " " << feat[2] << " "
                    << feat[3] << " " << feat[4] << " " << feat[5] <<    "\n";
            cout.flush();
            outputFile << feat[0] << " " << feat[1] << " " << feat[2] << " "
                    << feat[3] << " " << feat[4] << " " << feat[5] << "\n";
            outputFile.flush();

        }
        outputFile.close();
    }

    readFile.close();

    //waitKey(0);
    return 0;

}

对于许多图像,返回相同特征数组的值表示[x,y,z,u,v,w],并且此特征数组与任何图像都不对应。但当我把“cout<<m00<<" "<<m20<<" "<<m02<<" "<<m11<<"\n"; 在函数getfeatures()中它给出了正确的值。这里发生了什么?我完全失去了..请帮助..

2 个答案:

答案 0 :(得分:0)

Vikas,只需将getfeatures方法的返回类型从“int”更改为“float”即可。 返回时返回'return mpq',将float转换为int,然后再转换为float,因此在它们之间进行舍入。

答案 1 :(得分:-1)

尝试动态分配x[]y[],而不是在堆栈上分配它。如果您的图片是256x256*2*sizeof(float)

,AFAIK会分配大约500k

完成后不要忘记释放内存。

由于该函数在完成后不使用该数组,因此您也可以全局或静态地分配它,因此您不需要多次分配和释放它。

<强>更新

解决问题的快速而肮脏的方法是:

 void getFeatures(Mat img, long double* feat, float *x, float *y)
 {
    int k = 0;
   ...
    a = x[n];
}

main()
{
    float *x = new float[256*256];
    float *y = new float[256*256];

    while()
    {
        obj.getFeatures(img_bw, feat, x, y);
    }

delete [] x;
delete [] y;
 }

但是,如果重用此类,则应考虑添加一个constractur,您可以在其中传入大小或图像,并分配内存并在析构函数中释放它。上面的方法并不是很安全,因为你没有检查内存的大小等等,所以这应该在类本身IMO中处理。

从上面的示例开始,此代码假定所有图像的内存大小始终保持不变,并且不会被使用。如果这个假设发生变化,这个代码当然会破裂。