In an image, there are two nested rectangles, and they share two sides. How to use opencv to identify the two rectangles
Question:
Sorry, the original image cannot be uploaded due to some security reasons. The following is a schematic diagram:
original image:

my goal:

Current situation:

now I use findContours
function to to complete the goal,The code currently used is(use Python 3 and OpenCV
):
edges = cv2.Canny(mask, 10, 150)
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(ima, [contour], -1, (0, 0, 255), 5)
I also used the following function parameters:
cv2.RETR_EXTERNAL,cv2.RETR_LIST,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_NONE,cv2.CHAIN_APPROX_TC89_L1,cv2.CHAIN_APPROX_TC89_KCOS
Answers:
Bounding-box of each white regions can be used to judge the simple rectangular "nested" relation.
Using connectedComponentsWithStats
, AABB(axis-aligned bounding boxes) can be obtained.
(Following code is C++.)
//Judge the rectangular nested relation
bool Is_A_Including_B( const cv::Rect &A, const cv::Rect &B, int Margin )
{
int Left = A.x - Margin;
int Right = Left + A.width + 2*Margin - 1;
int Top = A.y - Margin;
int Bottom = Top + A.height + 2*Margin - 1;
auto B_br = B.br();
return ( Left<=B.x && B_br.x<=Right && Top<=B.y && B_br.y<=Bottom );
}
//main
int main()
{
//Load Image and Binalize
cv::Mat SrcImg = cv::imread( "Regs.png", cv::IMREAD_GRAYSCALE );
if( SrcImg.empty() )return 0;
cv::Mat BinImg;
cv::threshold( SrcImg, BinImg, 128, 255, cv::THRESH_BINARY );
//Find Bounding Boxes of white regions
std::vector< cv::Rect > BBs;
{
cv::Mat Labels, Stats, Centroids;
int N = cv::connectedComponentsWithStats( BinImg, Labels, Stats, Centroids );
BBs.reserve( N-1 );
for( int i=1; i<N; ++i )
{
BBs.emplace_back(
Stats.at<int>( i, cv::CC_STAT_LEFT ),
Stats.at<int>( i, cv::CC_STAT_TOP ),
Stats.at<int>( i, cv::CC_STAT_WIDTH ),
Stats.at<int>( i, cv::CC_STAT_HEIGHT )
);
}
}
//Find nested region
std::vector< cv::Rect > Found;
for( auto i=BBs.begin(); i!=BBs.end(); ++i )
{
for( auto j=BBs.begin(); j!=BBs.end(); ++j )
{
if( i == j )continue;
if( Is_A_Including_B( *i, *j, 5 ) )
{ Found.push_back( *j ); }
}
}
//Visualize
cv::Mat ShowImg;
cv::cvtColor( BinImg, ShowImg, cv::COLOR_GRAY2BGR );
ShowImg *= 0.5;
for( const auto &Rect : Found )
{
cv::rectangle( ShowImg, Rect, cv::Scalar(0,0,255), 4 );
}
cv::imshow( "Result", ShowImg );
cv::waitKey();
return 0;
}
Sorry, the original image cannot be uploaded due to some security reasons. The following is a schematic diagram:
original image:
my goal:
Current situation:
now I use findContours
function to to complete the goal,The code currently used is(use Python 3 and OpenCV
):
edges = cv2.Canny(mask, 10, 150)
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(ima, [contour], -1, (0, 0, 255), 5)
I also used the following function parameters:
cv2.RETR_EXTERNAL,cv2.RETR_LIST,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_NONE,cv2.CHAIN_APPROX_TC89_L1,cv2.CHAIN_APPROX_TC89_KCOS
Bounding-box of each white regions can be used to judge the simple rectangular "nested" relation.
Using connectedComponentsWithStats
, AABB(axis-aligned bounding boxes) can be obtained.
(Following code is C++.)
//Judge the rectangular nested relation
bool Is_A_Including_B( const cv::Rect &A, const cv::Rect &B, int Margin )
{
int Left = A.x - Margin;
int Right = Left + A.width + 2*Margin - 1;
int Top = A.y - Margin;
int Bottom = Top + A.height + 2*Margin - 1;
auto B_br = B.br();
return ( Left<=B.x && B_br.x<=Right && Top<=B.y && B_br.y<=Bottom );
}
//main
int main()
{
//Load Image and Binalize
cv::Mat SrcImg = cv::imread( "Regs.png", cv::IMREAD_GRAYSCALE );
if( SrcImg.empty() )return 0;
cv::Mat BinImg;
cv::threshold( SrcImg, BinImg, 128, 255, cv::THRESH_BINARY );
//Find Bounding Boxes of white regions
std::vector< cv::Rect > BBs;
{
cv::Mat Labels, Stats, Centroids;
int N = cv::connectedComponentsWithStats( BinImg, Labels, Stats, Centroids );
BBs.reserve( N-1 );
for( int i=1; i<N; ++i )
{
BBs.emplace_back(
Stats.at<int>( i, cv::CC_STAT_LEFT ),
Stats.at<int>( i, cv::CC_STAT_TOP ),
Stats.at<int>( i, cv::CC_STAT_WIDTH ),
Stats.at<int>( i, cv::CC_STAT_HEIGHT )
);
}
}
//Find nested region
std::vector< cv::Rect > Found;
for( auto i=BBs.begin(); i!=BBs.end(); ++i )
{
for( auto j=BBs.begin(); j!=BBs.end(); ++j )
{
if( i == j )continue;
if( Is_A_Including_B( *i, *j, 5 ) )
{ Found.push_back( *j ); }
}
}
//Visualize
cv::Mat ShowImg;
cv::cvtColor( BinImg, ShowImg, cv::COLOR_GRAY2BGR );
ShowImg *= 0.5;
for( const auto &Rect : Found )
{
cv::rectangle( ShowImg, Rect, cv::Scalar(0,0,255), 4 );
}
cv::imshow( "Result", ShowImg );
cv::waitKey();
return 0;
}