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)

核心思路:

  1. 干扰线去除:用形态学操作检测并移除横竖细线
  2. 倾斜矫正:通过霍夫变换检测文本基线角度进行旋转
  3. 参数调整:根据实际验证码特点调整阈值和核大小

关键参数说明:

  • kernel_line的尺寸决定检测的线粗细
  • cv2.THRESH_OTSU自动计算二值化阈值
  • 霍夫变换的阈值影响直线检测灵敏度

一句话建议: 根据你的验证码特点调整形态学核的大小和霍夫变换参数。

连续斜率?

这种只有切图了

深度训练

是阿,跟字母差不多粗,怎么去噪都去不掉

这样训练模型是不是要挺长时间的

看你用 gpu 还是 cpu 训练,几十万样本,gpu 四五天可以跑完,cpu 就很慢了

前几天一个类似的验证码,搞了二十万数据,去腾讯云开了个 gpu 机器训练,两个小时跑完,最终测试的验证码通过率有九十多

回到顶部