如何使用 Python OpenCV 查找表格图像中的行数和列数?

2023-11-29

我们如何通过 OpenCV 获取图像表中的行数和列数。

在我正确的表中获取框的代码

contours, hierarchy = cv2.findContours(img_final_bin, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

def sort_contours(cnts, method="left-to-right"):
# initialize the reverse flag and sort index
reverse = False
i = 0
# handle if we need to sort in reverse
if method == "right-to-left" or method == "bottom-to-top":
    reverse = True
# handle if we are sorting against the y-coordinate rather than
# the x-coordinate of the bounding box
if method == "top-to-bottom" or method == "bottom-to-top":
    i = 1
# construct the list of bounding boxes and sort them from top to
# bottom
boundingBoxes = [cv2.boundingRect(c) for c in cnts]
(cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes),
    key=lambda b:b[1][i], reverse=reverse))
# return the list of sorted contours and bounding boxes
return (cnts, boundingBoxes)

(contours, boundingBoxes) = sort_contours(contours, method="top-to-bottom")


这里有两种方法:第一种使用表格的结构来确定行数和列数,而第二种方法使用单元格计数。

方法#1:表结构

这个想法是我们可以计算表格的水平线和垂直线的数量来确定行数和列数。对于行来说,它是rows = horizontal lines - 1对于列来说,它是columns = vertical lines - 1.

检测到绿色水平线

enter image description here

检测到绿色垂直线

enter image description here

Result

Rows: 7
Columns: 4

Code

import cv2

# Load image, convert to grayscale, Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find number of rows 
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,1))
horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
rows = 0
for c in cnts:
    cv2.drawContours(image, [c], -1, (36,255,12), 2)
    rows += 1

# Find number of columns
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,25))
vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
columns = 0
for c in cnts:
    cv2.drawContours(image, [c], -1, (36,255,12), 2)
    columns += 1

print('Rows:', rows - 1)
print('Columns:', columns - 1)

cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()

方法#2:细胞计数

  1. 获取二值图像。加载图像,转换为灰度,高斯模糊, then 大津的门槛.

  2. 删除单元格内的文本。查找轮廓并使用过滤器cv2.contourArea()通过填充轮廓来删除文本cv2.drawContours()

  3. 反转图像。我们反转图像,使单元格为白色,背景为黑色

  4. 对单元格进行排序并对行/列求和。 We 找到轮廓然后对轮廓进行排序top-to-bottom using imutils.contours.sort_contours。接下来我们迭代轮廓并找到centroid以获得(cX, cY)坐标。这个想法是我们可以比较cY每个单元格的值,通过使用偏移量来确定它是新行还是同一行中的单元格。如果以下情况,单元格应位于同一行:cY值是+/-某个偏移值。如果它更大,则意味着该单元格位于新行中。我们构建一个模型表,其中表的长度为您提供行数,而任何索引的长度为您提供列数。


二值图像

enter image description here

删除文本轮廓+倒置图像

enter image description here

这是迭代每个单元格以计算行数和列数的可视化

enter image description here

Result

Rows: 7
Columns: 4

Code

import numpy as np
from imutils import contours
import cv2

# Load image, grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours and remove text inside cells
cnts = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < 4000:
        cv2.drawContours(thresh, [c], -1, 0, -1)

# Invert image
invert = 255 - thresh
offset, old_cY, first = 10, 0, True
visualize = cv2.cvtColor(invert, cv2.COLOR_GRAY2BGR)

# Find contours, sort from top-to-bottom and then sum up column/rows
cnts = cv2.findContours(invert, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
(cnts, _) = contours.sort_contours(cnts, method="top-to-bottom")
for c in cnts:
    # Find centroid
    M = cv2.moments(c)
    cX = int(M["m10"] / M["m00"])
    cY = int(M["m01"] / M["m00"])
    
    # New row
    if (abs(cY) - abs(old_cY)) > offset:
        if first:
            row, table = [], []
            first = False
        old_cY = cY
        table.append(row)
        row = []
    
    # Cell in same row
    if ((abs(cY) - abs(old_cY)) <= offset) or first:
        row.append(1)
   
    # Uncomment to visualize 
    '''
    cv2.circle(visualize, (cX, cY), 10, (36, 255, 12), -1) 
    cv2.imshow('visualize', visualize)
    cv2.waitKey(200)
    '''

print('Rows: {}'.format(len(table)))
print('Columns: {}'.format(len(table[1])))

cv2.imshow('invert', invert)
cv2.imshow('thresh', thresh)
cv2.waitKey()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Python OpenCV 查找表格图像中的行数和列数? 的相关文章

  • Keras model.predict 函数给出输入形状错误

    我已经在 Tensorflow 中实现了通用句子编码器 现在我正在尝试预测句子的类概率 我也将字符串转换为数组 Code if model model type universal classifier basic class probs
  • 来自 pandas 数据帧的烛台图,用日期替换索引

    此代码给出了带有移动平均线的烛台图 但 x 轴位于索引中 我需要 x 轴位于日期中 需要做什么改变 import numpy as np import pandas as pd import matplotlib pyplot as plt
  • 将 Python Pandas DataFrame 写入 Word 文档

    我正在努力创建一个使用 Pandas DataFrames 的 Python 生成的报告 目前我正在使用DataFrame to string 方法 但是 这会作为字符串写入文件 有没有办法让我实现这一目标 同时将其保留为表格 以便我可以使
  • 在linux上安装python ssl模块,无需重新编译

    是否可以在已经安装了 OpenSSL 的 Linux 机器上安装 python 的 SSL 模块 而无需重新编译 python 我希望它就像复制几个文件并将它们包含在库路径中一样简单 Python版本是2 4 3 谢谢 是否可以在已经安装了
  • Python - Unicode 到 ASCII 的转换

    我无法在不丢失数据的情况下将以下 Unicode 转换为 ASCII u ABRA xc3O JOS xc9 I tried encode and decode他们不会这么做 有人有建议吗 Unicode 字符u xce0 and u xc
  • 设置高亮大括号的 vim 颜色主题

    如何更改突出显示大括号的 vim 配色方案 我希望实际编辑 vim 主题文件以使更改永久生效 问候 克雷格 匹配括号的自动高亮颜色称为MatchParen 您可以通过执行以下操作来更改 vimrc 中的颜色 highlight MatchP
  • 在 Linux 上使用多处理时,TKinter 窗口不会出现

    我想生成另一个进程来异步显示错误消息 同时应用程序的其余部分继续 我正在使用multiprocessingPython 2 6 中的模块来创建进程 我试图用以下命令显示窗口TKinter 这段代码在Windows上运行良好 但在Linux上
  • 将 window.location 传递给 Flask url_for

    我正在使用 python 在我的页面上 当匿名用户转到登录页面时 我想将一个变量传递到后端 以便它指示用户来自哪里 发送 URL 因此 当用户单击此锚链接时 a href Sign in a 我想发送用户当前所在页面的当前 URL
  • 如何用正则表达式替换多个匹配/组?

    通常我们会编写以下内容来替换一场比赛 namesRegex re compile r is life re I replaced namesRegex sub r butter There is no life in the void pr
  • 为什么 Collections.counter 这么慢?

    我正在尝试解决罗莎琳德的基本问题 即计算给定序列中的核苷酸 并在列表中返回结果 对于那些不熟悉生物信息学的人来说 它只是计算字符串中 4 个不同字符 A C G T 出现的次数 我期望collections Counter是最快的方法 首先
  • 如何按 pandas 中的值对系列进行分组?

    我现在有一只熊猫Series与数据类型Timestamp 我想按日期对其进行分组 并且每组中有许多行具有不同的时间 看似显而易见的方法类似于 grouped s groupby lambda x x date 然而 熊猫的groupby按索
  • 从迭代器外部将 StopIteration 发送到 for 循环

    有几种方法可以打破一些嵌套循环 他们是 1 使用中断 继续 for x in xrange 10 for y in xrange 10 print x y if x y gt 50 break else continue only exec
  • Python 相当于 Scala 案例类

    Python 中是否有与 Scala 的 Case Class 等效的东西 就像自动生成分配给字段而无需编写样板的构造函数一样 当前执行此操作的现代方法 从 Python 3 7 开始 是使用数据类 https www python org
  • 两种 ODE 求解器之间的差异

    我想知道 两者之间有什么区别ODEINT and solve ivp用于求解微分方程 它们之间有什么优点和缺点 f1 solve ivp f 0 1 y0 y0 is the initial point f2 odeint f y0 0 1
  • 为什么Android的ImageReader类这么慢?

    我尝试了适用于 Android 3 4 1 的全新 OpenCVJavaCamera2View但它太慢了 仅显示相机视图约 15 fps 当我尝试较旧的JavaCameraView相反 它给了我很好的结果 30fps 这是我相机的极限 我想
  • pandas.read_fwf 忽略提供的数据类型

    我正在从文本文件导入数据框 我想指定列的数据类型 但 pandas 似乎忽略了dtype input 一个工作示例 from io import StringIO import pandas as pd string USAF WBAN S
  • 为boost python编译的.so找不到模块

    我正在尝试将 C 代码包装到 python 中 只需一个类即可导出两个函数 我编译为map so 当我尝试时import map得到像噪音一样的错误 Traceback most recent call last File
  • MoviePY 无法在 Windows 上检测 ImageMagick 二进制文件

    我刚买了一台新笔记本电脑 想要设置MoviePY在那新的Windows 64x Python3 7 0 机器 我对所有内容都进行了三次检查 但是当涉及到我的代码的文本部分时 它向我抛出了这个错误 OSError MoviePy Error
  • 如何同时接受int和float类型的输入?

    我正在制作一个货币转换器 如何让 python 同时接受整数和浮点数 我就是这样做的 def aud brl amount From to ER 0 42108 if amount int if From strip aud and to
  • 在Python中停止ThreadPool中的进程

    我一直在尝试为控制某些硬件的库编写一个交互式包装器 用于 ipython 有些调用对 IO 的影响很大 因此并行执行任务是有意义的 使用 ThreadPool 几乎 效果很好 from multiprocessing pool import

随机推荐

  • 将shared_ptr分配给weak_ptr

    我想将构造的shared ptr分配给weak ptr std weak ptr
  • 如何在“sub”表达式中使用lambda表达式参数?

    我希望能够构建类似以下委托的表达式 Func
  • 无法停止 Firebase JobDispatcher 服务

    可能重复 我创建了一个 JobDispatcher 服务来不断在后台获取用户位置并将用户位置发布到服务器 为此 我创建了一个作业 如下所示 private void startLocationJobService Check if loca
  • MVC .net core 未正确显示特殊字符

    我在 MVC net core 网站中有一个非常简单的视图 model MvcSearch Models SearchModel ViewData Title Index h2 Buscador de Informaci n h2 div
  • Struts 2.0 中登录时使用的拦截器

    我正在设计一个基本应用程序 其中用户提供他的用户 ID 和密码 如果登录成功 他将被重定向到主页 现在 如果用户 ID 和密码不为空 我想使用拦截器进行验证 但我无法找出如何访问拦截器中请求参数的值 JSP代码
  • NUnit 在汇编中找不到测试

    我用 MSTest 继承了一个程序集 但这些测试是在构建机器上使用 nunit console 运行的 不确定它是如何工作的 所以我决定对其进行整理并将其更改为适当的 NUnit 测试 但现在 nunit console 或 gui 找不到
  • 如何在firebase中管理用户的不同身份验证

    请帮助我在以下情况下找到正确的解决方案 我正在使用 swift 开发 ios 应用程序 它将使用 Firebase 作为后端 用户应该能够使用电子邮件 密码或 和 Facebook 登录 Firebase 也许稍后会添加谷歌 对我来说 为每
  • Python列表列表初始化

    我知道 10 将给出 10 个相同空的引用 并且 for i in range 10 将给出 10 个空列表 但在这个例子中 def get list thing return thing for i in range 10 a get l
  • 使用 Vuex 4 时,Vue.js 2 中出现警告

    当我尝试在 Vue 2 中使用 Vuex 4 作为商店时 控制台中出现警告 我该如何解决它 在 vue 中找不到导出 注入 反应 监视 以下是package jsonVue v2 x 和 Vuex v4 x 的条目 store js imp
  • 滑入和滑出图像

    我试图实现一种平滑的效果 当一个图像滑出时 另一个图像滑入 此动画需要采用一种方式 当一个图像滑出时 另一个图像滑入 以便它们都占用内部空间同时div 就像是this or this 我创建了一个简单的jsFiddle 描述他面临的问题 g
  • JemmyFx jar 位置

    我想测试我的 JavaFX 应用程序 我听说 JemmyFX 是执行此操作的正确工具 但是 我找不到要下载的 Jar 我尝试在网上搜索它 但我只能找到this页面显示该项目的最后一次提交是一年多前 我有两个问题 1 JemmyFX 是否已发
  • cudaMemcpyToSymbol 性能

    我有一些函数可以将变量加载到常量设备内存中并启动内核函数 我注意到 一个函数第一次将变量加载到常量内存中需要 0 6 秒 但下一次加载常量内存的速度非常快 0 0008 秒 无论哪个函数是 main 中的第一个函数 都会发生此行为 下面是示
  • 如何折叠 t-sql 中空值的行?

    我的查询处境很奇怪 我的目标是显示每个人多笔交易的存款和取款总额并显示它们 我收到多行 需要将其合并为一行 这一切都需要在一个查询中发生 SELECT lastname firsname case when upper category W
  • html 中的 ol 中不能有 ul

    当我测试 HTML 时 出现以下验证错误 Please look at the attached image for the HTML code Element ul not allowed as child of element olin
  • JFrame 以及为什么保持运行

    为什么如果我创建一个 JFrame 那么程序仍然运行直到 即 我使用窗口的小 退出按钮 关闭它 我寻找这个答案但失败了 我唯一猜测的是当我这样做时new JFrame 这就像一个特别的new 它在 EDT 中保留对象的引用 因此它将始终被引
  • 用于名称属性中带有方括号的输入的 jQuery 选择器

    我试图选择名称属性中带有方括号的这个元素
  • 如何将 getAccessToken 与 fetch 函数集成以将数据从 DRF 后端加载到 React 前端?

    这里是 React 新手 但精通 Django 我有一个简单的 fetch 函数 它工作得很好 但我的项目没有涉及登录身份验证 现在我已经配置了登录系统 我的后端拒绝使用任何访问令牌来处理请求 我的登录身份验证对我来说非常陌生 或多或少是从
  • 基于两个向量构造该矩阵 MATLAB

    我确实有 2 个向量 我想基于 r 和 c 构造一个矩阵 r 1 2 4 6 8 c 2 4 6 8 10 我想构造一个矩阵 A 使得 A 1 2 A 2 4 A 4 6 A 6 8 A 8 10 1 其他元素 0 请帮忙 您可以使用稀疏矩
  • *整个*文档中某个元素之后的下一个元素

    这是多次被问到的问题的变体 给定任何元素 我希望能够在该元素之后找到任何其他元素entire文档 它可以是同级元素 但也可以是之后发生的任何其他元素 例如 给定以下标记 div p Hello p div p Foo p p class b
  • 如何使用 Python OpenCV 查找表格图像中的行数和列数?

    我们如何通过 OpenCV 获取图像表中的行数和列数 在我正确的表中获取框的代码 contours hierarchy cv2 findContours img final bin cv2 RETR TREE cv2 CHAIN APPRO