首页 > 其他分享 >滑块验证码缺口识别及轨迹生成

滑块验证码缺口识别及轨迹生成

时间:2023-06-25 15:25:30浏览次数:39  
标签:轨迹 滑块 fillter 验证码 slider tracks edge np array

import base64
import random
import time
from io import BytesIO

import cv2
import requests


try:
    import matplotlib.pyplot as plt
except:
    plt = None
import numpy as np
from PIL import Image
from selenium.webdriver import ActionChains
from scipy import signal


def ease_out_quad(x):
    return 1 - (1 - x) * (1 - x)


def ease_out_quart(x):
    return 1 - pow(1 - x, 4)


def ease_out_expo(x):
    if x == 1:
        return 1
    else:
        return 1 - pow(2, -10 * x)


def ease_out_bounce(x):
    n1 = 7.5625
    d1 = 2.75
    if x < 1 / d1:
        return n1 * x * x
    elif x < 2 / d1:
        x -= 1.5 / d1
        return n1 * x * x + 0.75
    elif x < 2.5 / d1:
        x -= 2.25 / d1
        return n1 * x * x + 0.9375
    else:
        x -= 2.625 / d1
        return n1 * x * x + 0.984375


def get_tracks_by_ease_func(distance, ease_func=ease_out_quart, seconds=None, steps=50):
    if not seconds:
        seconds = random.random() + random.randint(2, 5)

    tracks = [0]
    offsets = [0]
    for t in np.arange(0.0, seconds, seconds / steps):
        offset = round(ease_func(t / seconds) * distance)
        tracks.append(offset - offsets[-1])
        offsets.append(offset)

    return tracks


#######################


def get_tracks_by_random(distance):
    # 移动轨迹
    tracks = []
    current = 0
    while current < distance:
        move = random.randint(-3, 5)
        current += move
        if current > 0:
            tracks.append(move)
    return tracks


#########################


def get_random(min, max):
    return random.choice(list(range(min, max)))


def get_tracks_by_a(distance):
    """
    根据加速度获取移动轨迹
    :param distance:
    :return: 移动轨迹
    """

    # 移动轨迹
    tracks = []
    # 当前位移
    current = 0
    # 减速阈值
    # mid = distance * 4 / 5
    # mid = distance * 3 / 5
    mid = distance * 7 / 10
    # 计算间隔
    # t = 0.2
    t = 0.1
    # 初速度
    v = 4

    while current < distance:
        if current < mid:
            # 加速度为正2
            a = 4 + get_random(-2, 2)
        else:
            # 加速度为负3
            a = -6 + get_random(-2, 2)
        # 初速度v0
        v0 = v
        # 当前速度 v = v0 + at
        v = v0 + a * t
        # 移动距离x = v0t + 1/2 * a * t^2
        move = v0 * t + 1 / 2 * a * t * t
        # 当前位移
        current += move
        # 加入轨迹
        tracks.append(round(move))
    return tracks


def get_tracks_by_a2(distance):
    """

    :param S: 缺口距离Px

    :return:

    """

    distance += 20
    v = 0
    t = 0.2
    tracks = []
    current = 0
    mid = distance * 3 / 5  # 减速阀值

    while current < distance:
        if current < mid:
            a = 2 + random.random()
        else:
            a = -3 + random.random()

        s = v * t + 0.5 * a * (t ** 2)
        v = v + a * t
        current += s
        tracks.append(round(s))

    back_tracks = [-3, -3, -2, -2, -2, -2, -2, -1, -1, -1]
    tracks.extend(back_tracks)

    return tracks


def get_tracks(distance):
    tracks_funcs = [
        lambda distance: get_tracks_by_ease_func(
            distance, ease_func=ease_out_quad, steps=get_random(30, 50)
        ),
        lambda distance: get_tracks_by_ease_func(
            distance, ease_func=ease_out_quart, steps=get_random(30, 50)
        ),
        lambda distance: get_tracks_by_ease_func(
            distance, ease_func=ease_out_expo, steps=get_random(30, 50)
        ),
        lambda distance: get_tracks_by_ease_func(
            distance, ease_func=ease_out_bounce, steps=get_random(30, 50)
        ),
        lambda distance: get_tracks_by_random(distance),
        lambda distance: get_tracks_by_a(distance),
        lambda distance: get_tracks_by_a2(distance),
    ]

    tracks_func = random.choice(tracks_funcs)
    return tracks_func(distance)


def drag_and_drop(browser, slider, tracks, seconds=None):
    if not seconds:
        seconds = random.random() + random.randint(2, 5)

    unit_times = seconds / len(tracks)
    ActionChains(browser).click_and_hold(slider).perform()
    for x in tracks:
        ActionChains(browser).move_by_offset(x, 0).perform()
        time.sleep(unit_times)

    ActionChains(browser).pause(0.5).release().perform()


def draw_tracks(tracks, seconds):
    distances = []
    distance = 0
    for track in tracks:
        distance += track
        distances.append(distance)

    times = []
    unit_times = seconds / len(tracks)
    time = 0
    for i in range(len(tracks)):
        time += unit_times
        times.append(time)

    print("tracks: ", tracks)
    print("times:", times)
    plt.plot(times, distances)
    plt.xlabel("time")
    plt.ylabel("distance")

    plt.show()


########### 获取滑块偏移量 ##############
def get_image(pic_path):
    return Image.open(pic_path)


def pic2gray(pic_path, save=False) -> np.ndarray:
    """
    图像转为灰度图像
    @param pic_path: 图片地址
    @return: np.ndarray
    """
    pic_path_rgb = cv2.imread(pic_path)
    pic_path_gray = cv2.cvtColor(pic_path_rgb, cv2.COLOR_BGR2GRAY)
    if save:
        cv2.imwrite(pic_path, pic_path_gray)
    return pic_path_gray


def img2array(image: Image) -> np.ndarray:
    """
    图片转 ndarray
    @param image:
    @return:
    """
    img_array = np.array(image)
    return img_array


def array2img(image_array: np.ndarray) -> Image:
    """
    array 转 Image
    @param image_array:
    @return: Image, 可以调用img.show()查看图片
    """
    img = Image.fromarray(image_array.astype("uint8")).convert("RGBA")
    return img


# def get_gap_edge_position(image: Image, gap_edge_rgb: tuple, show=False, rgb_range=10) -> np.ndarray:
#     '''
#     获取缺口 边界
#     @param image: 背景图
#     @param gap_edge_rgb: 缺口边界rgb
#     @param show: 是否画图 方便调试
#     @param rgb_range: rgb 上下浮动范围
#     @return: numpy.ndarray 二维矩阵,缺口边界为1,其他为0。 横向为列,纵向为行。左上角为原点
#     '''
#
#     pix = image.load()
#     width = image.size[0]
#     height = image.size[1]
#
#     positions = []
#     position_arrays = np.zeros((height, width), dtype=np.int)  # 高度为行 宽度为列
#
#     for x in range(width):
#         for y in range(height):
#             try:
#                 rgb1 = pix[x, y][:3]
#             except:
#                 rgb1 = (pix[x, y], pix[x, y], pix[x, y])  # 灰度图像,只有一个值
#
#             if abs(rgb1[0] - gap_edge_rgb[0]) < rgb_range and abs(rgb1[1] - gap_edge_rgb[1]) < rgb_range and abs(rgb1[2] - gap_edge_rgb[2]) < rgb_range:
#                 positions.append([x, y])
#                 position_arrays[y, x] = 1
#
#     if show:
#         x = [position[0] for position in positions]
#         y = [height - position[1] for position in positions]
#
#         plt.xlim(right=width, left=0)
#         plt.ylim(top=height, bottom=0)
#         plt.plot(x, y, 'ro')
#         plt.show()
#
#     return position_arrays


def get_slider_edge_position_by_alpha(
    image: Image, alpha=(80, 254), show=False
) -> np.ndarray:
    """
    根据边界透明度获取小滑块 边界
    @param image: 闭
    @param alpha: 透明度 开区间
    @param show: 是否画图 方便调试
    @return: numpy.ndarray 二维矩阵,缺口边界为1,其他为0。 横向为列,纵向为行。左上角为原点
    """
    pix = image.load()
    width = image.size[0]
    height = image.size[1]

    positions = []
    position_arrays = np.zeros((height, width), dtype=np.int)  # 高度为行 宽度为列

    for x in range(width):
        for y in range(height):
            r, g, b, a = pix[x, y]
            if a >= alpha[0] and a <= alpha[1]:  # 阴影为半透明 0 为全透明 255为不透明
                positions.append([x, y])
                position_arrays[y, x] = 1

    if show:
        x = [position[0] for position in positions]
        y = [height - position[1] for position in positions]

        plt.xlim(right=width, left=0)
        plt.ylim(top=height, bottom=0)
        plt.plot(x, y, "ro")
        plt.show()

    return position_arrays


def get_slider_edge_by_convolve2d(image: Image) -> np.ndarray:
    slider_fillter = get_slider_edge_position_by_alpha(
        image, show=False, alpha=(255, 255)
    )
    slider_fillter = delete_blank_edge(slider_fillter)

    slider_fillter = expand_edges(slider_fillter, count=1, axis=0, pos=0)  # 首行
    slider_fillter = expand_edges(slider_fillter, count=1, axis=1, pos=0)  # 首列
    slider_fillter = expand_edges(slider_fillter, count=1, axis=0, pos=-1)  # 末行
    slider_fillter = expand_edges(slider_fillter, count=1, axis=1, pos=-1)  # 末列

    # 做卷积 将中心为1的点去掉
    fillter = asarray([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])

    slider_fillter = convolve2d(slider_fillter, fillter)

    # 4 周为负数,非边界,只有大于0的才是边界
    slider_fillter = cover_number(
        slider_fillter != 0, 1, 0
    )  # slider_fillter != 0 则边缘粗度为2
    # slider_fillter = delete_blank_edge(slider_fillter)

    return slider_fillter


def print_array(array: np.ndarray):
    np.set_printoptions(threshold=np.inf, linewidth=np.inf)
    print(array)


def asarray(array: list) -> np.ndarray:
    """
    数组转np.ndarray
    @param array: 二维的list
    @return:
    """
    return np.asarray(array)


def delete_blank_edge(array: np.ndarray):
    """
    删除空白的边界(整行 或 整列都为0 则删除)
    @param array:
    @return:
    """
    rows, cols = array.shape[:2]
    for row in range(rows):  # 上到下遍历, 删除水平为0的行,到不为0的行时结束
        if sum(array[0,]) == 0:
            array = np.delete(array, 0, 0)
        else:
            break

    rows, cols = array.shape[:2]
    for row in reversed(range(rows)):  # 下到上遍历, 删除水平为0的行,到不为0的行时结束
        if sum(array[-1,]) == 0:
            array = np.delete(array, -1, 0)
        else:
            break

    rows, cols = array.shape[:2]
    for col in range(cols):  # 上到下遍历, 删除垂直为0的列,到不为0的列时结束
        if sum(array[:, 0]) == 0:
            array = np.delete(array, 0, 1)
        else:
            break

    rows, cols = array.shape[:2]
    for col in reversed(range(cols)):  # 下到上遍历, 删除垂直为0的列,到不为0的列时结束
        if sum(array[:, -1]) == 0:
            array = np.delete(array, -1, 1)
        else:
            break

    return array


def cover_number(condition, x, y):
    """
    转换数组中的值为指定的值 条件为真时转换为x,为假时转为y
    eg:
        np.where(a > 0, a, 0) # 将 类型为np.ndarray的a值大于零的不动,小于零的改为0
    @return:
    """
    return np.where(condition, x, y)


def expand_edges(array: np.ndarray, *, count, axis, pos=0) -> np.ndarray:
    """
    扩大边缘
    @param array:
    @param count: 边缘数量
    @param axis: 0/1 (0 为行 1 为列)
    @param pos: 插入的位置 (0为首行或首列 -1为末行或末列)
    @return:
    """
    if axis == 0:
        zero_array = np.zeros((array.shape[1]), dtype=np.int)
    else:
        zero_array = np.zeros((array.shape[0]), dtype=np.int)

    if pos == -1:
        pos = array.shape[0] if axis == 0 else array.shape[1]

    array = np.insert(array, pos, values=zero_array, axis=axis)

    return array


def convolve2d(bg_array: np.ndarray, fillter: np.ndarray) -> np.ndarray:
    """
    same 2d卷积 参考:https://blog.csdn.net/m0_38007695/article/details/82794454
    @param bg_array: 背景二维二维矩阵
    @param fillter: 小窗口二维矩阵, 行列最好为奇数
    @return:
    """
    bg_h, bg_w = bg_array.shape[:2]
    # K的高和宽
    fillter_h, fillter_w = fillter.shape[:2]
    # 计算full卷积
    c_full = signal.convolve2d(bg_array, fillter, mode="full")
    # 指定锚点的位置
    kr, kc = fillter_h // 2, fillter_w // 2
    # 根据锚点的位置,从full卷积中截取得到same卷积
    c_same = c_full[
        fillter_h - kr - 1 : bg_h + fillter_h - kr - 1,
        fillter_w - kc - 1 : bg_w + fillter_w - kc - 1,
    ]

    return c_same


def canny_edge(image_array: np.ndarray, show=False) -> np.ndarray:
    """
    锐化边缘
    @param image_array:
    @return:
    """
    can = cv2.Canny(image_array, threshold1=200, threshold2=300)

    if show:
        cv2.imshow("candy", can)
        cv2.waitKey()
        cv2.destroyAllWindows()

    return can


def draw_pic_from_array(array: np.ndarray) -> None:
    """
    根据array 画图
    @param array:
    @return:
    """
    plt.figure()  # 打开matplotlib的可视化figure
    plt.imshow(array)
    plt.gray()  # 灰阶图
    plt.title("filter image")  # 标题
    plt.show()


def find_gap_edge_center_point(
    bg_arrays: np.ndarray, slide_arrags: np.ndarray
) -> tuple:
    """
    获取缺口中心点
    @param bg_arrays: 背景图缺口边界矩阵
    @param slide_arrags: 滑块边界矩阵
    @return: 中心点 (x,y) 横向为x, 纵向y,左上角为坐标原点
    """
    slide_window_row, slide_window_cols = slide_arrags.shape  # 滑块窗口的行列数
    bg_rows, bg_cols = bg_arrays.shape  # 背景图的行列数

    bg_vertical_center = bg_rows // 2  # 滑块缺口一般在垂直的中间位置 及 中间行
    slider_window_center_vertical_padding = slide_window_row // 2  # 滑动窗口中心点到上下边距 及 垂直边距
    slider_window_center_horizontal_padding = (
        slide_window_cols // 2
    )  # 滑动窗口中心点到左右边距 及 水平边距

    max_point_sum = 0
    center_point = None

    for col in range(
        slider_window_center_horizontal_padding,
        bg_cols - slider_window_center_horizontal_padding + 1,
    ):  # 横向移动滑块窗口,求滑块窗口内的矩阵乘积
        if (
            bg_vertical_center + slider_window_center_vertical_padding > bg_rows
            or col + slider_window_center_horizontal_padding > bg_cols
        ):
            break

        current_window = bg_arrays[
            bg_vertical_center
            - slider_window_center_vertical_padding : bg_vertical_center
            + slider_window_center_vertical_padding,
            col
            - slider_window_center_horizontal_padding : col
            + slider_window_center_horizontal_padding,
        ]  # 当前被遮罩的窗口

        try:
            point_sum = (slide_arrags * current_window).sum()
        except:
            continue

        if point_sum > max_point_sum:
            max_point_sum = point_sum
            center_point = (col, bg_vertical_center)

    return center_point


def find_max_point(arrays: np.ndarray, search_on_horizontal_center=False) -> tuple:
    """
    找二维数组中最大的点
    @param arrays:
    @param search_on_horizontal_center: 只在水平居中处找
    @return: 中心点 (x,y) 横向为x, 纵向y,左上角为坐标原点
    """
    max_point = 0
    max_point_pos = None

    array_rows, array_cols = arrays.shape

    if search_on_horizontal_center:
        for col in range(array_cols):
            if arrays[array_rows // 2, col] > max_point:
                max_point = arrays[array_rows // 2, col]
                max_point_pos = col, array_rows // 2
    else:
        for row in range(array_rows):
            for col in range(array_cols):
                if arrays[row, col] > max_point:
                    max_point = arrays[row, col]
                    max_point_pos = col, row

    return max_point_pos


def draw_pos(pic: str, pos: tuple, rect_range=None):
    """
    画点 画点时以左下角为原点
    @param pic: 图片
    @param pos: 点的位置
    @return:
    """
    img = cv2.imread(pic)
    if rect_range:
        left_top_pos = pos[0] - rect_range[1] // 2, pos[1] - rect_range[0] // 2
        right_bottom_pos = pos[0] + rect_range[1] // 2, pos[1] + rect_range[0] // 2
    else:
        left_top_pos = pos
        right_bottom_pos = pos

    cv2.rectangle(
        img, left_top_pos, right_bottom_pos, (0, 0, 255), 2
    )  # 图片 左上角位置 右下角位置 矩形框颜色 边框像素
    if rect_range:
        cv2.rectangle(img, pos, pos, (0, 0, 255), 2)  # 图片 左上角位置 右下角位置 矩形框颜色 边框像素
    cv2.imshow(pic, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


def get_offset_x(slide_arrags: np.ndarray, gap_edge_center_point: tuple) -> int:
    """
    获取滑块的偏移量
    @param slide_arrags: 滑块数组
    @param gap_edge_center_point: 缺口坐标
    @return:
    """

    return gap_edge_center_point[0] - slide_arrags.shape[1] // 2


def clear_white(img: str) -> np.ndarray:
    """
    清除图片的空白区域,这里主要清除滑块的空白
    Args:
        img: 图片地址

    Returns:

    """
    img = cv2.imread(img)
    rows, cols, channel = img.shape
    min_x = 255
    min_y = 255
    max_x = 0
    max_y = 0
    for x in range(1, rows):
        for y in range(1, cols):
            t = set(img[x, y])
            if len(t) >= 2:
                if x <= min_x:
                    min_x = x
                elif x >= max_x:
                    max_x = x

                if y <= min_y:
                    min_y = y
                elif y >= max_y:
                    max_y = y
    img1 = img[min_x:max_x, min_y:max_y]
    return img1


def get_gap_center_point(bg_pic, slider_pic, show=False) -> tuple:
    """
    获取缺口位置, 为上面函数的汇总调度
    @param bg_pic:
    @param slider_pic:
    @return: (x, y)
    """

    # slider_image = get_image(slider_pic)

    bg_array = pic2gray(bg_pic)  # 图像灰度画

    # 锐化边缘
    edge_detection_array = canny_edge(bg_array, show=show)

    # # # 获取滑块 filter
    # # slider_edge_fillter = get_slider_edge_position(slider_image, show=False, alpha=(30, 254))  # 阴影边界 根据透明度
    # slider_content_fillter = get_slider_edge_position_by_alpha(slider_image, show=False, alpha=(255, 255))  # 内部图形
    # #
    # # # 删除空白边界
    # # slider_edge_fillter = delete_blank_edge(slider_edge_fillter)
    # # slider_content_fillter = delete_blank_edge(slider_content_fillter)
    # #
    # # # 内缩一些隐形边界,当实际边界也落入到阴影里,因为上面得到的边界为阴影边界,实际匹配时有可能是匹配轮廓,而非阴影
    # # slider_edge_content_difference = (slider_edge_fillter.shape[0] - slider_content_fillter.shape[0], slider_edge_fillter.shape[1] - slider_content_fillter.shape[1])
    # # slider_fillter = cv2.resize(slider_edge_fillter, (slider_edge_fillter.shape[0] - slider_edge_content_difference[0] // 2, slider_edge_fillter.shape[1] - slider_edge_content_difference[1] // 2),
    # #                             interpolation=cv2.INTER_AREA)  # https://blog.csdn.net/zh_jessica/article/details/77946346
    #
    # slider_content_fillter = delete_blank_edge(slider_content_fillter)
    # print_array(slider_content_fillter)
    #
    # fillter = asarray([
    #     [-1, -1, -1],
    #     [-1, 8, -1],
    #     [-1, -1, -1],
    # ])
    #
    # slider_content_fillter = convolve2d(slider_content_fillter, fillter)
    #
    # slider_fillter = cover_number(slider_content_fillter != 0, 1, 0)
    # print_array(slider_fillter)

    # slider_fillter = get_slider_edge_by_convolve2d(slider_image)
    # draw_pic_from_array(slider_fillter)

    slider_fillter = clear_white(slider_pic)
    slider_fillter = canny_edge(slider_fillter, show=show)

    slider_fillter = np.rot90(slider_fillter, 2)  # 逆时针旋转90度2次 即180度, 卷积的定义就是要旋转180度...

    # 将为0 的点设置为负数,防止匹配到噪声
    # total_point = slider_fillter.size
    # no_zero_point = sum(sum(slider_fillter))
    # zero_point = total_point - no_zero_point
    # slider_fillter = cover_number(
    #     slider_fillter == 0, -no_zero_point / zero_point, 1
    # )  # 为0点转换为 -1 * 不为零点数/为零点数。这样矩阵和为0
    # print_array(slider_fillter)

    # draw_pic_from_array(slider_fillter)

    # 找缺口中心点
    # center_point = find_gap_edge_center_point(edge_detection_array, slider_fillter)
    # draw_pic_from_array(edge_detection_array)

    edge_filltered = convolve2d(
        edge_detection_array, slider_fillter
    )  # 用fillter 与 蜕化后的背景做卷积
    # draw_pic_from_array(edge_filltered)

    center_point = find_max_point(edge_filltered)

    center_point = center_point[0], center_point[1]
    if show:
        draw_pos(bg_pic, center_point, rect_range=slider_fillter.shape)

    return center_point



if __name__ == "__main__":
    # seconds = random.randint(2, 10) + random.random()
    # distinct = 300 + random.randint(2, 10) + random.random()
    # tracks, seconds = get_tracks_by_ease_func(distinct, ease_out_quart, seconds)
    # tracks = get_tracks(distinct)
    # tracks = get_tracks_by_random(300)
    # tracks = get_tracks_by_a(300)
    #
    # draw_tracks(tracks, seconds)

    # 获取滑块 filter
    # slider_image = get_image('slide.png')
    #
    # # slider_edge_fillter = get_slider_edge_position(slider_image, show=False, alpha=(30, 254))
    # slider_content_fillter = get_slider_edge_position_by_alpha(slider_image, show=False, alpha=(255, 255))
    #
    # # 处理滑块fillter
    # # slider_edge_fillter = delete_blank_edge(slider_edge_fillter)
    # # print_array(slider_edge_fillter)
    #
    # slider_content_fillter = delete_blank_edge(slider_content_fillter)
    # print_array(slider_content_fillter)
    #
    # # 四周插入一圈为0的点, 为了方便找边缘
    # zero_array_row = np.zeros((slider_content_fillter.shape[1]), dtype=np.int)
    # zero_array_col = np.zeros((slider_content_fillter.shape[0] + 2), dtype=np.int)  # 插完行后 列多了两列
    #
    # slider_content_fillter = np.insert(slider_content_fillter, 0, values=zero_array_row, axis=0)  # 首行
    # slider_content_fillter = np.insert(slider_content_fillter, slider_content_fillter.shape[0], values=zero_array_row, axis=0)  # 末行
    # slider_content_fillter = np.insert(slider_content_fillter, 0, values=zero_array_col, axis=1)  # 首列
    # slider_content_fillter = np.insert(slider_content_fillter, slider_content_fillter.shape[1], values=zero_array_col, axis=1)  # 首列
    #
    # # print_array(slider_content_fillter)
    #
    # fillter = asarray([
    #     [-1, -1, -1],
    #     [-1, 8, -1],
    #     [-1, -1, -1],
    # ])
    #
    # slider_content_fillter = convolve2d(slider_content_fillter, fillter)
    # print_array(slider_content_fillter)
    #
    # slider_content_fillter = cover_number(slider_content_fillter != 0, 1, 0)
    # slider_content_fillter = delete_blank_edge(slider_content_fillter)
    # print_array(slider_content_fillter)

    # slider_edge_content_difference = (slider_edge_fillter.shape[0] - slider_content_fillter.shape[0], slider_edge_fillter.shape[1] - slider_content_fillter.shape[1])
    # # print(slider_edge_content_difference)
    #
    # slider_fillter = cv2.resize(slider_edge_fillter, (slider_edge_fillter.shape[0] - slider_edge_content_difference[0] // 2, slider_edge_fillter.shape[1] - slider_edge_content_difference[1] // 2),
    #                             interpolation=cv2.INTER_NEAREST)
    #
    # print_array(slider_fillter)

    # array = asarray([
    #     [1, 2],
    #     [3, 4]
    # ])
    #
    # array = expand_edges(array, count=1, axis=0, pos=0)
    # array = expand_edges(array, count=1, axis=1, pos=0)
    # array = expand_edges(array, count=1, axis=0, pos=-1)
    # array = expand_edges(array, count=1, axis=1, pos=-1)
    #
    # print(array)

    # img = 'WechatIMG1282.jpeg'
    #
    # img = pic2gray(img)
    #
    # canny_edge(img, show=True)

    # get_gap_center_point("test_files/bg2.png", "test_files/slider2.png", show=True)
    # a = pic2gray("test_files/bg3.png", True)
    # print_array(a)

    # bg = asarray(
    #     [
    #         [0, 0, 0, 0, 0, 0, 0],
    #         [0, 0, 1, 1, 1, 0, 0],
    #         [0, 0, 1, 1, 1, 0, 0],
    #         [0, 0, 1, 1, 1, 0, 0],
    #         [0, 0, 0, 0, 0, 0, 0],
    #     ]
    # )
    #
    # # fillter = np.rot90(fillter, 2)  # 逆时针旋转90度2次 即180度
    # # print(fillter)
    #
    # filte2 = asarray([[1, 1, 1], [1, 1, 1], [1, 1, 1]])
    #
    # result = convolve2d(bg, filte2)
    # print(result)
    image = Image.open("download.jpg")
    start = time.time()
    print(new_get_gap_point(image, type=1, size="280x158"))
    print("耗时: ", time.time() - start)

  

标签:轨迹,滑块,fillter,验证码,slider,tracks,edge,np,array
From: https://www.cnblogs.com/yoyo1216/p/17502974.html

相关文章

  • 古诗文网验证码识别
    1.将超级鹰的验证码识别demo代码添加到请求代码中_1: 2.将超级鹰的验证码识别demo代码添加到请求代码中_2: 3.先请求网站数据下载验证码图片,调用超级鹰函数进行图片验证码识别: 4.识别古诗文网的登录验证码图片: ......
  • 超级鹰验证码识别网站流程
    1.注册登录后进入用户中心: 2.查看是否有积分如果没有则关注公众号领取积分: 3.关注超级鹰公众号领取识别码积分: 4.点击软件ID生成一个软件ID_1: 5.创建相对应的软件名和使用说明: 6.创建成功后进入开发者文档下载python语言demo: 7.超级鹰py文件修改账号密码软件ID:......
  • 【Django】图形验证码显示及验证
    图形验证码显示及验证开发项目时,在登陆或者注册功能中为防止脚本恶意破坏系统,故而添加图形验证码。1安装配置安装第三方库pipinstalldjango-simple-captcha配置settings.pyINSTALLED_APPS=[ ......'captcha',]将已存在的数据库迁移文件集同步到数据库中......
  • thinkphp3.2后台谷歌验证码
    1.谷歌类库A<?phpnamespaceCommon\Ext;classGoogleAuthenticator{ protected$_codeLength=6; publicfunctioncreateSecret($secretLength=16) { $validChars=$this->_getBase32LookupTable(); unset($validChars[32]); $secret='';......
  • TienChin 验证码响应结果分析&验证码生成接口分析
    验证码响应结果分析首先从前端开始进行分析,进入到登录页面,打开开发者工具(f12),找到network,f5刷新一下页面,然后,筛选一下,筛选内容为Fetch/XHR:你会发现列表中有两项内容,我们只需要查看captchaImage即可,从名字就可以看出是验证码图片的意思,然后我们查看这个响应结果是什么,响应......
  • go 使用验证码库
    go使用验证码库标签(空格分隔):go安装gogetgithub.com/mojocn/base64Captcha使用packageapiimport( "github.com/gin-gonic/gin" "github.com/mojocn/base64Captcha" "go.uber.org/zap" "net/http")var( //存储方式 store=base......
  • 手机验证码登录
    代码写在reggie_take_out5中了从这里就到了移动端开发1. 效果展示  5-122. 短信发送  5-132.1 短信服务介绍  5-13目前市面.上有很多第三方提供的短信服务,这些第三方短信服务会和各个运营商(移动、联通、电信)对接,我们只需要注册成为会员并且按照提供的开发文档进行调用就......
  • .NET Core Web API 实现图形验证码
    https://blog.csdn.net/liwan09/article/details/126319320?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-126319320-blog-101289369.235%5Ev38%5Epc_relevant_sort_base2&depth_1-utm_......
  • [MAUI]弧形进度条与弧形滑块的交互实现
    @目录弧形基类定义绘制弧弧形进度条(ProgressBar)添加动画宽度补偿文本弧形滑块(Slider)创建控制柄拖动事件处理项目地址进度条(ProgressBar)用于展示任务的进度,告知用户当前状态和预期;滑块(Slider)通过拖动滑块在一个固定区间内进行选择数值范围。进度条和滑块都是进度值在UI界面......
  • 最新SMS-Activate短信验证码接收教程
    有些国外应用在使用应用上的功能时需要注册账号,由于某种不可抗因素,我们的手机号一般不支持注册,接收不到信息验证码,于是我们可以使用sms-activate提供的服务,实惠又稳定,最近sms-activate.org网站迎来了大更新许多小伙伴私信我说不会使用SmS-Activate了,今天正巧有需求,索性将验证过程......