【问题标题】:Blob tracking algorithm斑点跟踪算法
【发布时间】:2012-09-02 02:00:07
【问题描述】:

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

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

【问题讨论】:

  • 你能说明你的问题吗?

标签: c++ opencv computer-vision tracking


【解决方案1】:

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

  1. 如果您的帧间 blob 移动小于 blob 间距离..也就是说 blob 位移小于 blob 间距离,那么您可以创建一个列表并继续在每个当前帧中添加 blob上一帧中的 blob...
  2. 如果您的 blob 具有一些恒定的特征,例如椭圆度...纵横比(在将边界框拟合到它之后),您可以将具有这些特征的 blob 分组到一个列表中。

【讨论】:

    【解决方案2】:

    这是一个 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;
    }
    

    【讨论】:

      【解决方案3】:

      在第一帧中,您可以以任何方式分配 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 通常如何移动以调整算法非常重要。

      【讨论】:

      • 谢谢,你能通过例子和计算或图片给我更多的解释吗?我很高兴了解这个过程。或者你可以给我一个参考
      猜你喜欢
      • 2014-02-08
      • 1970-01-01
      • 1970-01-01
      • 2012-05-17
      • 2020-08-23
      • 1970-01-01
      • 2023-01-17
      • 1970-01-01
      • 2010-12-09
      相关资源
      最近更新 更多