9

我正在尝试使用 OpenCV 创建简单的 blob 跟踪。我已经使用 findcontours 检测到了这些斑点。我想给这些 blob 一个常量 ID。

我已经收集了前一帧和当前帧中的 blob 列表。然后我取了前一帧中每个 blob 和当前帧之间的距离。我想知道还需要什么来跟踪 blob 并给它们一个 ID。我只是获取了前一帧和当前帧 blob 之间的距离,但是如何使用 blob 之间的测量距离为 blob 分配一致的 ID?

4

3 回答 3

9

在第一帧中,您可以以任何方式分配 id,1 表示您找到的第一个,2 表示第二个......或者只是根据他们在集合中的位置给他们 ID。

然后在下一帧你将不得不使用最佳匹配。找到 blob,计算当前 blob 与前一个图像的所有 blob 之间的所有距离,并将每个前一个 ID 分配给最近的 blob。刚刚进入该字段的 Blob 将获得新的 ID。

现在你有两帧,你可以对下一帧进行运动预测。只需计算 blob 的先前位置和当前位置之间的 deltaX 和 deltaY。您可以使用此信息来猜测未来的位置。匹配这个未来的位置。

如果您没有太多重叠的 blob,并且每个帧之间的移动不是太快且不稳定,这应该可以工作。

通过多张图像使用评分系统可能会更准确:
获取前 3 或 5 张图像的位置。对于第一帧的任何斑点,在第 2 帧上寻找最近​​的斑点,计算速度(deltaX deltaY),寻找最接近第 3、4、5 帧的预测位置...总结预测位置和最近斑点之间的所有距离成为分数。使用第 2 帧上的第 2 个最近点执行相同操作(它将向另一个方向搜索)。分数越低,它最有可能是好的 blob。

如果你有很多 blob,你应该使用四叉树来加速进程。比较平方距离;它将避免大量的 sqrt 计算。

重要的是要知道您的 blob 通常如何移动以调整您的算法。

于 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. 如果您的帧间 blob 移动小于 blob 间距离..即 blob 位移小于 blob 间距离,那么您可以创建一个列表并继续在每个当前帧中添加 blob,这些 blob 位于 blob 附近在上一帧...
  2. 如果您的 blob 具有一些恒定的特征,例如椭圆度...纵横比(在将边界框拟合到它之后),您可以将具有这些特征的 blob 分组到一个列表中。
于 2012-09-08T13:37:29.383 回答