init repo

This commit is contained in:
2026-04-25 21:50:03 +08:00
commit ada92373c2
124 changed files with 5292 additions and 0 deletions

128
ocr_captcha.py Normal file
View File

@@ -0,0 +1,128 @@
#!/usr/bin/env python3
"""
验证码识别脚本
输入:验证码图片路径
输出:识别结果(打印到 stdout
预处理流程:
1. 灰度化
2. 去除水平干扰线(形态学开运算)
3. 二值化
4. 去噪
5. ddddocr 识别
"""
import sys
import cv2
import numpy as np
import ddddocr
def preprocess(img_path):
"""多种预处理方案"""
img = cv2.imread(img_path)
if img is None:
return []
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
results = []
# 方案1去水平线 + 二值化
# 用水平核做形态学开运算,提取水平线
h_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 1))
h_lines = cv2.morphologyEx(gray, cv2.MORPH_OPEN, h_kernel)
# 从原图减去水平线
no_lines = cv2.subtract(gray, h_lines)
# 二值化
_, binary1 = cv2.threshold(no_lines, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
results.append(binary1)
# 方案2自适应阈值
adaptive = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2)
results.append(adaptive)
# 方案3去水平线 + 自适应阈值
adaptive2 = cv2.adaptiveThreshold(no_lines, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2)
results.append(adaptive2)
# 方案4反色 + 去线 + 二值化
inverted = cv2.bitwise_not(gray)
h_lines_inv = cv2.morphologyEx(inverted, cv2.MORPH_OPEN, h_kernel)
no_lines_inv = cv2.subtract(inverted, h_lines_inv)
_, binary4 = cv2.threshold(no_lines_inv, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
results.append(binary4)
# 方案5中值滤波去噪 + OTSU
median = cv2.medianBlur(gray, 3)
_, binary5 = cv2.threshold(median, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
results.append(binary5)
# 方案6放大 + 去线 + 锐化
big = cv2.resize(gray, None, fx=3, fy=3, interpolation=cv2.INTER_CUBIC)
h_kernel_big = cv2.getStructuringElement(cv2.MORPH_RECT, (75, 1))
h_lines_big = cv2.morphologyEx(big, cv2.MORPH_OPEN, h_kernel_big)
no_lines_big = cv2.subtract(big, h_lines_big)
_, binary6 = cv2.threshold(no_lines_big, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 去小噪点
kernel_small = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2))
binary6 = cv2.morphologyEx(binary6, cv2.MORPH_OPEN, kernel_small)
results.append(binary6)
# 方案7原图直接用
results.append(gray)
# 方案8: 原始彩色图ddddocr 有时对彩色图效果更好)
results.append(img)
return results
def main():
if len(sys.argv) < 2:
print("用法: python3 ocr_captcha.py <图片路径>", file=sys.stderr)
sys.exit(1)
img_path = sys.argv[1]
ocr = ddddocr.DdddOcr(show_ad=False)
# 先直接用原图试
with open(img_path, 'rb') as f:
raw_result = ocr.classification(f.read())
if raw_result and len(raw_result) == 4 and raw_result.isalnum():
print(raw_result)
return
# 多种预处理方案
preprocessed = preprocess(img_path)
best = raw_result
for i, processed in enumerate(preprocessed):
try:
if len(processed.shape) == 3:
_, buf = cv2.imencode('.png', processed)
else:
_, buf = cv2.imencode('.png', processed)
result = ocr.classification(buf.tobytes())
if result and len(result) == 4 and result.isalnum():
print(result)
return
# 记录最佳结果
if result and len(result) >= 3 and (not best or len(result) == 4):
best = result
except Exception:
continue
# 返回最佳结果
if best:
print(best[:4] if len(best) > 4 else best)
else:
print("FAIL", file=sys.stderr)
sys.exit(1)
if __name__ == '__main__':
main()