线路端点检测

时间:2012-04-17 22:16:06

标签: c# line ocr detection endpoint

我打算在C#中检测从字符(OCR)生成的行的端点。我想要这样的东西:

enter image description here

我的意思是“端点”是我想得到字符中任何行的末尾...例如,'C'有两个端点(一个在顶部,一个在底部),如上面的图像表示为红色像素。我可以从“更胖”的现有扫描字符中提取单行,我可以进行边缘检测和Flood-fill分析,但我似乎无法复制上面的内容!任何指向文章或现有代码的指针都将非常感谢!任何代码示例都可以,因为我可以轻松地将C ++或任何.NET语言转换为C#。

谢谢,乔希

2 个答案:

答案 0 :(得分:1)

由于您还没有“端点”的定义,我建议:

  • 黑点是所有邻居(即曼哈顿距离<= 3的黑点)位于小于45度的扇区中的终点。

找到每个相邻黑点的角度应该不会太困难。对这些角度进行排序并找到范围也并不困难,尽管您需要注意不连续性(角度突然变化360度)。在没有实际计算角度的情况下按坡度排序可能稍快一些。使用提前退出逻辑可以获得额外的加速。

答案 1 :(得分:0)

这就是我这样做的方式。 对于每个像素,如果不是0,则计算该像素周围的3×3网格中的像素数而不是0。如果数字为2,则您有一个终点线。

// count the number of points in the neighborhood of our pixel
inline int countNeighborhood(cv::Mat &img, int xc, int yc)
{
    if (img.empty()) return 0;
    if (img.type() != CV_8UC1) return 0;
    xc++;
    yc++;
    int iCnt = 0;
    for (int y = yc - 2; y <= yc; y++)
    {
        if ((y < 0) || (y >= img.rows)) continue;
        uint8_t *buf = img.ptr(y);
        for (int x = xc - 2; x <= xc; x++)
            if ((x > 0) && (x < img.cols) && (buf[x])) iCnt++;
    }
    return iCnt;
}

/*  get endpoints of a image with lines in it
*/
std::vector<cv::Point> getEndPoints(cv::Mat &img)
{
    std::vector<cv::Point> res;
    for (int y = 0; y < img.rows; y++)
    {
        uint8_t *buf = img.ptr(y);
        for (int x = 0; x < img.cols; x++)
        {
            if (buf[x] == 0) continue;
            int iCnt = countNeighborhood(img, x, y);
            if (iCnt == 2) res.push_back(cv::Point(x, y));
        }
    }
    return res;
}
如果你愿意,可以用内核完成countNeighborhood。 函数getEndPoints返回所有找到的端点的数组。

P.S。此功能适用于黑色(0)背景和白色(1-255)als线。