Python OpenCV 实现红色印章清除基于红色通道和 OTSU 阈值在扫描件、表单、证书等图片中红色印章经常会覆盖正文内容影响后续文字识别或信息读取。这里介绍一种轻量级的印章清除方法不依赖深度学习模型只使用 OpenCV 对红色通道进行阈值处理将红色印章尽量从图像中剔除。这个方法的核心思路很简单红色印章在 RGB/BGR 图像中通常会让红色通道明显偏高。先提取红色通道再用 OTSU 自动阈值找出合适的二值化分界点。根据阈值动态调整过滤条件把红色印章区域压到白底。最终输出一张黑白二值图更适合作为文字识别或版面分析的前处理图像。需要注意这个方法不是图像修复算法它的目标不是生成一张视觉上完全自然的“无章原图”而是尽可能减少红章对黑色文字的干扰。效果示例下面是一个演示效果左侧是带红色印章的图片右侧是经过clear_stamp处理后的结果。可以看到红色印章基本被去掉黑色文字和表格线仍然保留下来。但输出结果变成了黑白二值图局部线条也可能出现断裂这是阈值法的正常副作用。完整代码下面是一个可以单独保存为clearstamp.py的版本# coding: utf-8importcv2importnumpyasnpdefclear_stamp(target_path): 清除图片中的红色印章。 Args: target_path: 图片路径或者 OpenCV 读取后的 numpy.ndarray 图像。 Returns: tuple: result_img: 清理后的图片失败或无需清理时返回原输入。 clean_type: clean 表示执行了清理no_clean 表示未清理。 try:# 判断输入是文件路径还是 numpy 数组。ifisinstance(target_path,str):target_imgcv2.imdecode(np.fromfile(target_path,dtypenp.uint8),cv2.IMREAD_COLOR,)elifisinstance(target_path,np.ndarray):target_imgtarget_pathelse:returntarget_path,no_cleaniftarget_imgisNone:returntarget_path,no_clean# 获取原始图片尺寸。org_h,org_w,channeltarget_img.shape# 放大图片增强细节降低小字和细线在阈值处理时丢失的概率。target_imgcv2.resize(target_img,(org_w*2,org_h*2))# OpenCV 默认通道顺序是 BGR。blue_c,green_c,red_ccv2.split(target_img)# 如果三个通道完全一致说明图片本身就是灰度或黑白图没有红色印章可清理。ifnp.array_equal(blue_c,green_c)andnp.array_equal(blue_c,red_c):returntarget_path,no_clean# 对红色通道使用 OTSU 自动阈值。thresh,_cv2.threshold(red_c,0,255,cv2.THRESH_OTSU)# 根据 OTSU 阈值动态调整过滤条件。ifint(thresh)170:filter_condition220elif190int(thresh)170:filter_condition210elif200int(thresh)190:filter_condition200elif210int(thresh)200:filter_conditionint(thresh*1.0)else:filter_conditionint(thresh*1.1)# 基于红色通道进行二值化。_,red_threshcv2.threshold(red_c,filter_condition,255,cv2.THRESH_BINARY,)# 将单通道二值图转换回三通道方便后续保存或继续处理。result_imgnp.expand_dims(red_thresh,axis2)result_imgnp.concatenate((result_img,result_img,result_img),axis-1)# 缩放回原始尺寸。resized_imgcv2.resize(result_img,(org_w,org_h))returnresized_img,cleanexceptExceptionase:print(fclear stamp failed:{e})returntarget_path,no_cleanif__name____main__:input_pathinput.pngoutput_pathoutput.pngresult_img,clean_typeclear_stamp(input_path)print(fclean_type:{clean_type})ifclean_typeclean:cv2.imencode(.png,result_img)[1].tofile(output_path)代码原理拆解1. 同时支持图片路径和 numpy 数组函数入口既可以传图片路径也可以传 OpenCV 已经读取好的图片对象ifisinstance(target_path,str):target_imgcv2.imdecode(np.fromfile(target_path,dtypenp.uint8),cv2.IMREAD_COLOR,)elifisinstance(target_path,np.ndarray):target_imgtarget_pathelse:returntarget_path,no_clean这里没有使用cv2.imread()而是使用cv2.imdecode(np.fromfile(path,dtypenp.uint8),cv2.IMREAD_COLOR)这种写法对包含中文路径的文件更友好。2. 放大图片再处理org_h,org_w,channeltarget_img.shape target_imgcv2.resize(target_img,(org_w*2,org_h*2))放大图片的目的是保留更多细节。印章通常由很多细线构成如果直接在低分辨率图片上做阈值处理容易把文字、表格线和印章边缘混在一起。放大后再处理可以让阈值分割更稳定一些。处理完成后代码会再把图片缩回原始尺寸resized_imgcv2.resize(result_img,(org_w,org_h))3. 判断是否为黑白图blue_c,green_c,red_ccv2.split(target_img)ifnp.array_equal(blue_c,green_c)andnp.array_equal(blue_c,red_c):returntarget_path,no_clean如果 B、G、R 三个通道完全一致说明这张图本身就是灰度图或黑白图。既然没有颜色信息就没有必要再做红章清除直接返回no_clean。4. 只处理红色通道红色印章最明显的特征是红色通道数值高因此代码只取红色通道blue_c,green_c,red_ccv2.split(target_img)后续所有阈值计算都基于red_c。这种方式简单直接速度也很快。但它也有一个缺点如果图片里有红色文字、红色 logo 或红色批注也可能被一起处理掉。5. 使用 OTSU 自动阈值thresh,_cv2.threshold(red_c,0,255,cv2.THRESH_OTSU)OTSU 会根据图像灰度分布自动计算一个阈值。相比手写固定阈值它对不同亮度、不同扫描质量的图片更有适应性。不过 OTSU 得到的阈值并不一定可以直接使用所以代码又做了一层动态修正。6. 动态调整过滤阈值ifint(thresh)170:filter_condition220elif190int(thresh)170:filter_condition210elif200int(thresh)190:filter_condition200elif210int(thresh)200:filter_conditionint(thresh*1.0)else:filter_conditionint(thresh*1.1)这段逻辑的作用是根据 OTSU 阈值落在哪个区间选择更适合的二值化阈值。可以理解为如果 OTSU 阈值偏低说明图片整体较暗或红色干扰不突出此时提高过滤阈值避免误伤黑色文字。如果 OTSU 阈值处于中间区间则使用较稳定的经验值。如果 OTSU 阈值已经很高则在它的基础上略微放大。这不是严格的数学公式而是一组经验规则。实际使用时可以根据自己的图片样本继续调整这些区间和阈值。7. 二值化并还原为三通道_,red_threshcv2.threshold(red_c,filter_condition,255,cv2.THRESH_BINARY,)这一步会把红色通道转换成黑白二值图。然后将单通道结果复制成三通道result_imgnp.expand_dims(red_thresh,axis2)result_imgnp.concatenate((result_img,result_img,result_img),axis-1)这样输出图片仍然是常见的三通道格式后续保存、显示或继续用 OpenCV 处理都更方便。方法优点实现简单只依赖 OpenCV 和 NumPy。速度快适合做批量图片前处理。对红色印章覆盖黑色文字的场景比较直接有效。不需要训练模型也不需要额外标注数据。代码容易调试阈值策略可以根据实际图片微调。局限性输出是黑白二值图不保留原始彩色版式。如果红章颜色偏暗、偏棕、偏紫清理效果可能下降。如果图片里有红色文字、红色 logo、红色标注也可能被一起清除。如果印章压住了黑色文字算法只能减少红色干扰不能真正恢复被遮挡的笔画。对复杂背景、彩色底纹或低质量扫描件可能产生噪声和断线。适合的使用场景这种方法适合用作前处理例如扫描件清理。表单图片预处理。证书、回执、审批单等带红章图片的二值化。文字识别前降低红章干扰。如果目标是得到一张肉眼看起来非常自然的无章图片更推荐使用 mask 图像修复算法例如cv2.inpaint()或者使用专门的图像修复模型。可优化方向如果要进一步提升效果可以考虑下面几种优化改用 HSV 色彩空间通过 H 通道定位红色区域。增加红色像素占比判断避免没有红章的彩色图也被二值化。对检测到的红色区域做形态学开闭运算减少噪声。使用红色 mask 配合cv2.inpaint()尽量保留原始版式。针对不同扫描仪、不同印章颜色维护多套阈值策略。总结这个clear_stamp方法本质上是一个基于红色通道的阈值分割方案。它不复杂但在“红色印章干扰黑色文字”的场景下很实用。如果你的目标是后续文字识别或结构化信息读取这种黑白二值化结果通常已经够用。如果你的目标是高质量图片修复则需要在此基础上继续引入 mask 修复或图像生成类方法。