0

OpenCVライブラリを使用してVisual Studio 2012で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

メモリの割り当て/解放の2つの方法を混ぜ合わせています-malloc/freeおよびnew/delete:

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

delete moments;

2 つを混ぜてはいけません。malloc/free割り当てられたメモリでコンストラクター/デストラクターを呼び出さないでください。new/delete割り当てられたメモリでコンストラクタ/デストラクタを呼び出しmalloc/freeます。実際のメモリを割り当て/解放する代わりに、他のメモリ関数を使用している可能性があります。その結果、構築されていないオブジェクトでデストラクタを呼び出すことから、対応しない関数を使用してメモリを割り当て/解放することまで、さまざまな理由から発生するあらゆる種類のエラーが発生する可能性があります。

さらに、もちろん、他の問題が発生する可能性もあります。これは明らかなものであり、修正することから始めるべきです。

編集#1:上記のすべてが真実であり、修正する必要がありますが、アンドレイ・スモロドフの答えはおそらくそれを釘付けにしました:無条件returnにループ内から。問題を見つけた後、コードのチェックをやめるべきではありませんでしたmalloc/delete;)。

編集#2:あなたのコメントに答えるために。CvMomentsが C 構造体の場合は、free代わりに を使用しdeleteます。C++ クラスの場合は、new代わりにmalloc.

また、ループの最後にあるコードを確認する必要があります。そこでやりたいことを言うのは難しいです。見た目では、ループのmoments前にメモリ割り当てを配置し、ループの後にメモリを解放します-同じ量のメモリを割り当て/解放し続けます。ヒープでも必要ですか?スタックに置くことはできませんか?また、ユーザーがキーを押すまでカメラを操作し続けたいと思われます。ユーザーがキーを押した後、またはキーを待つ前に毎回カメラを解放する必要がありますか? いずれの場合でも、制御がステートメントに移動する前に、returnステートメントはループを終了しmain(およびプログラム)ifます。returnステートメントをループの外側に置きます。

要するに:

ループ前 - メモリを割り当てます。malloc/freeまたはを使用することを忘れないnew/deleteでください。ただし、それらを混在させないでください。ヒープが必要な場合は、おそらくスタックで問題ないと考えてください。

ループ内 - 解放メモリを削除し、解放カメラを削除し、return. 次のループでそれらを使用しますよね?ユーザーが(ループ内で)キーを押すと、ループから抜けます。

ループの後 - 今、あなたは本当にクリーンアップしたいと思っています. からメモリを解放し、カメラを解放returnmainます。

于 2013-08-04T12:22:43.177 に答える
1

malloc と delete を一緒に使用することはできません。代わりに free(ptr) を使用してください。

于 2013-08-04T12:22:57.530 に答える
1

おもう

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

cvReleaseCapture(&キャプチャー);

0 を返します。

while ループ本体の外にある必要があります。

于 2013-08-04T13:12:20.020 に答える