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
):
现在我使用findContours函数来完成目标,目前使用的代码是(使用Python 3和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:
事实原始图像:
更多回答
优秀答案推荐
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.
使用connectedComponentsWithStats,可以获得AABB(轴对齐的边界框)。
(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:
结果:
更多回答
I used python to reproduce your code and it performed well. But there are still problems for my actual task, maybe because there are other patterns and tables in the original image. You can check the following example pictures. At present, I suspect that the problem is not the nested rectangle but the presence of the table in the picture. piclink:img1.imgtp.com/2023/09/11/2NpD4ckm.jpg
我使用python来复制你的代码,它表现得很好。但我的实际任务仍然存在问题,可能是因为原始图像中还有其他模式和表。您可以查看以下示例图片。目前,我怀疑问题不在于嵌套的矩形,而在于图片中是否存在表。图片链接:img1.imgtp.com/2023/09/11/2NpD4ckm.jpg
Sorry, I have no intention of trying to support more difficult image examples added later... However, for this example, I think followings : (1)Pixel value (white and black) is reversed from the first example, so, threshold mode should be changed to THRESH_BINARY_INV. (2)If you can actually ignore regions very near from image border, result of my code will be many cells of 2 grid tables. (3)If so, I guess, you can join cells to 1 rectangle with some additional step (e.g. with morophorogy).
抱歉,我无意尝试支持稍后添加的更困难的图像示例。。。然而,对于这个例子,我认为如下:(1)像素值(白色和黑色)与第一个例子相反,因此,阈值模式应该改为THRESH_BINARY_INV。(2) 若你们真的可以忽略离图像边界很近的区域,我的代码的结果将是两个网格表的许多单元格。(3) 如果是这样的话,我想,你可以通过一些额外的步骤将单元格连接到一个矩形中(例如,使用morphology)。
Thanks, I solved this problem based on your suggestion. The rectangles and nested rectangles on the border were removed, leaving independent small rectangles. After forming the small rectangles into a large rectangle, I got the border I needed.
谢谢,我根据你的建议解决了这个问题。边框上的矩形和嵌套矩形被删除,留下独立的小矩形。把小矩形变成大矩形后,我得到了我需要的边框。
我是一名优秀的程序员,十分优秀!