c++ - 检测盒子/ table 并移除它们

标签 c++ opencv

如何删除构成框/表格的所有垂直线和水平线

我已经搜索并尝试过..但无法使其工作

最近几天尝试搜索它.. 发现了一些不起作用的例子.. 尝试将各个部分放在一起..

cv:Mat img = cv::imread(input, CV_LOAD_IMAGE_GRAYSCALE);

cv::Mat grad;
cv::Mat morphKernel = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
cv::morphologyEx(img, grad, cv::MORPH_GRADIENT, morphKernel);

cv::Mat res;
cv::threshold(grad, res, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);

// find contours
cv::Mat mask = cv::Mat::zeros(res.size(), CV_8UC1);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(res, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

for(int i = 0; i < contours.size(); i++){
    cv::Mat approx;
    double peri = cv::arcLength(contours[i], true);
    cv::approxPolyDP(contours[i], approx, 0.04 * peri, true);
    int num_vertices = approx.rows;

    if(num_vertices == 4){
        cv::Rect rect = cv::boundingRect(contours[i]);

        // this is a rectangle
    }
}

enter image description here

enter image description here

最佳答案

你可以尝试这样的事情:

  • 限制你的形象
  • 计算连通分量
  • 移除 4 个边界框顶部中至少有 3 个与粒子接触的粒子

这应该给你这样的东西: result

这是相关的源代码:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <limits>

using namespace cv;

struct BBox {

    BBox() :
        _xMin(std::numeric_limits<int>::max()),
        _xMax(std::numeric_limits<int>::min()),
        _yMin(std::numeric_limits<int>::max()),
        _yMax(std::numeric_limits<int>::min())
    {}

    int _xMin;
    int _xMax;
    int _yMin;
    int _yMax;
};

int main()
{
    // read input image
    Mat inputImg = imread("test3_1.tif", IMREAD_GRAYSCALE);

    // create binary image
    Mat binImg;
    threshold(inputImg, binImg, 254, 1, THRESH_BINARY_INV);

    // compute connected components
    Mat labelImg;
    const int nbComponents = connectedComponents(binImg, labelImg, 8, CV_32S);

    // compute associated bboxes
    std::vector<BBox> bboxColl(nbComponents);
    for (int y = 0; y < labelImg.rows; ++y) {

        for (int x = 0; x < labelImg.cols; ++x) {

            const int curLabel = labelImg.at<int>(y, x);
            BBox& curBBox = bboxColl[curLabel];
            if (curBBox._xMin > x)
                curBBox._xMin = x;
            if (curBBox._xMax < x)
                curBBox._xMax = x;
            if (curBBox._yMin > y)
                curBBox._yMin = y;
            if (curBBox._yMax < y)
                curBBox._yMax = y;
        }
    }

    // parse all labels
    std::vector<bool> lutTable(nbComponents);
    for (int i=0; i<nbComponents; ++i) {

        // check current label width
        const BBox& curBBox = bboxColl[i];
        if (curBBox._xMax - curBBox._xMin > labelImg.cols * 0.3)
            lutTable[i] = false;
        else
            lutTable[i] = true;
    }

    // create output image
    Mat resImg(binImg);
    MatConstIterator_<int> iterLab = labelImg.begin<int>();
    MatIterator_<unsigned char> iterRes = resImg.begin<unsigned char>();
    while (iterLab != labelImg.end<int>()) {

        if (lutTable[*iterLab] == true)
            *iterRes = 1;
        else
            *iterRes = 0;

        ++iterLab;
        ++iterRes;
    }

    // write result
    imwrite("resImg3_1.tif", resImg);
}

我只是删除了所有大于图像总宽度 30% 的标签。你的图像很嘈杂,所以我不能像之前说的那样使用边界框顶部触摸,抱歉...

不知道这是否会与您的所有图像匹配,但您可以添加一些几何滤镜来改进第一个版本。

问候,

关于c++ - 检测盒子/ table 并移除它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54871237/

相关文章:

c++ - OpenSSL:尝试使用通过握手获得的 key Material 在本地加密数据

c++ - std::tuple 相当于 std::pair 的第二个成员?

python - 无法在 OpenCV python 中打开视频文件

python - opencv人脸识别: subspaceproject and subspacereconstruct methods in python

c++ - dyld : Library not loaded:/usr/local/opt/jpeg/lib/libjpeg. 9.dylib OpenCV C++ MacOS

c++ - 从 netlink 套接字请求连接设备列表

c++ - 每 X 字节删除空字节 c++ WINAPI

c++ - 带有自定义删除器的类成员唯一指针在初始化列表之外

xcode - 编译错误Xcode 4.3.1-> OpenCv Framework

python - 创建图像的函数 imshow 出错