Python处理滑块缺口验证码以及字母数字验证码识别

该功能主要运用到的模块有:re、cv2、ddddocr、 matplotlib等

字母数字识别

该识别可以直接下载第三方工具包ddddocr进行处理

使用Python的包管理工具来安装ddddocr及其所需的依赖库

pip install ddddocr

具体实现,分别处理保存在本地的图片已经base64格式的图片

import ddddocr

#识别本地图片
def alphanumericProcessing(img_path):
    ocr = ddddocr.DdddOcr()
    with open(img_path, 'rb') as f:
        img_bytes = f.read()
    res = ocr.classification(img_bytes)
    print(res)
    return res

#识别base64编码格式的图片
def ret_code(img_path):
    ocr = ddddocr.DdddOcr()
    res = ocr.classification(img_path)
    print(res)

滑块缺口识别

滑块缺口的识别主要有三个参数,分别为背景图片,缺口图片,图片显示长度(用于计算缩放比)

验证码识别图片

Python处理滑块缺口验证码以及字母数字验证码识别_第1张图片

f12找到对应图片的图片链接,已经图片的长度Python处理滑块缺口验证码以及字母数字验证码识别_第2张图片

首先我们需要对图片进行读取,因为兼容了URL链接和本地图片格式,读取方式不一样,需要先对图片的类型的判断

def determine_image_type(input_img):
    """
    自动判断输入图片的类型
    :param input_img: 输入图片(图片路径、URL链接)
    :return: 图片类型('path', 'url')或None
    """
    # 判断是否为URL
    if input_img.startswith(('http://', 'https://')): return 'url'
    # 判断是否为本地文件路径
    if os.path.isfile(input_img): return 'path'
    return None

然后进行读取图片方法的封装
 

def read_img(input_img):
    """
    从URL读取图片并解码为OpenCV格式
    :param input_img: 传入的图片
    :return: OpenCV格式的图片
    """
    img_type = determine_image_type(input_img)
    if img_type is None: ValueError("不支持的图像类型。请使用 'path', 'url'."); return None
    try:
        if img_type == 'path':  # 从本地路径读取图片
            img = cv2.imread(input_img)
        elif img_type == 'url':# 从URL获取图片数据
            with urllib.request.urlopen(input_img) as response:
                img_data = np.asarray(bytearray(response.read()), dtype="uint8")
                img = cv2.imdecode(img_data, cv2.IMREAD_COLOR)
        else:
            raise ValueError("不支持的图像类型。请使用 'path', 'url'.")
        return img if img is not None else None
    except Exception as e:
        print(f"图片读取异常: {e}")
        return None

然后需要对图片进行检测转换

background_img = read_img(background_img)  # 读取背景图
scaling_ratio = img_show_size / background_img.shape[1]  # 获取背景图尺寸和缩放比
# 对图片进行边缘检测    
background_edges = process_image(background_img, cv2.Canny, 100, 200)
# 将灰度边缘图转换为彩色
background_edges_rgb = cv2.cvtColor(background_edges, cv2.COLOR_GRAY2RGB)

最后对两个图片进行匹配,利用cv2.matchTemplate()进行处理

res = cv2.matchTemplate("处理后的背景图片", "处理后的缺口图片", cv2.TM_CCOEFF_NORMED)

具体代码实现:

import cv2, urllib, os, base64, re, numpy as np
from matplotlib import pyplot as plt
from typing import Union


class SliderSolver:
    def __init__(self, edge_detection_method=cv2.Canny, edge_args=(100, 200)):
        """
        初始化滑块验证码处理器
        :param edge_detection_method: 边缘检测方法(默认Canny)
        :param edge_args: 边缘检测参数(默认(100, 200))
        """
        self.edge_detection_method = edge_detection_method
        self.edge_args = edge_args

    @staticmethod
    def plt_show(img, cmap='gray'):
        """
        静态方法:显示图片(支持灰度图和彩色图)
        :param img: 输入图片数组
        :param cmap: 显示图片的颜色映射
        """
        plt.imshow(img, cmap=cmap)
        plt.axis('off')
        plt.show()

    def _determine_image_type(self, input_img: str) -> Union[str, None]:
        """
        判断图片类型(支持Base64)
        :param input_img: 输入内容(路径/URL/Base64)
        :return: 'url'/'path'/'base64'/None
        """
        if re.match(r'^data:image/[a-z]+;base64,', input_img): return 'base64'
        if input_img.startswith(('http://', 'https://')): return 'url'
        if os.path.isfile(input_img): return 'path'
        return None

    def _read_img(self, input_img: str):
        """
        统一读取入口(新增Base64处理)
        :param input_img: 输入内容(路径/URL/Base64)
        :return: OpenCV图像对象
        """
        img_type = self._determine_image_type(input_img)

        try:
            if img_type == 'base64':
                # 提取Base64数据部分
                header, data = input_img.split(',', 1)
                img_bytes = base64.b64decode(data)
                img_array = np.frombuffer(img_bytes, dtype=np.uint8)
                img = cv2.imdecode(img_array, cv2.IMREAD_COLOR)
            elif img_type == 'path':
                img = cv2.imread(input_img)
            elif img_type == 'url':
                with urllib.request.urlopen(input_img) as response:
                    img_data = np.asarray(bytearray(response.read()), dtype="uint8")
                    img = cv2.imdecode(img_data, cv2.IMREAD_COLOR)
            else: raise ValueError("无法识别的图片格式,支持类型:URL/本地路径/Base64")
            if img is None: raise ValueError("图片解码失败,请检查输入数据有效性")
            return img
        except Exception as e:
            raise RuntimeError(f"图片处理失败:{str(e)}")

    def _process_image(self, img):
        """
        执行图像处理(边缘检测)
        """
        return self.edge_detection_method(img, *self.edge_args)

    def calculate_distance(self, background_img: str, gap_img: str, img_show_size: int) -> int:
        """
        计算移动距离(兼容Base64)
        :param background_img: 背景图(URL/路径/Base64)
        :param gap_img: 缺口图(URL/路径/Base64)
        :param img_show_size: 显示宽度(像素)
        :return: 移动距离(像素)
        """
        bg_img = self._read_img(background_img)
        gap_img = self._read_img(gap_img)

        # 计算缩放比例
        scaling_ratio = img_show_size / bg_img.shape[1]

        # 执行边缘检测
        bg_edges = self._process_image(bg_img)
        gap_edges = self._process_image(gap_img)

        # 转换颜色空间用于模板匹配
        bg_edges_rgb = cv2.cvtColor(bg_edges, cv2.COLOR_GRAY2RGB)
        gap_edges_rgb = cv2.cvtColor(gap_edges, cv2.COLOR_GRAY2RGB)

        # 模板匹配
        res = cv2.matchTemplate(bg_edges_rgb, gap_edges_rgb, cv2.TM_CCOEFF_NORMED)
        _, _, _, max_loc = cv2.minMaxLoc(res)

        return int(max_loc[0] * scaling_ratio)


if __name__ == '__main__':
    # 使用示例 - Base64格式
    bg_base64 = ''
    gap_base64 = ''
    solver = SliderSolver()
    distance = solver.calculate_distance(bg_base64, gap_base64, 342)
    print(f"需要移动的距离:{distance} 像素")

你可能感兴趣的:(Python处理滑块缺口验证码以及字母数字验证码识别)