如何在很多边界框中检测交叉和重叠的边界框?

时间:2015-10-22 20:39:27

标签: image opencv image-processing

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

例如,

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

我知道使用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.

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

这还有什么有效的方法吗?  非常感谢你。

4 个答案:

答案 0 :(得分:0)

这是一个快速伪代码

  1. 为每个矩形生成二进制贴图,这些贴图是图像的大小。
  2. 添加这些二进制映射以创建新的单个合并映射。 (你可能需要将它们降低到1和0的阈值)
  3. 使用原始算法(用于获取前3个边界框的算法)为此生成一个新的边界框。

答案 1 :(得分:0)

此功能获取图像的轮廓并返回所需的合并框:

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

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

答案 2 :(得分:-1)

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

如果不这样做,你可以通过对所有矩形进行联合来绘制所有矩形的“效率不高”。 您可能希望标记重叠框图像以仅选择重叠的图像并丢弃其余图像。

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

答案 3 :(得分:-1)

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

 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