You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenCV程序化识别含异色字符行的验证码?

基于OpenCV的异色字符验证码识别方案

核心思路

目标是定位存在异色字符的行并返回对应行号,核心逻辑是逐行分析字符串区域的颜色一致性——若某行存在与其他字符颜色差异显著的字符,则标记该行。由于前景清晰,无需AI模型,仅用OpenCV基础图像处理功能即可实现。

关键步骤及对应OpenCV功能

1. 图像预处理与背景过滤

  • 用cv2.cvtColor()将图像从BGR转为HSV色彩空间(HSV对颜色差异的区分度更高,优于RGB)。
  • 若背景干扰极小,可直接跳过复杂滤波;若需强化前景,用cv2.threshold()对灰度图进行二值化,或用cv2.inRange()基于颜色范围提取前景字符的掩码,过滤背景像素。

2. 行区域分割

  • 利用垂直投影分割字符行:将图像转为灰度图后,用cv2.reduce()计算每行的像素总和(垂直投影),根据投影值的峰值定位每行的上下边界,得到所有行的区域范围。
  • 定位#列:对第一行的灰度图计算水平投影,找到#字符所在的列(投影值峰值对应的列),以此为界分割每行的行号区域和字符串区域。

3. 逐行颜色差异检测

  • 对每行的字符串区域,提取H通道(HSV的色调通道)数据,用cv2.calcHist()统计色调分布,找到该行字符的主色调。
  • 统计区域内与主色调差异超过阈值的像素数量,若占比超过设定比例(如5%),则判定该行存在异色字符。
  • 更精准的方式:用cv2.findContours()提取每个字符的轮廓,对每个字符的包围盒计算色调均值,对比该行内所有字符的均值,找到差异显著的字符。

4. 行号识别

  • 对标记的目标行,提取#列左侧的行号区域,用cv2.threshold()二值化后,通过模板匹配(cv2.matchTemplate())识别数字(提前制作0-9的数字模板),或用简单的像素特征统计(如数字的像素占比)快速识别。

简化实现示例代码

import cv2
import numpy as np

def get_target_line(img_path):
    # 读取图像
    img = cv2.imread(img_path)
    hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    # 垂直投影分割行
    row_projection = cv2.reduce(gray_img, 1, cv2.REDUCE_SUM, dtype=cv2.CV_32S)
    row_threshold = np.max(row_projection) * 0.5
    row_ranges = []
    start_row = None
    for idx, val in enumerate(row_projection):
        if val > row_threshold and start_row is None:
            start_row = idx
        elif val <= row_threshold and start_row is not None:
            row_ranges.append((start_row, idx))
            start_row = None
    if start_row is not None:
        row_ranges.append((start_row, len(row_projection)-1))

    # 定位#列(取第一行的水平投影峰值)
    first_row_gray = gray_img[row_ranges[0][0]:row_ranges[0][1], :]
    col_projection = cv2.reduce(first_row_gray, 0, cv2.REDUCE_SUM, dtype=cv2.CV_32S)
    hash_col = np.argmax(col_projection)

    target_line_num = -1
    # 逐行分析颜色差异
    for line_idx, (top, bottom) in enumerate(row_ranges):
        # 提取字符串区域的H通道
        str_h_channel = hsv_img[top:bottom, hash_col+1:, 0]
        # 统计主色调
        hue_hist = cv2.calcHist([str_h_channel], [0], None, [180], [0, 180])
        main_hue = np.argmax(hue_hist)
        # 计算异色像素占比
        diff_pixel_count = np.sum(np.abs(str_h_channel - main_hue) > 20)
        total_pixels = str_h_channel.size
        if diff_pixel_count / total_pixels > 0.05:
            # 识别行号(示例简化处理,实际可替换为模板匹配)
            num_region = gray_img[top:bottom, :hash_col]
            _, num_bin = cv2.threshold(num_region, 127, 255, cv2.THRESH_BINARY_INV)
            # 此处仅为示例,实际需根据数字样式调整识别逻辑
            target_line_num = line_idx + 1
            break
    return target_line_num

内容的提问来源于stack exchange,提问作者Newbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 04:20:19