如何移除扫描图像边缘的零散文本?现有OpenCV代码问题求助
问题分析与解决方案
原代码的核心问题
- 输出图像计算错误:最后一行
labels*255/num_labels会把有效像素值压缩到远低于255的范围,直接导致生成黑底图像。 - 边缘文本过滤不完整:只处理了左侧边缘的小对象,完全没覆盖右侧边缘的情况,而且
labels[stats[i][1], stats[i][2]] != 0属于冗余判断(i从1开始的连通区域本身就是非背景)。 - 冗余操作:移除目标标签后再次执行
connectedComponentsWithStats完全没必要,反而打乱了结果逻辑。
修正后的代码
import cv2 import numpy as np # 加载灰度扫描图 img = cv2.imread("1.jpg", cv2.IMREAD_GRAYSCALE) # 反相二值化:让文字为白色,背景为黑色,方便连通区域分析 _, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 获取所有连通区域的属性(位置、大小等) num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh, connectivity=8) # 创建空掩码,用于保留需要的区域 result_mask = np.zeros_like(labels, dtype=np.uint8) img_width = img.shape[1] # 遍历每个连通区域(跳过背景,i从1开始) for i in range(1, num_labels): x = stats[i][0] # 区域左上角x坐标 w = stats[i][2] # 区域宽度 # 判断是否是需要移除的边缘零散文本:左侧/右侧边缘50像素内,且宽度小于50 is_edge_noise = (x < 50 or (x + w) > img_width - 50) and w < 50 if not is_edge_noise: # 保留非边缘文本区域,设为白色 result_mask[labels == i] = 255 # 转回黑字白底的原图风格,保存结果 final_img = cv2.bitwise_not(result_mask) cv2.imwrite("output_image.png", final_img)
关键改进说明
- 修复黑底问题:通过掩码保留有效区域,最后用
bitwise_not还原成和原图一致的黑字白底,避免像素值被错误压缩。 - 全覆盖边缘过滤:新增右侧边缘判断
(x + w) > img_width - 50,同时保留宽度限制,确保只移除边缘的零散小文本,不影响正文内容。 - 简化流程:去掉冗余的二次连通分量分析,直接通过掩码生成结果,代码更高效易懂。
内容的提问来源于stack exchange,提问作者jonah_w
相关产品推荐
相关产品推荐

