视频中的多个跟踪

时间:2014-09-10 17:11:13

标签: c++ opencv feature-detection

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

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

enter image description here

3 个答案:

答案 0 :(得分:5)

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

简而言之:

  1. 检测对象。此步骤提供一组点(检测到的对象) 坐标)。
  2. 解决分配问题(矩形匈牙利算法)。这个 步骤将检测到的对象分配给现有轨道。
  3. 管理未分配/丢失的曲目。此步骤删除连续错过检测数太多的曲目,并为新检测添加曲目。
  4. 为每个轨道应用统计滤波器(本例中为卡尔曼滤波器),用于预测 使用对象对象动态丢失检测和平滑轨道 信息(在卡尔曼滤波器矩阵中定义)。
  5. 顺便说一句,要获得4个点的坐标,你需要知道3个点的坐标,因为你的模式是矩形的,你可以计算第4个点。

答案 1 :(得分:4)

我的天真实现使用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

enter image description here

        // 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

enter image description here

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

enter image description here

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

答案 2 :(得分:1)

以下是多个彩色物体追踪的步骤:
对于每个帧,请执行以下步骤:

  1. 使用cv::cvtColor()
  2. 将输入图像(BGR)转换为HSV色彩空间
  3. 使用cv::inRange()
  4. 细分红色对象
  5. 使用cv::findContours()
  6. 从图像中提取每个blob
  7. 对于每个blob,使用cv::boundingRect()
  8. 计算其中心
  9. 匹配前一帧的斑点加上一些移动到当前斑点,比较它们的中心之间的距离 - &gt;如果他们的距离最小,则匹配他们
  10. 这是算法的基础。然后你必须处理情况,当blob进入图像时(当前帧中有斑点,但前一帧没有紧密斑点时)或保留图像(前一帧中有斑点,但是当前框架中没有密切的blob。)