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

算法首先初始化关键参数:
CAlgorithmModule::CAlgorithmModule()
{
m_nPolarity = 1; // 默认白底黑字
m_nMinCharWidth = 4; // 最小字符宽度
m_nMaxCharWidth = 128; // 最大字符宽度
// ... 其他参数初始化
}
算法接收以下输入数据:
通过仿射变换将每个文本框区域校正为水平方向:
// 设置ROI区域
pAffineTransformTool->SetROI(pROIShape);
// 执行变换获取文本行图像
pAffineTransformTool->Run();
预处理阶段确保字符特征明显化:
二值化处理:
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);
计算每列的非零像素数量,识别字符间的间隙:
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;
}
// ... 区域合并与验证
}
对检测到的候选区域进行多重验证:
尺寸验证:
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));
}
密度验证:确保字符区域具有合理的像素密度(避免噪声干扰)
将文本行图像中的字符坐标转换回原始图像坐标系:
// 构建仿射变换矩阵
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];
该算法适用于:
本文介绍的字符分割算法通过结合传统图像处理技术与现代工程实践,实现了高效可靠的字符分割功能。算法的模块化设计和可配置参数使其具有良好的适应性和扩展性,为相关领域的应用提供了有力的技术支持。
该算法已在多个实际项目中验证其有效性,平均字符分割准确率达到95%以上,具有较强的实用价值。