组合图像中的重叠组

Ant*_*ony 5 c++ opencv image-processing computer-vision

我使用opencv_contrib来检测图像中的文本区域.

这是原始图像

这是找到文本区域后的图像:

可以看出,图像中存在重叠的组.例如,似乎是围绕两个组Hello World和两个绕Some more sample text

问题 在这样的场景中,如何通过合并两个框来保持最宽的框.对于这些例子,它将以一个开始H和结束的方式d覆盖Hello World.我这样做的原因是我想裁剪这部分图像并将其发送给tesseract.

这是绘制框的相关代码.

void groups_draw(Mat &src, vector<Rect> &groups)
{
    for (int i=(int)groups.size()-1; i>=0; i--)
    {
        if (src.type() == CV_8UC3)
            rectangle(src,groups.at(i).tl(),groups.at(i).br(),Scalar( 0, 255, 255 ), 2, 8 );
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我尝试过的.我的想法在评论中.

void groups_draw(Mat &src, vector<Rect> &groups)
{
    int previous_tl_x = 0;
    int previous_tl_y = 0;
    int prevoius_br_x = 0;
    int previous_br_y = 0;
    //sort the groups from lowest to largest.
    for (int i=(int)groups.size()-1; i>=0; i--)
    {
        //if previous_tl_x is smaller than current_tl_x then keep the current one.
       //if previous_br_x is smaller than current_br_x then keep the current one.
        if (src.type() == CV_8UC3) {
          //crop the image
          Mat cropedImage = src(Rect(Point(groups.at(i).tl().x, groups.at(i).tl().y),Point(groups.at(i).br().x, groups.at(i).br().y)));
          imshow("cropped",cropedImage);
          waitKey(-1);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新

我正在尝试[groupRectangles][4]用来完成这个:

void groups_draw(Mat &src, vector<Rect> &groups)
{
    vector<Rect> rects;
    for (int i=(int)groups.size()-1; i>=0; i--)
    {
        rects.push_back(groups.at(i));
    }
    groupRectangles(rects, 1, 0.2);
}
Run Code Online (Sandbox Code Playgroud)

但是,这给了我一个错误:

textdetection.cpp:106:5: error: use of undeclared identifier 'groupRectangles'
    groupRectangles(rects, 1, 0.2);
    ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

Bar*_*raa 3

首先,出现重叠边界框的原因是文本检测器模块正在反转通道(例如:灰色和反转灰色)上工作,并且由于某些字符(例如 o 和 g)的内部区域被错误地检测并分组为字符。因此,如果您只想检测一种文本模式(深色背景上的白色文本),只需传递反转通道即可。代替:

 for (int c = 0; c < cn-1; c++)
    channels.push_back(255-channels[c]);
Run Code Online (Sandbox Code Playgroud)

和:

for (int c = 0; c < cn-1; c++)
    channels[c] = (255-channels[c]);
Run Code Online (Sandbox Code Playgroud)

现在对于你的问题,矩形已经定义了交集和组合运算符:

rect = rect1 & rect2 (rectangle intersection)
rect = rect1 | rect2 (minimum area rectangle containing rect2 and rect3 )
rect &= rect1, rect |= rect1 (and the corresponding augmenting operations)
Run Code Online (Sandbox Code Playgroud)

您可以在迭代矩形时使用这些运算符来检测相交的矩形并将它们组合起来,如下所示:

if ((rect1 & rect2).area() != 0)
    rect1 |= rect2;
Run Code Online (Sandbox Code Playgroud)

编辑:

首先,按面积从大到小对矩形组进行排序:

std::sort(groups.begin(), groups.end(),
            [](const cv::Rect &rect1, const cv::Rect &rect2) -> bool {return rect1.area() > rect2.area();});
Run Code Online (Sandbox Code Playgroud)

然后,迭代矩形,当两个矩形相交时,将较小的添加到较大的矩形中,然后将其删除:

for (int i = 0; i < groups.size(); i++)
        {
            for (int j = i + 1; j < groups.size(); j++)
            {
                if ((groups[i] & groups[j]).area() != 0)
                {
                    groups[i] |= groups[j];
                    groups.erase(groups.begin() + j--);                     
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)