| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- 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}")
|