如何使用OpenCV C++检测文本图像中的干扰噪声线条?
基于OpenCV C++的文本图像干扰线条检测与去除方案
该方案利用线条与文本字符的形态学特征差异实现干扰线条的精准检测,最终输出效果可接近手动Photoshop处理结果。
实现步骤
步骤1:图像预处理
首先将输入图像转为灰度图,使用自适应阈值做二值化处理,避免光照不均对后续检测造成干扰,二值化时反转前景背景,让文本和线条为白色、背景为黑色。
步骤2:形态学操作提取候选线条
创建不同方向的线性结构元素,通过形态学开运算提取对应方向的候选线条区域,结构元素的长度需大于普通文本字符的最大宽/高,确保只会提取到跨多个字符的长线条。
可以根据实际噪声情况,新增45度、135度等倾斜方向的结构元素,覆盖斜向线条的检测需求。
步骤3:连通域过滤排除误检
对候选线条区域做连通域分析,计算每个连通域最小外接矩形的宽高比,过滤掉宽高比不符合线条特征、面积过小的区域,避免把长文本、大字符误判为线条,得到最终的干扰线条掩码。
步骤4:线条区域修复
使用生成的线条掩码,调用OpenCV内置的图像修复算法填充线条区域,自动恢复被线条覆盖的文本内容,文本边缘恢复精度高。
完整可运行代码
#include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main() { // 读取输入图像 Mat src = imread("input_noisy_text.jpg"); if(src.empty()) return -1; Mat gray, binary, mask; // 灰度化+自适应二值化 cvtColor(src, gray, COLOR_BGR2GRAY); adaptiveThreshold(~gray, binary, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 15, -2); // 生成不同方向的结构元素提取候选线条 int line_length = 30; // 可根据图像分辨率调整,需大于普通字符的最大宽度 Mat horizontal_kernel = getStructuringElement(MORPH_RECT, Size(line_length, 1)); Mat vertical_kernel = getStructuringElement(MORPH_RECT, Size(1, line_length)); // 可选添加倾斜方向的结构元素适配斜向噪声 // Mat kernel45 = getStructuringElement(MORPH_CROSS, Size(line_length, line_length)); // 形态学开运算提取线条 Mat horizontal_lines, vertical_lines, line_mask; morphologyEx(binary, horizontal_lines, MORPH_OPEN, horizontal_kernel); morphologyEx(binary, vertical_lines, MORPH_OPEN, vertical_kernel); line_mask = horizontal_lines | vertical_lines; // 连通域过滤误检区域 vector<vector<Point>> contours; findContours(line_mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); Mat final_mask = Mat::zeros(line_mask.size(), CV_8UC1); for(auto &cnt : contours) { RotatedRect rrect = minAreaRect(cnt); float ratio = max(rrect.size.width, rrect.size.height) / min(rrect.size.width, rrect.size.height); // 宽高比大于8判定为线条,可根据实际场景调整阈值 if(ratio > 8 && contourArea(cnt) > 20) { drawContours(final_mask, vector<vector<Point>>{cnt}, -1, Scalar(255), 2); } } // 图像修复去除线条 Mat result; inpaint(src, final_mask, result, 3, INPAINT_TELEA); imwrite("clean_text.jpg", result); return 0; }
参数调整说明
- 结构元素长度
line_length:如果图像分辨率高、噪声线条长,可增大到4050;如果线条短细,可减小到1520 - 宽高比阈值:如果出现长文本被误判为线条,可将阈值从8调高到1012;如果有线条漏检,可降低到56
- 修复半径:
inpaint函数的第4个参数为修复半径,线条越粗半径越大,默认3即可,粗线条可调整到5
内容的提问来源于stack exchange,提问作者Quang
相关产品推荐
相关产品推荐

