Blob跟踪算法

10

我正在尝试使用OpenCV创建简单的blob跟踪。我已经使用findcontours检测到了这些blobs。我希望能够为这些blobs分配一个恒定的ID。

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


请问您能否举例说明您的问题? - bokan
3个回答

9
在第一帧中,您可以以任何方式分配ID,例如为第一个找到的1,第二个为2...或者根据它们在集合中的位置直接给它们ID。
然后,在下一帧中,您将需要使用最佳匹配。查找blob,计算当前blob和上一帧图像中所有blob之间的所有距离,并将每个先前的ID分配给最近的blob。刚进入场地的blob将获得新的ID。
现在您有两个帧,可以对下一个进行移动预测。只需计算blob的先前和当前位置之间的deltaX和deltaY。您可以使用此信息来猜测未来的位置。与此未来位置进行匹配。
如果重叠的blob不太多,并且每个帧之间的移动速度不太快且不稳定,则应该有效。
可以通过多张图像使用评分系统更准确:
获取前3或5张图像的位置。对于第一帧的任何blob,寻找第二帧中最接近的blob,计算速度(deltaX deltaY),寻找第三、四、五帧的预测位置最接近的blob,总结所有预测位置和最接近的blob之间的距离,这将是分数。使用第二接近帧2的相同方法进行操作(它将朝另一个方向寻找)。分数越低,好的blob越可能。
如果有很多blob,则应使用四叉树加速处理。比较平方距离;这将避免大量的sqrt计算。
了解blob的典型移动方式以调整您的算法非常重要。

谢谢,您能否通过示例、计算或图片给我更多的解释?我非常希望能够理解这个过程。或者您可以为我提供一个参考资料。 - Moaz ELdeen

4
这是一个 OpenCV 的代码示例,用于 blob 跟踪。
#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;
}

1

您可以使用cvblobslib库进行斑点检测...

  1. 如果您的帧间斑点移动小于斑点间距离...也就是说,斑点位移小于斑点间距离,则可以创建一个列表,并在每个当前帧中添加落在前一帧中斑点邻域内的斑点...
  2. 如果您的斑点具有某些恒定特征,例如椭圆度...长宽比(适合边界框),则可以将具有这些特征的斑点分组到列表中...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接