【问题标题】:how to detect intersecting and overlapping bounding box in a lot of bounding box?如何在很多边界框中检测相交和重叠的边界框?
【发布时间】:2015-10-22 20:39:27
【问题描述】:

我在图像中生成了很多边界框。如何合并图像中的重叠边界框?

例如,

_________________                   ________________________
|               |                   |                      |
|      —————————|————               |                      | 
|      |        |   |               |                      |
———————|——————————  |         ——>   |                      |  
       |            |               |                      |
       |    ————————|——————         |                      |
       —————|————————     |         |                      |
            |             |         |                      |
            |             |         |                      |
            ————————————————        ________________________

我知道使用rectangle 1 | rectangle 2 来生成一个新的矩形。

它可以通过以下方法检测并合并它们。(来自Efficient way to combine intersecting bounding rectangles

if((rect1 & rect2) == rect1) ... // rect1 is completely inside rect2; do nothing.
else if((rect1 & rect2).area() > 0) // they intersect; merge them.
    newrect = rect1 | rect2;
    ... // remove rect1 and rect2 from list and insert newrect.

但是我的意思是当三个或四个矩形重叠时如何判断哪个矩形重叠。我虽然可以使用重叠区域来判断它们是否重叠。

还有其他有效的方法吗? 非常感谢。

【问题讨论】:

    标签: image opencv image-processing


    【解决方案1】:

    这是一些快速的伪代码

    1. 为每个矩形生成图像大小的二进制映射。
    2. 添加这些二进制映射以创建一个新的单一合并映射。 (您可能必须将它们重新设置为 1 和 0)
    3. 使用您的原始算法(用于获取前 3 个边界框的算法)为此生成一个新的边界框

    【讨论】:

    • 您好,我使用您的方法。结果很好。
    • 我把所有的矩形都放到了一张图片中。之后,我使用连接组件标记方法和联合查找算法。结果就是我想要得到的。但是仍然有小矩形无法删除矩形内的哪个。非常感谢!
    • 很高兴听到它成功了!我不确定你所说的内部矩形是什么意思 - 但也许你在添加后没有阈值回到二进制,所以它有 2 个边界框?
    【解决方案2】:

    此函数获取图像的轮廓并返回您想要的合并框:

    ae::error_code authenticator::get_boxes(const std::vector<std::vector<cv::Point>>& contours, std::vector<cv::Rect>& boxes){
            std::vector<cv::Rect> bounding_boxes;
            for (const auto& contour_item : contours){
                bounding_boxes.push_back(cv::boundingRect(contour_item));
            }
    
    
            auto rect_corners = [](const cv::Rect& rect)->std::vector<cv::Point>{
                return{ cv::Point(rect.x, rect.y),
                    cv::Point(rect.x + rect.width, rect.y),
                    cv::Point(rect.x + rect.width, rect.y + rect.height),
                    cv::Point(rect.x, rect.y + rect.height) };
            };
    
            auto check_shared_rects = [](const cv::Rect& rect_a, const cv::Rect& rect_b)->bool{
                return (rect_a & rect_b).area() > 0;
            };
    
    
            for (size_t rect_idx = 0; rect_idx < bounding_boxes.size() - 1; ++rect_idx){
                for (size_t other_rect_idx = rect_idx + 1; other_rect_idx < bounding_boxes.size(); ++other_rect_idx){
                    if (check_shared_rects(bounding_boxes[rect_idx], bounding_boxes[other_rect_idx])){
                        auto new_rect_points(rect_corners(bounding_boxes[rect_idx]));
                        auto temp_points(rect_corners(bounding_boxes[other_rect_idx]));
                        new_rect_points.insert(std::end(new_rect_points), std::begin(temp_points), std::end(temp_points));
                        bounding_boxes.push_back(cv::boundingRect(new_rect_points));
                        bounding_boxes.erase(std::begin(bounding_boxes) + other_rect_idx);
                        bounding_boxes.erase(std::begin(bounding_boxes) + rect_idx);
                        rect_idx = 0;
                        other_rect_idx = rect_idx;
                    }
                }
            }
            boxes = bounding_boxes;
            return ae::error_code::ae_error_free;
        }
    

    编辑: 您可以忽略关于生成边界框的第一部分,因为您已经有了它们。

    【讨论】:

      【解决方案3】:

      按区域对边界框进行排序:最大的框更有可能重叠。

      如果做不到这一点,您可以通过合并所有矩形来“不那么有效”地绘制所有矩形。 您可能希望标记重叠框图像以仅选择重叠的框并丢弃其余部分。

      在这个想法下可能有一些技巧可以通过使用一种 z-buffer 来存储在每个像素上绘制的矩形?

      【讨论】:

        【解决方案4】:

        这是我用来解决我的问题的代码,你也可以用它来享受:

         function varargout = isBoxMerg(ReferenceBox,TestBox,isNewBox)
        
                    X = ReferenceBox; Y = TestBox;
        
                    X1 = X(1);Y1 = X(2);W1 = X(3);H1 = X(4);
                    X2 = Y(1);Y2 = Y(2);W2 = Y(3);H2 = Y(4);
        
                    if ((X1+W1)>=X2 && (Y2+H2)>=Y1 && (Y1+H1)>=Y2 && (X1+W1)>=X2 && (X2+W2)>=X1)
                        Intersection = true;
                    else
                        Intersection = false;
                    end
                    if (~isNewBox)
                        varargout{1} = Intersection;
                    elseif(isNewBox && Intersection)
                        varargout{1} = Intersection;
        
                        a = X1;b=X1+W1;c=Y1;d=Y1+H1;
                        p = X2;q=X2+W2;r=Y2;s=Y2+H2;
        
        
        
                        if a<p
                            newA = a;
                        else
                            newA = p;
                        end
                        if b>q
                            newB = b;
                        else
                            newB = q;
                        end
                        if c<r
                            newC = c;
                        else
                            newC = r;
                        end
                        if d>s
                            newD = d;
                        else
                            newD = s;
                        end
                        newCC = [newA,newC,abs(newA-newB),abs(newC-newD)];
                        varargout{2} = newCC;  
                    end
        

        【讨论】:

        • 感谢您的方法。我会试试。我没有投票给你的答案。谢谢~
        猜你喜欢
        • 1970-01-01
        • 2021-04-15
        • 2017-07-07
        • 1970-01-01
        • 2020-07-23
        • 2013-04-06
        • 2020-07-20
        • 2018-11-12
        • 2013-04-30
        相关资源
        最近更新 更多