检测纸张边缘并裁剪

Detecting Paper Edge and Crop it

我正在使用 C# 编写一个程序来检测纸张边缘并从图像中裁剪出纸张的方形边缘。

下面是我要裁剪的图片。论文将始终出现在页面底部。

我已经阅读了这些链接,但我仍然不知道该怎么做。

OpenCV C++/Obj-C: Detecting a sheet of paper / Square Detection

编辑:我正在为这个 OCR 项目使用 EMGU

  • 决定纸张颜色
  • 确定增量以允许颜色变化
  • 确定沿底部的点进行垂直测试
  • 向上进行垂直测试,收集颜色停止出现的最小 y
  • 至少做 10-20 次这样的测试

结果 y 应该比你想要保留的多 1。如果图像太亮,您可能需要插入一个限制以避免裁剪所有内容。要么优化算法,要么将这样的图片标记为例外人工处理!

要裁剪,请使用 DrawImage 重载源和目标矩形!

这里还有一些提示:

  • 要找到纸张颜色,您可以从左下边缘沿对角线向右向上移动,直到找到 Color.GetBrightness > 0.8 的像素;然后进一步移动 2 个像素以清除任何抗锯齿像素。

  • 合理的增量取决于您的图像;从 10%

  • 开始
  • 使用底部随机游走;当你完成后,可以在第一遍中找到的最小值附近添加一个额外的遍。

  • 垂直测试可以使用 GetPixel 来获取颜色,如果速度太慢,您可能需要查看 LockBits。但是先搞定搜索算法,再考虑优化!

如果您 运行 遇到代码问题,请扩展您的问题!

您还可以:

  1. 将您的图像转换为灰度图像
  2. 按像素强度应用ThresholdBinary
  3. 求等高线。
    要查看有关查找轮廓的示例,您可以查看 this post.
    FundContours 方法不关心轮廓大小。在找到轮廓之前唯一要做的就是通过对图像进行二值化来强调它们(我们在步骤 2 中这样做)。
    有关更多信息,请参阅 OpenCV 文档findContours, example.

  4. 根据边界框的大小和位置找到合适的轮廓。
    (在这一步中,我们遍历所有在轮廓上找到的东西,并尝试找出哪一个是纸张的轮廓sheet,使用已知的纸张尺寸,它们的比例和相对位置 - 图片的左下角)。

  5. 使用纸张 sheet 的边界框裁剪图像。

    Image<Gray, byte> grayImage = new Image<Gray, byte>(colorImage);
    Image<Bgr, byte> color = new Image<Bgr, byte>(colorImage);
    
    grayImage = grayImage.ThresholdBinary(new Gray(thresholdValue), new Gray(255));
    
    using (MemStorage store = new MemStorage())
    for (Contour<Point> contours= grayImage.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE, store); contours != null; contours = contours.HNext)
    {
        Rectangle r = CvInvoke.cvBoundingRect(contours, 1);
    
        // filter contours by position and size of the box
    }
    
    // crop the image using found bounding box
    

更新:我添加了更多细节。