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:

original image

my goal:

my goal

Current situation:

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

fact original image:enter image description here

Asked By: Hasegaawa Haruka

||

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

Result:
enter image description here

Answered By: fana
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.