#!/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()
