0

我在 Visual Studio 2012 中使用 OpenCV 库使用 C++。问题是当我运行我的控制台应用程序时,大约 2 或 3 秒后它会关闭。继承人的代码:

#include "cv.h"
#include "highgui.h"

IplImage* GetThresholdedImage(IplImage *img)
{
    // Convert the image into an HSV image
    IplImage* imgHSV = cvCreateImage(cvGetSize(img), 8, 3);

    cvCvtColor(img, imgHSV, CV_BGR2HSV);

    IplImage* imgThreshed = cvCreateImage(cvGetSize(img), 8, 1);

    cvInRangeS(imgHSV, cvScalar(20, 100, 100), cvScalar(30, 255, 255), imgThreshed); //Detect Colour

    cvReleaseImage(&imgHSV);
    return imgThreshed;
}

int main()
{
    // Initialize capturing live feed from the camera
    CvCapture* capture = 0;
    capture = cvCaptureFromCAM(0); // cvCaptureFromCAM(0) indicates camera being used,           Change the 0 for a different camera

    // Couldn't get a device? Throw an error and quit
    if(!capture)
    {
        printf("Camera not working\n");
        return -1;
    }

 // The two windows we'll be using
cvNamedWindow("video"); //Create new window containing video
cvNamedWindow("thresh"); //Create another window containing thresholded image

// This image holds the "scribble" data
// the tracked positions of the ball
IplImage* imgScribble = NULL;

// An infinite loop
while(true)
{
    // Will hold a frame captured from the camera
    IplImage* frame = 0;
    frame = cvQueryFrame(capture);

    // If we couldn't grab a frame... quit
    if(!frame)
        printf("Couldnt get frame \n");



     // If this is the first frame, we need to initialize it
    if(imgScribble == NULL)
    {
        imgScribble = cvCreateImage(cvGetSize(frame), 8, 3);
    }

    // Holds the yellow thresholded image (yellow = white, rest = black)
    IplImage* imgYellowThresh = GetThresholdedImage(frame);

    // Calculate the moments to estimate the position of the ball
    CvMoments *moments = (CvMoments*)malloc(sizeof(CvMoments));
    cvMoments(imgYellowThresh, moments, 1);

    // The actual moment values
    double moment10 = cvGetSpatialMoment(moments, 1, 0);
    double moment01 = cvGetSpatialMoment(moments, 0, 1);
    double area = cvGetCentralMoment(moments, 0, 0);

    // Holding the last and current ball positions
    static int posX = 0;
    static int posY = 0;

    int lastX = posX;
    int lastY = posY;

    posX = moment10/area;
    posY = moment01/area;

    // Print it out for debugging purposes
    printf("position (%d,%d)\n", posX, posY);

    // We want to draw a line only if its a valid position
    if(lastX>0 && lastY>0 && posX>0 && posY>0)
    {
        // Draw a yellow line from the previous point to the current point
        cvLine(imgScribble, cvPoint(posX, posY), cvPoint(lastX, lastY), cvScalar(0,255,255), 5);
    }

     // Add the scribbling image and the frame
    cvAdd(frame, imgScribble, frame);
    cvShowImage("thresh", imgYellowThresh);
    cvShowImage("video", frame);

    // Release the thresholded image+moments we need no memory leaks please
    cvReleaseImage(&imgYellowThresh);
    delete moments;

        // We're done using the camera. Other applications can now use it
    cvReleaseCapture(&capture);
    return 0;

    // Wait for a keypress
    int c = cvWaitKey(10);
    if(c!=-1)
    {
        // If pressed, break out of the loop
        break;
    }

}
}

我的相机工作正常,但它仍然退出。提前致谢

4

3 回答 3

1

我认为

// We're done using the camera. Other applications can now use it

cvReleaseCapture(&capture);

返回0;

必须在 while 循环体之外。

于 2013-08-04T13:12:20.020 回答
1

您将两种分配/释放内存的方式混合在一起 -malloc/freenew/delete

CvMoments *moments = (CvMoments*)malloc(sizeof(CvMoments));

delete moments;

您不应该将两者混为一谈。malloc/free不要在分配的内存上调用构造函数/析构函数。new/delete在分配的内存上调用构造函数/析构函数,并且可能使用其他内存函数而不是malloc/free分配/释放实际内存。结果,您可能会遇到各种各样的错误,从调用非构造对象的析构函数到使用不对应的函数来分配/释放内存。

另外,当然可能还有其他问题。这是一个显而易见的问题,您应该从修复它开始。

编辑#1:虽然上面所说的一切都是正确的并且应该修复,但安德烈·斯莫罗多夫的回答可能已经确定了:你无条件地return来自循环内部。看到问题后,我不应该停止检查您的代码malloc/delete;)。

编辑#2:回答您的评论。如果CvMoments是 C 结构,请使用free而不是delete. 如果它是 C++ 类,请使用new而不是malloc.

您还必须在循环结束时查看代码。很难说你想在那里做什么。从外观上看,我会moments在循环之前分配内存,在循环之后释放内存——你会继续分配/释放相同数量的内存。你甚至需要它在堆上吗?你不能把它放在堆栈上吗?您似乎还想继续使用相机,直到用户按下一个键。您是否需要在用户按下某个键后或每次开始等待之前释放相机?无论如何,您的语句在控制进入语句之前return退出循环和(和程序) 。将语句放在循环之外。mainifreturn

简而言之:

循环前 - 分配内存。记得使用malloc/freeor new/delete,但不要混合使用。想想如果你需要堆,也许堆栈就可以了。

在循环中 - 删除释放内存,删除释放相机,删除return. 您将在下一次循环中使用它们,对吗?如果用户按下一个键(在循环内),您将退出循环。

循环之后 - 现在你真的想要清理。释放内存,释放相机,returnmain.

于 2013-08-04T12:22:43.177 回答
1

malloc 和 delete 不能一起使用,请使用 free(ptr) 代替。

于 2013-08-04T12:22:57.530 回答