Files
kami_jd_ck/bind_card/utils/slide.py
2025-04-13 19:17:51 +08:00

395 lines
13 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import json
import math
import random
import PIL
import numpy as np
import urllib.parse
from pathlib import Path
import cv2
class BezierTrajectory:
def _bztsg(self, dataTrajectory):
lengthOfdata = len(dataTrajectory)
def staer(x):
t = ((x - dataTrajectory[0][0]) / (dataTrajectory[-1][0] - dataTrajectory[0][0]))
y = np.array([0, 0], dtype=np.float64)
for s in range(len(dataTrajectory)):
y += dataTrajectory[s] * ((math.factorial(lengthOfdata - 1) / (
math.factorial(s) * math.factorial(lengthOfdata - 1 - s))) * math.pow(t, s) * math.pow(
(1 - t), lengthOfdata - 1 - s))
return y[1]
return staer
def _type(self, type, x, numberList):
numberListre = []
pin = (x[1] - x[0]) / numberList
if type == 0:
for i in range(numberList):
numberListre.append(i * pin)
if pin >= 0:
numberListre = numberListre[::-1]
elif type == 1:
for i in range(numberList):
numberListre.append(1 * ((i * pin) ** 2))
numberListre = numberListre[::-1]
elif type == 2:
for i in range(numberList):
numberListre.append(1 * ((i * pin - x[1]) ** 2))
elif type == 3:
dataTrajectory = [np.array([0, 0]), np.array([(x[1] - x[0]) * 0.8, (x[1] - x[0]) * 0.6]),
np.array([x[1] - x[0], 0])]
fun = self._bztsg(dataTrajectory)
numberListre = [0]
for i in range(1, numberList):
numberListre.append(fun(i * pin) + numberListre[-1])
if pin >= 0:
numberListre = numberListre[::-1]
numberListre = np.abs(np.array(numberListre) - max(numberListre))
biaoNumberList = ((numberListre - numberListre[numberListre.argmin()]) / (
numberListre[numberListre.argmax()] - numberListre[numberListre.argmin()])) * (x[1] - x[0]) + x[0]
biaoNumberList[0] = x[0]
biaoNumberList[-1] = x[1]
return biaoNumberList
def getFun(self, s):
'''
:param s: 传入P点
:return: 返回公式
'''
dataTrajectory = []
for i in s:
dataTrajectory.append(np.array(i))
return self._bztsg(dataTrajectory)
def simulation(self, start, end, le=1, deviation=0, bias=0.5):
start = np.array(start)
end = np.array(end)
cbb = []
if le != 1:
e = (1 - bias) / (le - 1)
cbb = [[bias + e * i, bias + e * (i + 1)] for i in range(le - 1)]
dataTrajectoryList = [start]
number = random.uniform(1, 15)
number_rounded1 = round(number, 2)
number2 = random.uniform(-15, -1)
number_rounded2 = round(number2, 2)
t = random.choice([number_rounded2, number_rounded1])
w = 0
for i in cbb:
px1 = start[0] + (end[0] - start[0]) * (random.random() * (i[1] - i[0]) + (i[0]))
p = np.array([px1, self._bztsg([start, end])(px1) + t * deviation])
dataTrajectoryList.append(p)
w += 1
if w >= 2:
w = 0
t = -1 * t
dataTrajectoryList.append(end)
return {"equation": self._bztsg(dataTrajectoryList), "P": np.array(dataTrajectoryList)}
def trackArray(self, start, end, numberList, le=4, deviation=0, bias=0.6, type=0, cbb=0, yhh=10):
s = []
fun = self.simulation(start, end, le, deviation, bias)
w = fun['P']
fun = fun["equation"]
if cbb != 0:
numberListOfcbb = round(numberList * 0.2 / (cbb + 1))
numberList -= (numberListOfcbb * (cbb + 1))
xTrackArray = self._type(type, [start[0], end[0]], numberList)
for i in xTrackArray:
s.append([i, fun(i)])
dq = yhh / cbb
kg = 0
ends = np.copy(end)
for i in range(cbb):
if kg == 0:
d = np.array([end[0] + (yhh - dq * i),
((end[1] - start[1]) / (end[0] - start[0])) * (end[0] + (yhh - dq * i)) + (
end[1] - ((end[1] - start[1]) / (end[0] - start[0])) * end[0])])
kg = 1
else:
d = np.array([end[0] - (yhh - dq * i),
((end[1] - start[1]) / (end[0] - start[0])) * (end[0] - (yhh - dq * i)) + (
end[1] - ((end[1] - start[1]) / (end[0] - start[0])) * end[0])])
kg = 0
# print(d)
y = self.trackArray(ends, d, numberListOfcbb, le=le, deviation=deviation, bias=bias, type=3, cbb=0,
yhh=yhh)
s += list(y['trackArray'])
ends = d
y = self.trackArray(ends, end, numberListOfcbb, le=le, deviation=deviation, bias=bias, type=2, cbb=0,
yhh=yhh)
s += list(y['trackArray'])
else:
xTrackArray = self._type(type, [start[0], end[0]], numberList)
for i in xTrackArray:
s.append([i, fun(i)])
return {"trackArray": np.array(s), "P": w}
def imshow(img, winname='test', delay=0):
"""cv2展示图片"""
cv2.imshow(winname, img)
cv2.waitKey(delay)
cv2.destroyAllWindows()
def pil_to_cv2(img):
"""
pil转cv2图片
:param img: pil图像, <type 'PIL.JpegImagePlugin.JpegImageFile'>
:return: cv2图像, <type 'numpy.ndarray'>
"""
img = cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
return img
def bytes_to_cv2(img):
"""
二进制图片转cv2
:param img: 二进制图片数据, <type 'bytes'>
:return: cv2图像, <type 'numpy.ndarray'>
"""
# 将图片字节码bytes, 转换成一维的numpy数组到缓存中
img_buffer_np = np.frombuffer(img, dtype=np.uint8)
# 从指定的内存缓存中读取一维numpy数据, 并把数据转换(解码)成图像矩阵格式
img_np = cv2.imdecode(img_buffer_np, 1)
return img_np
def cv2_open(img, flag=None):
"""
统一输出图片格式为cv2图像, <type 'numpy.ndarray'>
:param img: <type 'bytes'/'numpy.ndarray'/'str'/'Path'/'PIL.JpegImagePlugin.JpegImageFile'>
:param flag: 颜色空间转换类型, default: None
eg: cv2.COLOR_BGR2GRAY灰度图
:return: cv2图像, <numpy.ndarray>
"""
if isinstance(img, bytes):
img = bytes_to_cv2(img)
elif isinstance(img, (str, Path)):
img = cv2.imread(str(img))
elif isinstance(img, np.ndarray):
img = img
elif isinstance(img, PIL.Image):
img = pil_to_cv2(img)
else:
raise ValueError(f'输入的图片类型无法解析: {type(img)}')
if flag is not None:
img = cv2.cvtColor(img, flag)
return img
def convert_png_to_jpg(img_data):
"""
将透明背景的图片转换为白色背景使用OpenCV实现。
参数:
input_image_path: str输入图片的路径
output_image_path: str输出图片的路径
返回:
"""
# 使用BytesIO将数据转换为文件对象
img_array = np.frombuffer(img_data, np.uint8)
# 读取图像数据
img = cv2.imdecode(img_array, cv2.IMREAD_UNCHANGED)
# 检查是否读取成功
if img is None:
raise ValueError("Image could not be decoded from base64 data.")
# 分离RGBA通道
b, g, r, a = cv2.split(img)
# 创建一个与Alpha通道大小相同的全白背景
white_background = np.ones_like(a) * 255
# 将Alpha通道归一化到0-1范围
a = a / 255.0
# 按照Alpha通道的透明度混合原图和白色背景
r = r * a + white_background * (1 - a)
g = g * a + white_background * (1 - a)
b = b * a + white_background * (1 - a)
# 合并BGR通道
result = cv2.merge((b, g, r))
return result
def resize_image_to_width(img, target_width):
"""将图像调整为指定宽度,同时保持纵横比"""
height, width = img.shape[:2]
aspect_ratio = height / width
new_height = int(target_width * aspect_ratio)
resized_img = cv2.resize(img, (target_width, new_height))
return resized_img
def merge_images(img1, img2):
"""将两张图像垂直合并成一张图像,调整第二张图像的宽度以匹配第一张图像的宽度"""
# 获取两张图像的高度和宽度
height1, width1 = img1.shape[:2]
height2, width2 = img2.shape[:2]
# 如果第二张图像的宽度大于第一张图像的宽度,则缩放第二张图像
if width2 > width1:
img2 = resize_image_to_width(img2, width1)
# 重新获取第二张图像的高度和宽度
height2, width2 = img2.shape[:2]
# 计算新的高度和宽度
new_height = height1 + height2
new_width = width1
# 创建一个新的图像以容纳两张图像
merged_img = np.zeros((new_height, new_width, 3), dtype=np.uint8)
# 将第一张图像拷贝到新图像中
merged_img[:height1, :width1] = img1
# 将第二张图像拷贝到新图像中
merged_img[height1:, :width2] = img2
# 将合并后的图像编码为 PNG 格式的字节流
_, img_encoded = cv2.imencode('.png', merged_img)
img_bytes = img_encoded.tobytes()
return img_bytes
def get_distances(bg, tp, im_show=False, save_path=None):
# 读取图片
bg_img = cv2_open(bg)
tp_gray = cv2_open(tp, flag=cv2.COLOR_BGR2GRAY)
# 金字塔均值漂移
bg_shift = cv2.pyrMeanShiftFiltering(bg_img, 5, 50)
# 边缘检测
tp_gray = cv2.Canny(tp_gray, 255, 255)
bg_gray = cv2.Canny(bg_shift, 255, 255)
# 目标匹配
result = cv2.matchTemplate(bg_gray, tp_gray, cv2.TM_CCOEFF_NORMED)
# 解析匹配结果
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
distance = max_loc[0]
if save_path or im_show:
# 需要绘制的方框高度和宽度
tp_height, tp_width = tp_gray.shape[:2]
# 矩形左上角点位置
x, y = max_loc
# 矩形右下角点位置
_x, _y = x + tp_width, y + tp_height
# 绘制矩形
bg_img = cv2_open(bg)
cv2.rectangle(bg_img, (x, y), (_x, _y), (0, 0, 255), 2)
# 保存缺口识别结果到背景图
if save_path:
save_path = Path(save_path).resolve()
save_path = save_path.parent / f"{save_path.stem}.{distance}{save_path.suffix}"
save_path = save_path.__str__()
cv2.imwrite(save_path, bg_img)
# 显示缺口识别结果
if im_show:
imshow(bg_img)
return distance
def slider_swipe_time(length):
times = []
time_interval = None
_number = 0
for i in range(length):
if i < length - 10:
time_interval = random.uniform(0, 4)
else:
if time_interval and time_interval > 50 and random.random() > 0.80:
time_interval = random.uniform(time_interval - 40, time_interval)
else:
time_interval = random.uniform(1, 100)
_number += time_interval
times.append(round(time_interval))
return times # 返回时间间隔列表
def get_distance(background, slide):
'''
:param1:background是缺口图
:param2:slide是滑块图
'''
distance = get_distances(bg=background, tp=slide, im_show=False)
distance = distance + 5
yend = random.randint(random.randint(-60, -1), random.randint(1, 60))
random_case = random.choice([1, 2, 3])
baidong = random.randint(1, 50)
fangwei = random.randint(random.randint(-60, -1), random.randint(1, 60))
le = random.randint(20, 50)
if distance > 150:
number = random.uniform(2.2, 2.4)
elif 140 < distance < 150:
number = random.uniform(2.1, 2.2)
elif 130 < distance < 140:
number = random.uniform(2.0, 2.1)
elif 120 < distance < 130:
number = random.uniform(1.9, 2.0)
elif 110 < distance < 120:
number = random.uniform(1.8, 1.9)
else:
number = random.uniform(1.7, 1.8)
number_rounded = round(number, 2)
a = BezierTrajectory().trackArray(
start=[0, random.randint(0, 20)],
end=[distance, yend],
numberList=int(distance * number_rounded),
le=le,
type=random_case,
cbb=baidong,
yhh=fangwei,
)
_move_list = a["trackArray"].tolist()
move_list = []
length = len(_move_list)
swipe_times = slider_swipe_time(length)
swipe_times[0] = 0
swipe_times[1] = 0.01
swipe_times[2] = 0.03
swipe_times[3] = 0.04
swipe_times[4] = 0.04
for index, i in enumerate(_move_list):
x = round(i[0])
y = round(i[1])
move_list.append([x, y, swipe_times[index]])
return move_list
def save_photo_and_check(quekou, huakuai):
distance_list = get_distance(quekou, huakuai)
distance_dict = {}
distance_dict['6@hH@X'] = "H%io5u"
distance_dict['P7cH*^'] = "aOr*7C"
distance_dict['ht'] = 179
distance_dict['wt'] = 290
distance_dict['bw'] = 59
distance_dict['sw'] = 290
distance_dict['mw'] = 50
distance_dict['list'] = distance_list
photo_distance = str(json.dumps(distance_dict))
photo_distance = photo_distance.replace(" ", '')
# print(photo_distance)
track = urllib.parse.quote(photo_distance, safe=':,')
return track