You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Python的表格内手写数字定位与检测技术求助

表格单元格手写数字检测完整流程

你已经通过腐蚀膨胀提取表格结构,接下来可以按以下步骤完成单元格定位与数字检测:

一、完善表格结构提取

你当前的腐蚀膨胀仅处理了单方向线条,需要合并水平与垂直线条得到完整表格结构:

import cv2
import numpy as np

img = cv2.imread("test.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应阈值比固定阈值更适配手写表格的明暗差异
_, img_bin = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 提取水平表格线
horiz_kernel = np.ones((1, 50), np.uint8)
horiz_lines = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN, horiz_kernel, iterations=2)

# 提取垂直表格线
vert_kernel = np.ones((50, 1), np.uint8)
vert_lines = cv2.morphologyEx(img_bin, cv2.MORPH_OPEN, vert_kernel, iterations=2)

# 合并水平与垂直线条,膨胀让线条更连贯
table_struct = cv2.addWeighted(horiz_lines, 0.5, vert_lines, 0.5, 0.0)
table_struct = cv2.dilate(table_struct, np.ones((3,3), np.uint8), iterations=2)

二、定位所有单元格

通过轮廓提取锁定表格主体,再分割出单个单元格:

# 提取表格的外轮廓(取面积最大的轮廓即为整个表格)
contours, _ = cv2.findContours(table_struct, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
table_contour = max(contours, key=cv2.contourArea)
x_table, y_table, w_table, h_table = cv2.boundingRect(table_contour)
table_roi = img_bin[y_table:y_table+h_table, x_table:x_table+w_table]

# 反向提取单元格区域(表格内的空白区域即为单元格)
inverted_table = cv2.bitwise_not(table_roi)
cell_contours, _ = cv2.findContours(inverted_table, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 筛选有效单元格:排除噪点类小轮廓,保留符合尺寸的区域
cells = []
for cnt in cell_contours:
    area = cv2.contourArea(cnt)
    if 1000 < area < 50000:  # 尺寸范围根据你的表格实际调整
        x_cell, y_cell, w_cell, h_cell = cv2.boundingRect(cnt)
        # 转换回原图坐标
        cells.append((x_cell + x_table, y_cell + y_table, w_cell, h_cell))

# 按行排序单元格(先按纵向y坐标,再按横向x坐标)
cells.sort(key=lambda c: (c[1], c[0]))

三、单元格内数字预处理

对每个单元格的数字做标准化处理,方便后续识别:

processed_digits = []
for (x, y, w, h) in cells:
    # 提取单元格灰度区域
    cell_roi = gray[y:y+h, x:x+w]
    # 自适应阈值二值化
    _, digit_bin = cv2.threshold(cell_roi, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    # 去除小噪点
    digit_bin = cv2.morphologyEx(digit_bin, cv2.MORPH_OPEN, np.ones((2,2), np.uint8), iterations=1)
    # 调整为MNIST标准的28x28尺寸(适配多数数字识别模型)
    digit_resized = cv2.resize(digit_bin, (28, 28))
    processed_digits.append(digit_resized)

四、数字识别

新手可以选择两种简单实现方式:

方法1:OpenCV KNN算法(快速上手)

# 需提前准备MNIST训练数据(将训练集转为(样本数,784)的数组,标签为对应数字)
knn = cv2.ml.KNearest_create()
knn.train(train_data, cv2.ml.ROW_SAMPLE, train_labels)

# 逐个识别数字
for digit in processed_digits:
    test_data = digit.reshape(1, 784).astype(np.float32)
    _, result, _, _ = knn.findNearest(test_data, k=5)
    print("识别结果:", int(result[0][0]))

方法2:深度学习模型(更准确)

用TensorFlow/Keras加载预训练的MNIST模型,直接输入处理好的28x28图像即可得到识别结果,适合需要更高准确率的场景。

关键调整点

  • 阈值适配:如果表格线条模糊,可替换为cv2.adaptiveThreshold做局部阈值处理
  • 轮廓筛选:根据表格实际大小调整单元格面积的筛选范围
  • 噪点去除:若单元格内有多余噪点,可增大形态学操作的核尺寸

内容的提问来源于stack exchange,提问作者user21339606

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:43:18