Python中如何去除验证码的干扰线并进行图像矫正?
最近在用 Python 做爬虫,碰到了这种验证码(降噪 /二值化处理后的)
现在想要将干扰线去掉,最好能矫正一下字符,不吝赐教。
Python中如何去除验证码的干扰线并进行图像矫正?
9 回复
这干扰线…
都跟字母的笔画一边粗了吧…
这可咋整…
囧…
import cv2
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
def remove_interference_lines(image_path):
"""
去除验证码干扰线的主要步骤
"""
# 1. 读取图像并转为灰度
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 2. 二值化处理
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 3. 形态学操作去除细线
kernel_line = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 15))
vertical_lines = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel_line)
kernel_line2 = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 1))
horizontal_lines = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel_line2)
# 4. 合并并去除干扰线
lines_mask = cv2.bitwise_or(vertical_lines, horizontal_lines)
cleaned = cv2.subtract(binary, lines_mask)
return cleaned, binary
def correct_image_skew(image):
"""
图像倾斜矫正
"""
# 边缘检测
edges = cv2.Canny(image, 50, 150, apertureSize=3)
# 霍夫变换检测直线
lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
if lines is not None:
angles = []
for line in lines:
rho, theta = line[0]
angle = theta * 180 / np.pi - 90
if abs(angle) < 45: # 只考虑接近水平的线
angles.append(angle)
if angles:
median_angle = np.median(angles)
# 旋转矫正
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, median_angle, 1.0)
corrected = cv2.warpAffine(image, M, (w, h),
flags=cv2.INTER_CUBIC,
borderMode=cv2.BORDER_REPLICATE)
return corrected
return image
def process_captcha(image_path):
"""
完整的验证码处理流程
"""
# 去除干扰线
cleaned, original_binary = remove_interference_lines(image_path)
# 倾斜矫正
corrected = correct_image_skew(cleaned)
# 可选:进一步降噪
kernel = np.ones((2,2), np.uint8)
final = cv2.morphologyEx(corrected, cv2.MORPH_CLOSE, kernel)
return final
# 使用示例
if __name__ == "__main__":
# 处理验证码图片
result = process_captcha("captcha.png")
# 显示结果
plt.figure(figsize=(12, 4))
plt.subplot(131)
plt.title("Original")
plt.imshow(cv2.imread("captcha.png")[:,:,::-1])
plt.axis('off')
plt.subplot(132)
plt.title("After Line Removal")
cleaned, _ = remove_interference_lines("captcha.png")
plt.imshow(cleaned, cmap='gray')
plt.axis('off')
plt.subplot(133)
plt.title("Final Result")
plt.imshow(result, cmap='gray')
plt.axis('off')
plt.tight_layout()
plt.show()
# 保存结果
cv2.imwrite("processed_captcha.png", result)
核心思路:
- 干扰线去除:用形态学操作检测并移除横竖细线
- 倾斜矫正:通过霍夫变换检测文本基线角度进行旋转
- 参数调整:根据实际验证码特点调整阈值和核大小
关键参数说明:
kernel_line的尺寸决定检测的线粗细cv2.THRESH_OTSU自动计算二值化阈值- 霍夫变换的阈值影响直线检测灵敏度
一句话建议: 根据你的验证码特点调整形态学核的大小和霍夫变换参数。
连续斜率?
这种只有切图了
深度训练
是阿,跟字母差不多粗,怎么去噪都去不掉
这样训练模型是不是要挺长时间的
看你用 gpu 还是 cpu 训练,几十万样本,gpu 四五天可以跑完,cpu 就很慢了
前几天一个类似的验证码,搞了二十万数据,去腾讯云开了个 gpu 机器训练,两个小时跑完,最终测试的验证码通过率有九十多

