使用opencv+tesseract识别图片中的表格

这篇具有很好参考价值的文章主要介绍了使用opencv+tesseract识别图片中的表格。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

描述

在java环境中使用opencv和tesserac识别一个图片表格

环境:opencv和tesseract安装在linux环境下,docker将运行springboot服务

opencv和tesseract的安装和docker加载可参考之前的文章

过程

将图片进行预处理,过滤掉颜色等干扰元素

提取图片的水平线和垂直线,并进行重叠过滤

得到水平线和垂直线的交点,根据交点构建单元格

对每个单元格进行识别

1.转换

将image转换成mat

private  Mat bufferedImageToMat(BufferedImage bufferedImage) {
      Mat mat = new Mat();
      try {
            // Convert BufferedImage to byte array
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         
            ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
      
            byteArrayOutputStream.flush();

            byte[] imageInByte = byteArrayOutputStream.toByteArray();

            byteArrayOutputStream.close();

            // Convert byte array to Mat
            MatOfByte matOfByte = new MatOfByte(imageInByte);

            mat = Imgcodecs.imdecode(matOfByte, Imgcodecs.IMREAD_UNCHANGED);
  
        } catch (IOException e) {
            e.printStackTrace();
        }
    return mat;
}

2.图片预处理

原图:

java opencv识别表格,其它,opencv,ocr,java,spring boot

将图片灰度化,并进行边缘检测

灰度化

 //image为加载的图片
 Mat imread = bufferedImageToMat(image);
 Mat gray = new Mat();
 Imgproc.cvtColor(imread, gray,Imgproc.COLOR_BGR2GRAY);

边缘检测

Mat edges = new Mat();
Imgproc.Canny(gray, edges, 50, 150);

java opencv识别表格,其它,opencv,ocr,java,spring boot

3.检测水平线和垂直线

识别水平线和垂直线

            List<MatOfPoint> verticalLines = new ArrayList<>();
            List<MatOfPoint> horizontalLines = new ArrayList<>();

            for (int i = 0; i < lines.rows(); i++) {
                double[] val = lines.get(i, 0);
                if (isVertical(val)) {
                    verticalLines.add(new MatOfPoint(new Point(val[0], val[1]), new Point(val[2], val[3])));

                } else if (isHorizontal(val)) {
                    horizontalLines.add(new MatOfPoint(new Point(val[0], val[1]), new Point(val[2], val[3])));
                }

            }

水平线和垂直线的阈值可根据实际情况调节 

    private  boolean isVertical(double[] line) {
        // 实现判断线是否垂直的逻辑
        return Math.abs(line[0] - line[2]) < 1.0; // 这里的阈值需要根据实际情况调整
    }

    private  boolean isHorizontal(double[] line) {
        // 实现判断线是否水平的逻辑
        return Math.abs(line[1] - line[3]) < 1.0; // 这里的阈值需要根据实际情况调整
    }

java opencv识别表格,其它,opencv,ocr,java,spring boot

 

4.重叠过滤

过滤掉相邻太近,应该为同一条线的线段

    private  List<MatOfPoint> overlappingFilter(List<MatOfPoint> lines, int sortingIndex) {
        List<MatOfPoint> uniqueLines = new ArrayList<>();

        // 按照 sortingIndex 进行排序
        if(sortingIndex == 0){
            //行,检查y坐标
            lines.sort(Comparator.comparingDouble(line -> calculateLineCenter(line).y));
        }else{
            //列检查x坐标
            lines.sort(Comparator.comparingDouble(line -> calculateLineCenter(line).x));
        }


        double distanceThreshold = 5;
        for (int i = 0; i < lines.size(); i++) {
            MatOfPoint line1 = lines.get(i);
            Point[] pts1 = line1.toArray();

            // 如果 uniqueLines 为空或当前线与最后一条线不重复,则添加到 uniqueLines 中
            if (uniqueLines.isEmpty() || !isDuplicate(pts1, uniqueLines.get(uniqueLines.size() - 1).toArray(), distanceThreshold)) {
                uniqueLines.add(line1);
            }
        }

        return uniqueLines;
    }

    private  Point calculateLineCenter(MatOfPoint line) {
        Point[] pts = line.toArray();
        return new Point((pts[0].x + pts[1].x) / 2, (pts[0].y + pts[1].y) / 2);
    }

5.水平线和垂直线的焦点

得到水平线和垂直线的焦点

            List<List<Point>> intersectionList = new ArrayList<>();//交点列表
                for (MatOfPoint hLine : horizontalLines) {
                List<Point> intersectionRow = new ArrayList<>();
                for (MatOfPoint vLine : verticalLines) {
                    Point intersection = getIntersection(hLine, vLine);
                    intersectionRow.add(intersection);
                }
                intersectionList.add(intersectionRow);
            }

获取两条线的焦点文章来源地址https://www.toymoban.com/news/detail-834232.html

    private Point getIntersection(MatOfPoint line1, MatOfPoint line2) {
        Point[] points1 = line1.toArray();
        Point[] points2 = line2.toArray();

        double x1 = points1[0].x, y1 = points1[0].y, x2 = points1[1].x, y2 = points1[1].y;
        double x3 = points2[0].x, y3 = points2[0].y, x4 = points2[1].x, y4 = points2[1].y;

        double det = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
        double x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / det;
        double y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / det;

        return new Point(x, y);
    }

6.构建单元格

             List<List<Rect>> cells = new ArrayList<>();

            // 构建单元格
            for (int i = 0; i < intersectionList.size() - 1; i++) {
                List<Rect> rowCells = new ArrayList<>();
                for (int j = 0; j < intersectionList.get(i).size() - 1; j++) {
                    Point p1 = intersectionList.get(i).get(j);
                    Point p2 = intersectionList.get(i).get(j + 1);
                    Point p3 = intersectionList.get(i + 1).get(j);
                    Rect cell = new Rect((int) p1.x, (int) p1.y, (int) (p2.x - p1.x), (int) (p3.y - p1.y));
                    rowCells.add(cell);
                }
                cells.add(rowCells);
            }

7.对每个单元格进行识别

           for(int i=0;i<cells.size();i++){
                List<String> row = new ArrayList<>();
                for(int j=0;j<cells.get(i).size();j++){
                    Rect cell = cells.get(i).get(j);
                    Mat cellImage = new Mat(gray, cell);
                    BufferedImage bufferedImage = matToBufferedImage(cellImage);
                    if(bufferedImage == null)continue;
                    String text = tess.doOCR(bufferedImage);
                    row.add(text);
                }
            }
    private  BufferedImage matToBufferedImage(Mat mat) {
        int type = BufferedImage.TYPE_BYTE_GRAY;
        if (mat.channels() > 1) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        int bufferSize = mat.channels() * mat.cols() * mat.rows();
        byte[] buffer = new byte[bufferSize];
        mat.get(0, 0, buffer); // 获取所有像素值
        BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type);
        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);
        return image;
    }

到了这里,关于使用opencv+tesseract识别图片中的表格的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于Tesseract模块Python实现提取图片中的文字信息(安装+使用教程)

    Python实现提取图片中的文字可以使用Optical Character Recognition (OCR) 技术来解决。OCR是指将图像中的文本转换成可编辑的文本的过程。Python有许多OCR库,但最流行和最广泛使用的是Tesseract库。 下面是一个使用Python和Tesseract来提取图像中的文本的简单示例代码。 OCR,即光学字符识

    2024年02月05日
    浏览(33)
  • 无法正确识别车牌(Python、OpenCv、Tesseract)

    我正在尝试识别车牌,但出现了错误,例如错误/未读取字符 以下是每个步骤的可视化: 从颜色阈值+变形关闭获得遮罩 以绿色突出显示的车牌轮廓过滤器 将板轮廓粘贴到空白遮罩上 Tesseract OCR的预期结果 BP 1309 GD 但我得到的结果是 BP 1309 6D 我试着把轮廓切成3片 是的,它是有

    2024年02月13日
    浏览(28)
  • 计算机视觉的应用10-图片中的表格结构识别与提取实战

    大家好,我是微学AI,今天给大家介绍一下计算机视觉的应用10-图片中的表格结构识别与提取实战,表格结构识别在信息处理领域中具有广泛应用,但由于表格的多样性和复杂性,以及难以准确解析的布局和格式,传统的方法往往存在一定的局限性。本项目基于深度学习技术

    2024年02月13日
    浏览(26)
  • java 调用 opencv 识别图片

    opencv 的 github 地址 opencv 官网 本文介绍如何使用 java 来调用 opencv opencv下载 页面根据自己电脑操作系统下载最新的安装包,我这里下载的是 4.7.0 版本。 (4.7.0 版本里的 opencv-470.jar 包是使用 jdk11 编译的,所以 需要安装 jdk11 后面测试时才不会报错) 下载后运行文件,开始抽取

    2024年02月10日
    浏览(26)
  • 【Java】使用Apache POI识别PPT中的图片和文字,以及对应的大小、坐标、颜色、字体等

    本文介绍如何使用Apache POI识别PPT中的图片和文字,获取图片的数据、大小、尺寸、坐标,以及获取文字的字体、大小、颜色、坐标。 官方文档:https://poi.apache.org/components/slideshow/xslf-cookbook.html 官方文档和网上的资料介绍的很少,很多元素,需要一点点尝试才能获取到。 注意

    2024年02月12日
    浏览(32)
  • 100天精通Python(实用脚本篇)——第113天:基于Tesseract-OCR实现OCR图片文字识别实战

    🔥🔥 本文已收录于 《100天精通Python从入门到就业》:本专栏专门针对零基础和需要进阶提升的同学所准备的一套完整教学,从0到100的不断进阶深入,后续还有实战项目,轻松应对面试,专栏订阅地址:https://blog.csdn.net/yuan2019035055/category_11466020.html 优点 : 订阅限时9.9付费专

    2024年01月22日
    浏览(38)
  • 【爬虫】8.1. 深度使用tesseract-OCR技术识别图形验证码

    前言:本片文章是基于我之前发的一篇文章《【爬虫】8.1. 使用OCR技术识别图形验证码》而写的,链接为: 【爬虫】8.1. 使用OCR技术识别图形验证码,前面这篇文章比较基础。入门了tesseract-OCR技术之后对它比较感兴趣,故继续深度学习以下。为了衔接比较好,故本篇文章前面

    2024年02月09日
    浏览(33)
  • 如何使用Python识别图片中的二维码

    如何使用Python识别图片中的二维码 二维码是一种方便快捷的信息传递方式,它们广泛应用于电子商务、广告和其他领域。在许多情况下,我们需要识别图片中的二维码,以便从中获取信息。Python是一种流行的编程语言,拥有丰富的图像处理库,可以帮助我们识别二维码。 使

    2024年02月04日
    浏览(28)
  • 【Python 实战】---- 批量识别图片中的文字,存入excel中【使用百度的通用文字识别】

    1. 获取信息图片示例 2. 运行实例 3. 运行结果 4. 各个文件的位置 1. 需求分析 识别图片中的文字【采用百度的通用文字识别】; 文字筛选,按照分类获取对应的文本; 采用 openpyxl 实现将数据存入 excel 中。 2. 获取 access_token 获取本地缓存的

    2024年02月15日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包