9

OpenCV を使用して単純なブロブ追跡を作成しようとしています。findcontours を使用してブロブを検出しました。これらのブロブに定数 ID を付与したいと考えています。

前のフレームと現在のフレームのブロブのリストを収集しました。次に、前のフレームと現在のフレームの各ブロブ間の距離を取りました。ブロブを追跡して ID を付与するために他に何が必要か知りたいです。前のフレーム ブロブと現在のフレーム ブロブの間の距離を取得しましたが、ブロブ間の測定距離を使用して一貫した ID をブロブに割り当てるにはどうすればよいでしょうか?

4

3 に答える 3

9

最初のフレームでは、任意の方法で id を割り当てることができます。最初に見つかったものには 1、2 番目のものには 2... または、コレクション内の位置に従って単純に ID を与えます。

次に、次のフレームでベストマッチを使用する必要があります。ブロブを見つけ、現在のブロブと前の画像のすべてのブロブの間のすべての距離を計算し、前の各 ID を最も近いブロブに割り当てます。フィールドに入ったばかりのブロブは、新しい ID を取得します。

これで 2 つのフレームができたので、次のフレームの動き予測を行うことができます。ブロブの以前の位置と現在の位置の間の deltaX と deltaY を計算するだけです。この情報を使用して、将来の位置を推測できます。この将来の位置と照合します。

これは、重なっているブロブが多くない場合、および各フレーム間で動きが速すぎず不安定でない場合に機能します。

複数の画像を使ってスコアリング システムを使用すると、より正確になる可能性があり
ます。最初の 3 つまたは 5 つの画像の位置を取得します。フレーム 1 の任意のブロブについて、フレーム 2 で最も近いものを探し、速度 (deltaX deltaY) を計算し、フレーム 3、4、5 の予測位置に最も近いものを探します... 予測された位置と最も近いブロブの間のすべての距離を合計します。スコアになります。フレーム 2 で 2 番目に近いものを使用して同じことを行います (別の方向にシークします)。スコアが低いほど、良好なブロブである可能性が高くなります。

大量のブロブがある場合は、四分木を使用してプロセスを高速化する必要があります。二乗距離を比較します。多くのsqrt計算を回避します。

アルゴリズムを調整するために、ブロブが通常どのように移動するかを知ることが重要です。

于 2012-09-08T12:44:50.910 に答える
3

これがblobトラッキングのOpenCVコードサンプルです:

#include "stdafx.h"

#include <opencv2\opencv.hpp>

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);

    // Values 20,100,100 to 30,255,255 working perfect for yellow at around 6pm
    cvInRangeS(imgHSV, cvScalar(112, 100, 100), cvScalar(124, 255, 255), imgThreshed);

    cvReleaseImage(&imgHSV);

    return imgThreshed;
}

int main()
{
    // Initialize capturing live feed from the camera
    CvCapture* capture = 0;
    capture = cvCaptureFromCAM(0);  

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

    // The two windows we'll be using
    cvNamedWindow("video");
    cvNamedWindow("thresh");

    // 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)
            break;

        // 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... and we get a combination of the two
        cvAdd(frame, imgScribble, frame);
        cvShowImage("thresh", imgYellowThresh);
        cvShowImage("video", frame);

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

        // Release the thresholded image... 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;
}
于 2012-09-08T13:09:28.440 に答える
1

ブロブ検出にcvblobslibライブラリを使用できます...

  1. フレーム間のブロブの動きがブロブ間の距離よりも小さい場合..つまり、ブロブの変位がブロブ間の距離よりも小さい場合、リストを作成し、ブロブの近くにある現在の各フレームにブロブを追加し続けることができます前のフレームで...
  2. ブロブに楕円率...アスペクト比などの一定の機能がある場合(バウンディングボックスをそれに合わせた後)、これらの機能を持つブロブをリストにグループ化できます..
于 2012-09-08T13:37:29.383 に答える