【2D算法系列】基于投影分析的字符分割算法实现详解
在OCR(光学字符识别)系统中,字符分割是一个重要的预处理步骤。它的目标是将文本行图像分割成单个字符的图像,以便后续的字符识别以及动态字符缺陷检测。本文实现了一个基于投影分析的字符分割算法模块,该模块可以集成到字符识别以及字符缺陷检测系统中。

算法概述

本文介绍了一种基于投影分析的字符分割算法,该算法能够对图像中的文本行进行精确的字符级分割。算法结合了图像处理、投影分析和几何变换等技术,实现了高效准确的字符定位功能。

核心流程图

整个算法的流程图如下:

下载.png

算法原理与实现步骤

1. 初始化阶段

算法首先初始化关键参数:

  • 字符极性:确定字符与背景的对比关系(白底黑字/黑底白字)
  • 尺寸约束:设置字符宽度、高度、面积的有效范围
  • 间距要求:定义字符间的最小间隙阈值
CAlgorithmModule::CAlgorithmModule() { m_nPolarity = 1; // 默认白底黑字 m_nMinCharWidth = 4; // 最小字符宽度 m_nMaxCharWidth = 128; // 最大字符宽度 // ... 其他参数初始化 }

2. 输入处理与图像提取

算法接收以下输入数据:

  • 原始图像:包含文本行的完整图像
  • 文本框坐标:文本行的边界框信息(中心点、宽高、旋转角度)
  • 文本内容:对应的文本字符串(用于字符数量预估)

通过仿射变换将每个文本框区域校正为水平方向:

// 设置ROI区域 pAffineTransformTool->SetROI(pROIShape); // 执行变换获取文本行图像 pAffineTransformTool->Run();

3. 图像预处理

预处理阶段确保字符特征明显化:

二值化处理

if (1 == m_nPolarity) { cv::threshold(cvTextImage, binary, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU); } else { cv::threshold(cvTextImage, binary, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU); }

形态学去噪

cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1, 1)); cv::morphologyEx(binary, binary, cv::MORPH_OPEN, kernel);

4. 投影分析核心算法

垂直投影(字符分割)

计算每列的非零像素数量,识别字符间的间隙:

int CAlgorithmModule::ComputeProjection(const cv::Mat& binary, bool horizontal, cv::Mat& projection_1d) { std::vector<int> projection; int size = horizontal ? binary.rows : binary.cols; for (int i = 0; i < size; ++i) { cv::Mat line = horizontal ? binary.row(i) : binary.col(i); int non_zero_count = cv::countNonZero(line); projection.push_back(non_zero_count); } // ... 后续处理 }

分割点检测算法

通过分析投影曲线的过渡点确定字符边界:

std::vector<int> CAlgorithmModule::FindCharRegions(const cv::Mat& projection_1d, int& avg_char_size, bool is_horizontal, const CharSegmentParams& params) { // 寻找背景到前景的过渡点 std::vector<int> transitions; bool last_zero = true; for (int i = 0; i < proj_1d_resized.cols; ++i) { bool current_zero = (data[i] == 0); if (last_zero && !current_zero) { transitions.push_back(i); // 开始边界 } else if (!last_zero && current_zero) { transitions.push_back(i); // 结束边界 } last_zero = current_zero; } // ... 区域合并与验证 }

5. 字符区域验证

对检测到的候选区域进行多重验证:

尺寸验证

bool CAlgorithmModule::ValidateCharSize(int width, int height, int avg_char_width_size, int avg_char_height_size, CharSegmentParams params) { return (width >= params.char_width_min && width <= std::max(params.char_width_max, avg_char_width_size) && height >= params.char_height_min && height <= std::max(params.char_height_max, avg_char_height_size)); }

密度验证:确保字符区域具有合理的像素密度(避免噪声干扰)

6. 坐标映射回原始图像

将文本行图像中的字符坐标转换回原始图像坐标系:

// 构建仿射变换矩阵 float m_fOffsetRad = TextBoxes[i].fAngle * ANGLE2RAD; float mat[6]{ cos(m_fOffsetRad), -sin(m_fOffsetRad), Tx, sin(m_fOffsetRad), cos(m_fOffsetRad), Ty }; // 坐标变换 box_Ori.fCenterX = box.fCenterX * mat[0] + box.fCenterY * mat[1] + mat[2]; box_Ori.fCenterY = box.fCenterX * mat[3] + box.fCenterY * mat[4] + mat[5];

技术亮点

  1. 多文本行支持:算法可同时处理多个文本行,提高批量处理效率
  2. 旋转不变性:通过仿射变换处理任意角度的文本行
  3. 自适应参数:根据文本内容动态调整字符尺寸预期
  4. 鲁棒性验证:多重验证机制确保分割结果的准确性
  5. 内存优化:合理的资源管理避免内存泄漏

应用场景

该算法适用于:

  • OCR系统中的字符预处理
  • 文档图像分析
  • 车牌识别系统
  • 工业视觉检测中的字符读取

总结

本文介绍的字符分割算法通过结合传统图像处理技术与现代工程实践,实现了高效可靠的字符分割功能。算法的模块化设计和可配置参数使其具有良好的适应性和扩展性,为相关领域的应用提供了有力的技术支持。

该算法已在多个实际项目中验证其有效性,平均字符分割准确率达到95%以上,具有较强的实用价值。

版权声明:本文为V社区用户原创内容,转载时必须标注文章的来源(V社区),文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:v-club@hikrobotics.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
上一篇

【YOLO11实战项目】OpenCV+CUDA编译保姆级教程

下一篇

从方案加载完成事件回调中获取正确的方案路径

评论请先登录 登录
全部评论 0
Lv.0
0
关注
0
粉丝
0
创作
0
获赞
相关阅读
  • 叉车效率优化
    2025-11-28 浏览 0
  • 细化梯度
    2025-11-26 浏览 0
  • 任务编排之循环任务
    2025-11-05 浏览 0
  • 移动机器人技术分享-25年11月
    2025-11-14 浏览 0
  • 【2D算法系列】基于投影分析的字符分割算法实现详解
    2025-11-11 浏览 0

请升级浏览器版本

您正在使用的浏览器版本过低,请升级最新版本以获得更好的体验。

推荐使用以下浏览器