import cv2 import numpy as np from PIL import Image import os import sys def detect_captcha_left_edge(image_path_or_array, output_path=None): """ 识别滑块验证码中橙色缺口覆盖层的最左边X坐标,并生成绿线标记图。 支持传入图片路径(str)或numpy.ndarray(BGR/RGB)。 """ if isinstance(image_path_or_array, str): img = Image.open(image_path_or_array) img_np = np.array(img) else: img_np = image_path_or_array.copy() # OpenCV 截图通常是 BGR,转成 RGB if img_np.shape[2] == 3: img_np = cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB) h, w = img_np.shape[:2] # 转换为HSV颜色空间 hsv = cv2.cvtColor(img_np, cv2.COLOR_RGB2HSV) # 检测 peach/orange 覆盖层 # 色调: 10-35 (橙色/桃色), 饱和度: 40-255, 亮度: 140-255 lower = np.array([10, 40, 140]) upper = np.array([35, 255, 255]) mask = cv2.inRange(hsv, lower, upper) # 形态学操作去噪 kernel = np.ones((5, 5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # 查找轮廓 contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if not contours: raise ValueError("未检测到橙色区域") # 筛选候选区域: # 1. 轮廓中心位于验证码图片区域内(y + bh/2 在 0.4h ~ 0.65h 之间) # 2. 面积足够大 # 3. y 范围足够长(bh > 0.2h),排除滑块按钮等短区域 candidates = [] for cnt in contours: x, y, bw, bh = cv2.boundingRect(cnt) area = bw * bh if area < 5000: continue center_y = y + bh / 2 if center_y < h * 0.4 or center_y > h * 0.65: continue if bh < h * 0.2: continue candidates.append((cnt, x, y, bw, bh, area, bh)) if not candidates: raise ValueError("未检测到拼图覆盖层") # 选择 y 范围最长的候选 best = max(candidates, key=lambda c: c[6]) _, x, y, bw, bh, area, bh_max = best # 左边缘 x 坐标 left_x = x # 在原图上画绿线 canvas = img_np.copy() cv2.line(canvas, (left_x, 0), (left_x, h), (0, 255, 0), 2) # 保存绿线标记图 if output_path is None: base, ext = os.path.splitext(image_path_or_array if isinstance(image_path_or_array, str) else "") output_path = f"{base}_green.png" cv2.imwrite(output_path, cv2.cvtColor(canvas, cv2.COLOR_RGB2BGR)) return left_x, output_path if __name__ == "__main__": if len(sys.argv) < 2: print("用法: python detect_captcha_edge.py <图片路径> [输出路径]") sys.exit(1) image_path = sys.argv[1] output_path = sys.argv[2] if len(sys.argv) > 2 else None left_x, out = detect_captcha_left_edge(image_path, output_path) print(f"拼图最左边X坐标: {left_x}") print(f"绿线标记图: {out}")