【问题标题】:Multiple tracking in a Video视频中的多个跟踪
【发布时间】:2014-11-04 10:43:13
【问题描述】:

我正在处理需要跟踪 4 个红色对象的小型图像处理任务。我知道如何跟踪一个。我想知道跟踪多个点的最佳方法是什么。

有 4 个点被定位形成一个矩形,所以我可以使用形状检测或角检测来检测和跟踪这些点请参见下图..

【问题讨论】:

  • 看看像粒子过滤这样的概率跟踪方法
  • 取决于红点的移动以及如果它们重叠,您是否必须继续跟踪正确的红点。
  • 所以你的想法不是跟踪多个对象而是跟踪单个模式?
  • 是的,确实如此!但我还需要得到 4 个红点的 x、y 位置。
  • 我可以使用四边形算法吗?

标签: c++ opencv feature-detection


【解决方案1】:

这是我在 GitHub 上的实现:https://github.com/Smorodov/Multitarget-tracker youtube 上的视频:http://www.youtube.com/watch?v=2fW5TmAtAXM&list=UUhlR5ON5Uqhi_3RXRu-pdVw

简而言之:

  1. 检测物体。此步骤提供一组点(检测到的对象 坐标)。
  2. 解决分配问题(矩形匈牙利算法)。这 步骤将检测到的对象分配给现有轨道。
  3. 管理未分配/丢失的轨道。此步骤会删除连续漏检过多的轨迹,并添加新检测的轨迹。
  4. 为每个轨道应用统计过滤器(在本例中为卡尔曼过滤器),用于预测 使用对象对象动力学丢失检测和平滑跟踪 信息(在卡尔曼滤波器矩阵中定义)。

顺便说一句,要获得 4 个点的坐标,您只需要知道 3 个点的坐标,因为您的图案是矩形的,您可以计算第 4 个点。

【讨论】:

  • 这看起来很高级!不过谢谢。但这不是我要找的。​​span>
  • +1 仅因为我知道您将在回答中添加对该方法的高级概述。如今,仅链接的答案已不被认为是好的答案。
  • 是否只有 C 版本。我没有 Matlab。
  • 是的。它是 OpenCV/CPP 版本。
【解决方案2】:

我的幼稚实现使用OpenCV bounding boxes 中描述的技术来跟踪红色斑点。

以下是一个辅助函数,用于检索检测到的所有红色对象的中心:

/* get_positions: a function to retrieve the center of the detected blobs.
 * largely based on OpenCV's "Creating Bounding boxes and circles for contours" tutorial.
 */
std::vector<cv::Point2f> get_positions(cv::Mat& image)
{
    if (image.channels() > 1)
    {
        std::cout << "get_positions: !!! Input image must have a single channel" << std::endl;
        return std::vector<cv::Point2f>();
    }

    std::vector<std::vector<cv::Point> > contours;
    cv::findContours(image, contours, cv::RETR_LIST, cv::CHAIN_APPROX_SIMPLE);

    // Approximate contours to polygons and then get the center of the objects
    std::vector<std::vector<cv::Point> > contours_poly(contours.size());
    std::vector<cv::Point2f> center(contours.size());
    std::vector<float> radius(contours.size());
    for (unsigned int i = 0; i < contours.size(); i++ )
    {
        cv::approxPolyDP(cv::Mat(contours[i]), contours_poly[i], 5, true );
        cv::minEnclosingCircle((cv::Mat)contours_poly[i], center[i], radius[i]);
    }

    return center;
}   

我编写了代码,通过从网络摄像头捕获帧来实时测试我的方法。整个过程与@Dennis 描述的非常相似(抱歉,当你提交答案时我已经在编码了)。

好的,这就是真正有趣的地方。

int main()
{
    // Open the capture device. My webcam ID is 0:
    cv::VideoCapture cap(0);
    if (!cap.isOpened())
    {
        std::cout << "!!! Failed to open webcam" << std::endl;
        return -1;
    }

    // Let's create a few window titles for debugging purposes
    std::string wnd1 = "Input", wnd2 = "Red Objs", wnd3 = "Output";   

    // These are the HSV values used later to isolate RED-ish colors
    int low_h = 160, low_s = 140, low_v = 50;
    int high_h = 179, high_s = 255, high_v = 255;

    cv::Mat frame, hsv_frame, red_objs;
    while (true)
    {
        // Retrieve a new frame from the camera
        if (!cap.read(frame))
            break;

        cv::Mat orig_frame = frame.clone();
        cv::imshow(wnd1, orig_frame);

orig_frame:

        // Convert BGR frame to HSV to be easier to separate the colors
        cv::cvtColor(frame, hsv_frame, CV_BGR2HSV);

        // Isolate red colored objects and save them in a binary image
        cv::inRange(hsv_frame,
                    cv::Scalar(low_h,  low_s,  low_v),
                    cv::Scalar(high_h, high_s, high_v),
                    red_objs);

        // Remove really small objects (mostly noises)
        cv::erode(red_objs, red_objs, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3)));
        cv::dilate(red_objs, red_objs, cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7, 7)));

        cv::Mat objs = red_objs.clone();
        cv::imshow(wnd2, objs);

objs:

        // Retrieve a vector of points with the (x,y) location of the objects
        std::vector<cv::Point2f> points = get_positions(objs);

        // Draw a small green circle at those locations for educational purposes
        for (unsigned int i = 0; i < points.size(); i++)
            cv::circle(frame, points[i], 3, cv::Scalar(0, 255, 0), -1, 8, 0);

        cv::imshow(wnd3, frame);

        char key = cv::waitKey(33);
        if (key == 27) {   /* ESC was pressed */
            //cv::imwrite("out1.png", orig_frame);
            //cv::imwrite("out2.png", red_objs);
            //cv::imwrite("out3.png", frame);
            break;
        }
    }

    cap.release();

    return 0;
}

【讨论】:

  • 有希望的解决方案!谢谢 但是,你是怎么得到红色物体的只有一个绿色圆圈的?我的重点是接近红色物体的完美中心 x,y 坐标!我猜这里的 blob 不平滑!
  • 该部分由代码中的cv::approxPolyDP()cv::minEnclosingCircle()执行。找到不是完美正方形或圆形的事物的中心是一个不错的选择。
  • @aaa 我想我现在明白你的期望了。您想将所有检测到的小方块放在一个大矩形内,对吗? 但是,这不是 youtube 视频的功能。在that video 中,很明显每个红色斑点最终都有自己的矩形围绕它。我做了完全相同的事情,除了我在斑点的中心放置了一个绿色圆圈。你的印象是我所做的不同,因为我展示了一个显示 6 个红色小方块的对象,而视频人显示了 2 个更大的红色方块。
  • Here is the link to my video(顺便说一句,我知道这很糟糕);D
  • Here is my result 我不明白为什么我的红色物体上有多个绿色圆圈?
【解决方案3】:

以下是多色对象跟踪的步骤:
对每一帧执行以下步骤:

  1. 使用 cv::cvtColor() 将输入图像 (BGR) 转换为 HSV 颜色空间
  2. 使用cv::inRange()分割红色对象
  3. 使用cv::findContours()从图像中提取每个blob
  4. 对于每个 blob,使用 cv::boundingRect() 计算其中心
  5. 将前一帧的 blob 加上一些移动与当前 blob 匹配,比较它们的中心之间的距离 --> 如果它们的距离最小,则匹配它们

这是算法的基础。然后你必须处理一些情况,当 blob 进入图像时(当前帧中有 blob,但前一帧没有关闭 blob)或离开图像(前一帧中有 blob,但当前帧中没有关闭 blob)。

【讨论】:

  • +1 不错的方法。我最终做了类似的事情。
猜你喜欢
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
  • 2011-10-29
相关资源
最近更新 更多