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

如何编程分割手写时间戳单数字以适配MNIST分类器?

解决手写时间戳数字分割的可靠方案

嗨,看你描述的情况——手动提取数字给MNIST分类器效果极佳,但自动分割卡壳,其实核心可以利用你时间戳**格式固定(HH:MM)**这个关键特点,完全绕开不稳定的轮廓检测,用固定区域分割的方法来解决,这比依赖轮廓靠谱多了。

下面是一步步可落地的实现思路,结合OpenCV来做:

1. 先做图像预处理,统一输入质量

不管是从整页报告截取的列,还是单条时间戳,先把图像标准化:

  • 转灰度图:cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  • 用自适应二值化对付手写的明暗不均:cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2),这样能把手写数字和背景分离开
  • 用形态学操作去小噪声:cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones((2,2), np.uint8)),避免小斑点干扰后续处理

2. 定位单个时间戳的整体区域

从你提供的截图来看,所有时间戳都在同一列,位置对齐得很好。如果是整页报告,你可以先按行截取每个时间戳的矩形区域——要么用轮廓检测定位每行的文本块,要么直接利用列的坐标范围(如果报告格式规整的话),把每个时间戳单独抠出来。

3. 按固定比例分割单个数字

因为时间格式是XX:XX,四个数字加中间的冒号,位置相对固定。你可以先手动测量几个样本里数字的宽度比例,比如:

  • 假设单个时间戳的整体宽度是w,把它分成5个等份(前两个数字各占1份,冒号占1份,后两个数字各占1份),如果冒号更窄,就微调比例(比如冒号占0.8份,每个数字占1.05份)
  • 用代码裁剪的话,示例如下:
    # time_roi是已经截取好的单个时间戳二值图
    roi_width = time_roi.shape[1]
    digit_segment_width = roi_width // 5  # 可根据实际样本微调这个数值
    
    # 分割四个数字,跳过中间的冒号区域
    digit_1 = time_roi[:, 0:digit_segment_width]
    digit_2 = time_roi[:, digit_segment_width:2*digit_segment_width]
    digit_3 = time_roi[:, 3*digit_segment_width:4*digit_segment_width]
    digit_4 = time_roi[:, 4*digit_segment_width:5*digit_segment_width]
    

4. 适配MNIST分类器的输入规格

MNIST的输入是28x28的灰度图,所以要把每个裁剪后的数字调整成对应规格:

  • 先把数字区域resize到20x20(保留手写的细节,避免直接缩到28x28丢失特征)
  • 创建一个28x28的空白画布,把20x20的数字放在画布中心,周围填充空白,这样数字的位置和MNIST训练样本的对齐方式一致,能提升识别准确率

5. 小偏移的优化方案

如果少数行的数字有轻微左右偏移,可以用投影直方图来校准:

  • 对单个时间戳的二值图,计算水平方向的像素投影(统计每列的白色像素数),找到数字聚集的左右边界,然后调整分割的起始位置,确保每个数字都被完整裁剪

这个方法完全避开了轮廓检测的痛点——比如手写数字连笔、和冒号粘连的问题,毕竟你的时间格式是固定的,固定区域分割是最适配你场景的方案,和你手动PS提取的逻辑一致,效果应该会很好。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:35:35