【问题标题】:Merging Overlapping Rectangle in OpenCV在 OpenCV 中合并重叠矩形
【发布时间】:2016-06-27 18:32:04
【问题描述】:

我正在使用 OpenCV 3.0。我做了一个汽车检测程序,但我一直遇到重叠边界框的问题:

有没有一种方法可以合并重叠的边界框,如下图所述? 我使用rectangle(frame, Point(x1, y1), Point(x2, y2), Scalar(255,255,255)); 来绘制这些边界框。我已经从类似的线程中搜索了答案,但我找不到它们有帮助。我想在合并这些边界框后形成一​​个外部边界矩形。

【问题讨论】:

标签: c++ opencv rectangles object-detection


【解决方案1】:

问题

好像你正在显示你得到的每个轮廓。你不必那样做。按照下面给出的算法和代码。

算法

在这种情况下,您可以做的是遍历您检测到的每个轮廓并选择最大的 boundingRect。您不必显示检测到的每个轮廓。

这是您可以使用的代码。

代码

for( int i = 0; i< contours.size(); i++ ) // iterate through each contour. 
      {
       double a=contourArea( contours[i],false);  //  Find the area of contour
       if(a>largest_area){
       largest_area=a;
       largest_contour_index=i;                //Store the index of largest contour
       bounding_rect=boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
       }

      }

问候

【讨论】:

    【解决方案2】:

    正如我在类似的帖子here 中提到的,这是一个最好通过非最大抑制来解决的问题。

    虽然您的代码是 C++,但请查看 this pyimagesearch 文章 (python) 以了解其工作原理。

    我已将这段代码从 python 翻译成 C++,。

    struct detection_box
    {
        cv::Rect box;               /*!< Bounding box */
        double svm_val;             /*!< SVM response at that detection*/
        cv::Size res_of_detection;  /*!< Image resolution at which the detection occurred */
    };
    
    /*!
    \brief Applies the Non Maximum Suppression algorithm on the detections to find the detections that do not overlap
    
    The svm response is used to sort the detections. Translated from http://www.pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/
    
    \param boxes list of detections that are the input for the NMS algorithm
    \param overlap_threshold the area threshold for the overlap between detections boxes. boxes that have overlapping area above threshold are discarded
    
    
    \returns list of final detections that are no longer overlapping
    */
    std::vector<detection_box> nonMaximumSuppression(std::vector<detection_box> boxes, float overlap_threshold)
    {
        std::vector<detection_box> res;
        std::vector<float> areas;
    
        //if there are no boxes, return empty 
        if (boxes.size() == 0)
            return res;
    
        for (int i = 0; i < boxes.size(); i++)
            areas.push_back(boxes[i].box.area());
    
        std::vector<int> idxs = argsort(boxes);     
    
        std::vector<int> pick;          //indices of final detection boxes
    
        while (idxs.size() > 0)         //while indices still left to analyze
        {
            int last = idxs.size() - 1; //last element in the list. that is, detection with highest SVM response
            int i = idxs[last];
            pick.push_back(i);          //add highest SVM response to the list of final detections
    
            std::vector<int> suppress;
            suppress.push_back(last);
    
            for (int pos = 0; pos < last; pos++)        //for every other element in the list
            {
                int j = idxs[pos];
    
                //find overlapping area between boxes
                int xx1 = max(boxes[i].box.x, boxes[j].box.x);          //get max top-left corners
                int yy1 = max(boxes[i].box.y, boxes[j].box.y);          //get max top-left corners
                int xx2 = min(boxes[i].box.br().x, boxes[j].box.br().x);    //get min bottom-right corners
                int yy2 = min(boxes[i].box.br().y, boxes[j].box.br().y);    //get min bottom-right corners
    
                int w = max(0, xx2 - xx1 + 1);      //width
                int h = max(0, yy2 - yy1 + 1);      //height
    
                float overlap = float(w * h) / areas[j];    
    
                if (overlap > overlap_threshold)        //if the boxes overlap too much, add it to the discard pile
                    suppress.push_back(pos);
            }
    
            for (int p = 0; p < suppress.size(); p++)   //for graceful deletion
            {
                idxs[suppress[p]] = -1;
            }
    
            for (int p = 0; p < idxs.size();)
            {
                if (idxs[p] == -1)
                    idxs.erase(idxs.begin() + p);
                else
                    p++;
            }
    
        }
    
        for (int i = 0; i < pick.size(); i++)       //extract final detections frm input array
            res.push_back(boxes[pick[i]]);
    
        return res;
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-06-13
      • 1970-01-01
      • 2016-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 2018-11-02
      相关资源
      最近更新 更多