Image 如何在大量的包围盒中检测相交和重叠的包围盒?
我在图像中生成了很多边界框。如何在图像中合并重叠的边界框 比如说,Image 如何在大量的包围盒中检测相交和重叠的包围盒?,image,opencv,image-processing,Image,Opencv,Image Processing,我在图像中生成了很多边界框。如何在图像中合并重叠的边界框 比如说, _________________ ________________________ | | | | | —————————|———— | | | | | |
_________________ ________________________
| | | |
| —————————|———— | |
| | | | | |
———————|—————————— | ——> | |
| | | |
| ————————|—————— | |
—————|———————— | | |
| | | |
| | | |
———————————————— ________________________
我知道使用矩形1 |矩形2
生成一个新矩形
它可以通过以下方法检测并合并它们
但我的意思是,当三个或四个矩形重叠时,如何判断哪个矩形重叠。我想我可以使用重叠区域来判断它们是否重叠
这是其他有效的方法吗?
非常感谢。这里有一些快速伪代码
按区域对边界框进行排序:最大的框更有可能重叠 如果做不到这一点,可以通过对所有矩形进行并集来绘制“效率不高”的所有矩形。 您可能希望为重叠框图像添加标签,以便仅选择重叠框并放弃其余框
在这种想法下,可能需要使用一些技巧,使用一种z缓冲区来存储在每个像素上绘制的矩形?这是我用于解决我的问题的代码,您也可以使用它来解决您的问题
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
function varargout=isBoxMerg(参考框、测试框、isNewBox)
X=参考框;Y=测试盒;
X1=X(1);Y1=X(2);W1=X(3);H1=X(4);
X2=Y(1);Y2=Y(2);W2=Y(3);H2=Y(4);
如果((X1+W1)>=X2&&(Y2+H2)>=Y1&&(Y1+H1)>=Y2&&(X1+W1)>=X2&&(X2+W2)>=X1)
交点=真;
其他的
交点=假;
终止
如果(~isNewBox)
varargout{1}=交叉点;
elseif(isNewBox和交叉口)
varargout{1}=交叉点;
a=X1;b=X1+W1;c=Y1;d=Y1+H1;
p=X2;q=X2+W2;r=Y2;s=Y2+H2;
如果aq
newB=b;
其他的
newB=q;
终止
如果cs
newD=d;
其他的
newD=s;
终止
newCC=[newA,newC,abs(newA-newB),abs(newC-newD)];
varargout{2}=newCC;
终止
此函数获取图像轮廓并返回所需的合并框:
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;
}
ae::error\u code authenticator::get\u box(const std::vector&contours,std::vector&box){
std::向量边界盒;
用于(常量自动和等高线项目:等高线){
边界框。向后推(cv::boundingRect(轮廓项));
}
auto rect_corners=[](常量cv::rect&rect)->std::vector{
返回{cv::Point(rect.x,rect.y),
cv::点(矩形x+矩形宽度,矩形y),
cv::点(矩形x+矩形宽度,矩形y+矩形高度),
cv::Point(rect.x,rect.y+rect.height)};
};
自动检查\u共享\u rects=[](常量cv::Rect&Rect\u a,常量cv::Rect&Rect\u b)->bool{
返回(矩形a和矩形b).area()>0;
};
对于(size_t rect_idx=0;rect_idx
编辑:
您可以忽略关于生成边界框的第一部分,因为您已经有了它们。您好,我使用您的方法。结果很好,我把所有的矩形都放进了一张图片中。之后,我使用了连通元件标记方法和联合查找算法。结果就是我想要得到的。但是还有一个小矩形不能去掉它里面的矩形。非常感谢你!很高兴听到它起作用了!我不确定你所说的“内部矩形”是什么意思,但也许你在添加两个边界框后没有将阈值还原为二进制?谢谢你的建议谢谢你的方法。我试试看。我还没有投你的票。多谢各位~
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;
}