Python中如何去除验证码的干扰线并进行图像矫正?
最近在用 Python 做爬虫,碰到了这种验证码(降噪 /二值化处理后的)
现在想要将干扰线去掉,最好能矫正一下字符,不吝赐教。
Python中如何去除验证码的干扰线并进行图像矫正?
9 回复
话说我的图片呢
import cv2
import numpy as np
from skimage import morphology
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_erode = np.ones((2, 2), np.uint8)
eroded = cv2.erode(binary, kernel_erode, iterations=1)
# 再膨胀恢复字符
kernel_dilate = np.ones((3, 3), np.uint8)
cleaned = cv2.dilate(eroded, kernel_dilate, iterations=1)
# 4. 可选:使用连通组件分析去除小面积噪声
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(cleaned, connectivity=8)
# 创建掩码,只保留面积较大的组件(假设字符面积较大)
min_area = 50 # 根据实际情况调整
mask = np.zeros_like(cleaned)
for i in range(1, num_labels):
if stats[i, cv2.CC_STAT_AREA] > min_area:
mask[labels == i] = 255
return mask
def correct_image_skew(image):
"""
图像倾斜矫正
"""
# 1. 边缘检测
edges = cv2.Canny(image, 50, 150, apertureSize=3)
# 2. 霍夫变换检测直线
lines = cv2.HoughLines(edges, 1, np.pi/180, 200)
if lines is not None:
# 3. 计算平均角度
angles = []
for line in lines:
rho, theta = line[0]
angle = theta * 180 / np.pi - 90
if abs(angle) < 45: # 只考虑接近水平的线
angles.append(angle)
if angles:
# 4. 计算平均倾斜角度
median_angle = np.median(angles)
# 5. 旋转矫正
(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, output_path=None):
"""
完整的验证码处理流程
"""
# 步骤1: 去除干扰线
cleaned = remove_interference_lines(image_path)
# 步骤2: 倾斜矫正
corrected = correct_image_skew(cleaned)
# 步骤3: 最终二值化处理
_, final = cv2.threshold(corrected, 127, 255, cv2.THRESH_BINARY)
if output_path:
cv2.imwrite(output_path, final)
return final
# 使用示例
if __name__ == "__main__":
# 处理验证码图片
result = process_captcha('captcha.jpg', 'processed_captcha.jpg')
# 显示结果对比
original = cv2.imread('captcha.jpg')
cv2.imshow('Original', original)
cv2.imshow('Processed', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
核心思路:
- 去干扰线:利用干扰线通常比字符细的特点,通过形态学操作(腐蚀+膨胀)过滤细线
- 倾斜矫正:用霍夫变换检测文本基线,计算倾斜角度后旋转矫正
参数调整建议:
- 形态学操作的核大小需要根据验证码具体样式调整
- 连通组件的最小面积阈值根据字符大小设置
- 霍夫变换的参数需要根据图像分辨率调整
一句话总结:用形态学去噪+霍夫变换矫正,具体参数得看你的验证码长啥样。
怎么发本地图片😓
1, 大佬们发图似乎都用 https://sm.ms
2, 看不到图,但是我瞎说一下:open cv ,先灰度化, 再用 sobel 算一下 xy 方向上的梯度,之后相减,最后 blur 一下,行不行?
厉害了,不过算法那些搞不懂~
可以直接上 CNN+RNN 进行端到端验证码识别,GitHub 上有相关代码
pytesser
试过了 效果很差

