一、引言
随着验证码的防护强度逐步升级,越来越多的验证码图片中加入了弯曲字符、干扰线、背景噪声等元素,传统 OCR 已难以胜任直接识别任务。为了提升识别准确率,本文采用 Python 构建一个针对“多干扰线图像验证码”的鲁棒识别系统,融合图像处理、噪声剔除和字符分割技术。
二、系统流程概览
系统分为五个核心步骤:
图像灰度化与二值化
干扰线去除(基于形态学和边缘检测)
更多内容访问ttocr.com或联系1436423940
图像降噪
字符分割
OCR识别(Tesseract or CNN)
三、依赖库与环境
pip install opencv-python pillow pytesseract numpy
Tesseract OCR 引擎需要单独安装,并配置环境变量。
四、图像处理与干扰线去除(denoise.py)
import cv2
import numpy as np
def preprocess_and_denoise(path):
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应二值化
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV, 25, 10)# 去除干扰线:通过形态学操作(开操作 + 细化)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)# 轮廓去除细线
contours, _ = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
mask = np.ones_like(opening) * 255
for cnt in contours:area = cv2.contourArea(cnt)if area < 30:cv2.drawContours(mask, [cnt], -1, 0, -1)result = cv2.bitwise_and(opening, mask)out_path = 'temp_cleaned.png'
cv2.imwrite(out_path, result)
return out_path
五、字符切割模块(segment.py)
from PIL import Image
import os
def segment_characters(image_path, output_dir='segmented'):
os.makedirs(output_dir, exist_ok=True)
img = Image.open(image_path).convert('L')
img = img.point(lambda x: 0 if x < 128 else 255, '1')
w, h = img.size
pixels = img.load()# 统计每一列黑色像素数,确定字符边界
vertical_projection = [sum(pixels[x, y] == 0 for y in range(h)) for x in range(w)]segments = []
start = None
for i, v in enumerate(vertical_projection):if v > 0 and start is None:start = ielif v == 0 and start is not None:if i - start > 2:segments.append((start, i))start = None# 保存切割字符图像
char_images = []
for idx, (l, r) in enumerate(segments):cropped = img.crop((l, 0, r, h))char_path = os.path.join(output_dir, f'char_{idx}.png')cropped.save(char_path)char_images.append(char_path)return char_images
六、OCR识别模块(ocr.py)
import pytesseract
from PIL import Image
def recognize_characters(image_list):
config = r'-c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 --psm 10'
result = ''
for path in image_list:
image = Image.open(path)
text = pytesseract.image_to_string(image, config=config).strip()
result += text
return result
七、主程序入口(main.py)
from denoise import preprocess_and_denoise
from segment import segment_characters
from ocr import recognize_characters
def recognize(path):
cleaned = preprocess_and_denoise(path)
segments = segment_characters(cleaned)
result = recognize_characters(segments)
print(f"识别结果:{result}")
if name == "main":
import sys
test_path = sys.argv[1] if len(sys.argv) > 1 else "test_samples/sample.png"
recognize(test_path)