Skip to content

Instantly share code, notes, and snippets.

@lewangdev
Created November 23, 2025 03:51
Show Gist options
  • Select an option

  • Save lewangdev/8a1b9c9f954308dd72093394eb0a72f1 to your computer and use it in GitHub Desktop.

Select an option

Save lewangdev/8a1b9c9f954308dd72093394eb0a72f1 to your computer and use it in GitHub Desktop.
Extract Red Seal From Scan
import cv2
import numpy as np
def remove_white_paper(input_path, output_path, sensitivity=220):
"""
去除A4白纸背景,保留印章。
:param input_path: 输入图片路径
:param output_path: 输出图片路径
:param sensitivity: 灵敏度(0-255)。数值越大,去背景力度越大(会将更多浅灰色视为背景去除)。
建议范围 200-240。
"""
# 1. 读取图片
img = cv2.imread(input_path)
if img is None:
print(f"错误:找不到文件 {input_path}")
return
# 2. 转换为 BGRA (增加透明通道)
# 先分离 B, G, R 通道
b, g, r = cv2.split(img)
# 3. 计算 Alpha 通道 (透明度)
# 逻辑:将图片转为灰度,越亮的地方越透明,越暗的地方越不透明
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# --- 关键步骤:处理扫描噪点 ---
# 扫描件的纸通常不是纯白(255),可能是浅灰(230左右)。
# 我们把所有亮于 sensitivity (默认220) 的像素强制变为纯白(255),
# 这样它们在后续步骤中就会变成完全透明。
_, mask = cv2.threshold(gray, sensitivity, 255, cv2.THRESH_BINARY)
# 这里的 mask 是:背景为白(255),印章为黑(0)。
# 我们需要反转它,让印章为不透明(255),背景为透明(0)。
alpha = cv2.bitwise_not(mask)
# 4. 边缘优化 (可选,让印章边缘更圆润,不带锯齿)
# 使用高斯模糊让透明度遮罩的边缘变软
alpha = cv2.GaussianBlur(alpha, (3, 3), 0)
# 5. 合并通道
# 组合 B, G, R 和 计算出的 Alpha
rgba = cv2.merge([b, g, r, alpha])
# 6. 保存结果
cv2.imwrite(output_path, rgba)
print(f"处理完成!已保存为: {output_path}")
# --- 运行部分 ---
if __name__ == "__main__":
# 改成你的文件名
input_file = "scan_a4.jpg"
output_file = "seal_transparent.png"
# 如果发现背景没去干净,把 220 改大 (例如 240)
# 如果发现印章浅色的地方被误删了,把 220 改小 (例如 180)
remove_white_paper(input_file, output_file, sensitivity=220)
@lewangdev
Copy link
Author

运行前,需要安装好依赖包

pip install opencv-python numpy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment