├── models
└── __init__.py
├── utils
├── __init__.py
├── image_processing.py
├── face_encoding.py
├── face_detection.py
├── face_storage.py
└── face_quality.py
├── services
├── __init__.py
├── authentication.py
├── registration.py
└── recognition.py
├── business
└── xunfei
│ ├── __init__.py
│ ├── config.py
│ ├── utils.py
│ ├── face_feature_client.py
│ ├── face_compare_client.py
│ └── spark.py
├── .idea
├── vcs.xml
├── inspectionProfiles
│ └── profiles_settings.xml
├── modules.xml
├── poetry.xml
├── misc.xml
├── iflyface.iml
└── workspace.xml
├── pyproject.toml
├── .gitignore
├── app.py
└── poetry.lock
/models/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/services/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/business/xunfei/__init__.py:
--------------------------------------------------------------------------------
1 | from .face_compare_client import FaceCompareClient
2 | from .face_feature_client import FaceFeatureClient
3 | from .spark import SparkAPI
4 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/poetry.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/business/xunfei/config.py:
--------------------------------------------------------------------------------
1 | # 请填写控制台获取的APPID、APISecret、APIKey
2 | APP_ID = '142b649c'
3 | API_KEY_FACE_COMPARE = "3790438c24750aa9ed3b02ab6321c360"
4 | API_SECRET_FACE_COMPARE = 'ZGE2OWRlNjVkNzM0MzM5MzYwYWNkZTYy'
5 | SERVER_ID_FACE_COMPARE = 's67c9c78c'
6 | API_KEY_FACE_FEATURE = "002c130bd3c09614c4173a250b1ebd1b"
7 | API_KEY_SPARK = '3790438c24750aa9ed3b02ab6321c360'
8 | API_SECRET_SPARK = 'ZGE2OWRlNjVkNzM0MzM5MzYwYWNkZTYy'
9 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | name = "iflyface"
3 | version = "0.1.0"
4 | description = ""
5 | authors = ["p0ise "]
6 | readme = "README.md"
7 |
8 | [tool.poetry.dependencies]
9 | python = "^3.10"
10 | flask = "^3.0.2"
11 | requests = "^2.31.0"
12 | flask-cors = "^4.0.0"
13 | flask-socketio = "^5.3.6"
14 | opencv-python = "^4.9.0.80"
15 | facenet-pytorch = "^2.5.3"
16 | websocket-client = "^1.7.0"
17 |
18 |
19 | [build-system]
20 | requires = ["poetry-core"]
21 | build-backend = "poetry.core.masonry.api"
22 |
--------------------------------------------------------------------------------
/utils/image_processing.py:
--------------------------------------------------------------------------------
1 | import base64
2 |
3 | import cv2
4 | import numpy as np
5 | from PIL import Image
6 |
7 |
8 | def cv2_to_pil(image):
9 | """Convert a CV2 image to PIL format."""
10 | image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
11 | return Image.fromarray(image)
12 |
13 |
14 | def parse_frame_data(frame_data):
15 | """Parse frame data from base64 encoding."""
16 | frame_data = base64.b64decode(frame_data.split(',')[1])
17 | frame = np.frombuffer(frame_data, dtype=np.uint8)
18 | frame = cv2.imdecode(frame, flags=1)
19 | return cv2_to_pil(frame)
20 |
--------------------------------------------------------------------------------
/.idea/iflyface.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/utils/face_encoding.py:
--------------------------------------------------------------------------------
1 | import torch
2 | from facenet_pytorch import InceptionResnetV1
3 | from torchvision import transforms
4 |
5 | device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
6 | resnet = InceptionResnetV1(pretrained='vggface2').eval().to(device)
7 |
8 |
9 | def encode_face(face_image):
10 | """Encode a face image into a high-dimensional vector."""
11 | preprocess = transforms.Compose([
12 | transforms.Resize((160, 160)),
13 | transforms.ToTensor(),
14 | ])
15 | face_tensor = preprocess(face_image).unsqueeze(0)
16 | with torch.no_grad():
17 | face_encoding = resnet(face_tensor)
18 | return face_encoding.detach().cpu().numpy()[0]
19 |
--------------------------------------------------------------------------------
/services/authentication.py:
--------------------------------------------------------------------------------
1 | from utils.face_detection import find_primary_face, align_face
2 | from utils.face_encoding import encode_face
3 | from utils.face_quality import evaluate_face_quality
4 | from utils.face_storage import FaceStorage
5 |
6 | face_storage = FaceStorage()
7 |
8 |
9 | def authenticate_face(image):
10 | """
11 | 对给定的图像进行人脸认证。
12 |
13 | 参数:
14 | - image: 包含用户人脸的图像(PIL.Image格式)。
15 |
16 | 返回:
17 | - 认证成功与否的布尔值以及相应的消息。
18 | """
19 | primary_face = find_primary_face(image)
20 | if primary_face:
21 | box, prob, landmark = primary_face
22 | if evaluate_face_quality(box, prob, image, landmark):
23 | aligned_face = align_face(image, box, landmark)
24 | face_encoding = encode_face(aligned_face)
25 | matched_face = face_storage.match_face(face_encoding)
26 | if matched_face:
27 | return True, matched_face['name']
28 | else:
29 | return False, "认证失败,未知人脸,请先注册"
30 | else:
31 | return False, "人脸质量不符合要求"
32 | else:
33 | return False, "未检测到人脸"
34 |
--------------------------------------------------------------------------------
/services/registration.py:
--------------------------------------------------------------------------------
1 | from utils.face_detection import find_primary_face, align_face
2 | from utils.face_encoding import encode_face
3 | from utils.face_quality import is_face_forward, evaluate_face_quality
4 | from utils.face_storage import FaceStorage
5 |
6 | face_storage = FaceStorage()
7 |
8 |
9 | def register_face(image, username):
10 | """
11 | 注册新的用户人脸。
12 |
13 | 参数:
14 | - image: 包含用户人脸的图像(PIL.Image格式)。
15 | - username: 用户的名称。
16 |
17 | 返回:
18 | - 成功或失败的消息。
19 | """
20 | primary_face = find_primary_face(image)
21 | if primary_face:
22 | box, prob, landmark = primary_face
23 | if is_face_forward(landmark) and evaluate_face_quality(box, prob, image, landmark):
24 | aligned_face = align_face(image, box, landmark)
25 | face_encoding = encode_face(aligned_face)
26 | matched_face = face_storage.match_face(face_encoding)
27 | if matched_face is None:
28 | face = face_storage.add_known_face(face_encoding, username)
29 | face_id = face['id']
30 | return True, username
31 | else:
32 | return False, "人脸已注册"
33 | else:
34 | return False, "人脸质量不符合要求或非正脸"
35 | else:
36 | return False, "未检测到人脸"
37 |
--------------------------------------------------------------------------------
/business/xunfei/utils.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import hashlib
3 | import hmac
4 | import mimetypes
5 |
6 |
7 | class AssembleHeaderException(Exception):
8 | pass
9 |
10 |
11 | def parse_url(request_url):
12 | stidx = request_url.index("://")
13 | host = request_url[stidx + 3:]
14 | schema = request_url[:stidx + 3]
15 | edidx = host.index("/")
16 | if edidx <= 0:
17 | raise AssembleHeaderException("Invalid request URL: " + request_url)
18 | path = host[edidx:]
19 | host = host[:edidx]
20 | return schema, host, path
21 |
22 |
23 | def generate_signature(api_secret, host, date, method, path):
24 | signature_origin = f"host: {host}\ndate: {date}\n{method} {path} HTTP/1.1"
25 | signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
26 | digestmod=hashlib.sha256).digest()
27 | return base64.b64encode(signature_sha).decode('utf-8')
28 |
29 |
30 | def assemble_authorization_header(api_key, signature_sha):
31 | authorization_origin = (f'api_key="{api_key}", algorithm="hmac-sha256", '
32 | f'headers="host date request-line", signature="{signature_sha}"')
33 | return base64.b64encode(authorization_origin.encode('utf-8')).decode('utf-8')
34 |
35 |
36 | def encode_image(image_path):
37 | """
38 | 对图片文件进行Base64编码,并自动检测图片类型。
39 | 返回编码后的图片字符串和图片类型。
40 | """
41 | # 检测文件类型
42 | mime_type, _ = mimetypes.guess_type(image_path)
43 | if mime_type is None:
44 | raise ValueError("Cannot determine the file type of the image.")
45 | # 获取文件的扩展名,例如 "image/jpeg" -> "jpeg"
46 | file_type = mime_type.split('/')[-1]
47 |
48 | with open(image_path, 'rb') as image_file:
49 | encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
50 | return encoded_string, file_type
51 |
--------------------------------------------------------------------------------
/utils/face_detection.py:
--------------------------------------------------------------------------------
1 | import cv2
2 | import numpy as np
3 | import torch
4 | from PIL import Image
5 | from facenet_pytorch import MTCNN
6 |
7 | device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
8 | mtcnn = MTCNN(keep_all=True, device=device)
9 |
10 |
11 | def find_faces(image):
12 | # 使用MTCNN检测人脸,同时返回框、置信度和关键点
13 | boxes, probs, landmarks = mtcnn.detect(image, landmarks=True)
14 | if boxes is not None:
15 | return boxes, probs, landmarks
16 | else:
17 | return [], [], []
18 |
19 |
20 | def find_primary_face(image):
21 | """
22 | 查找图像中最显著的人脸。
23 |
24 | 参数:
25 | - image: PIL.Image对象,包含待检测的图像。
26 |
27 | 返回:
28 | - primary_face: 最显著的人脸信息,包括框、置信度和关键点。
29 | 如果没有检测到人脸,则返回None。
30 | """
31 | boxes, probs, landmarks = mtcnn.detect(image, landmarks=True)
32 | if boxes is not None:
33 | return boxes[0], probs[0], landmarks[0]
34 | else:
35 | return None
36 |
37 |
38 | def align_face(image, box, landmark):
39 | # 计算两眼之间的角度
40 | eye_left = np.array(landmark[0])
41 | eye_right = np.array(landmark[1])
42 | d_y = eye_right[1] - eye_left[1]
43 | d_x = eye_right[0] - eye_left[0]
44 | angle = np.degrees(np.arctan2(d_y, d_x))
45 |
46 | # 计算box中心作为旋转中心
47 | box_center = ((box[0] + box[2]) / 2, (box[1] + box[3]) / 2)
48 |
49 | # 将PIL.Image转换为numpy数组以便使用cv2函数处理
50 | image_np = np.array(image)
51 |
52 | # 应用仿射变换对齐整个画面
53 | scale = 1
54 | M = cv2.getRotationMatrix2D(box_center, angle, scale)
55 | rotated_image_np = cv2.warpAffine(image_np, M, (image_np.shape[1], image_np.shape[0]))
56 |
57 | # 将旋转后的numpy数组图像转换回PIL.Image
58 | rotated_image = Image.fromarray(rotated_image_np)
59 |
60 | # 从旋转后的图像中截取人脸区域
61 | face_image = rotated_image.crop(box)
62 |
63 | # 缩放图像到指定的尺寸
64 | aligned_face = face_image.resize((160, 160))
65 |
66 | return aligned_face
67 |
--------------------------------------------------------------------------------
/utils/face_storage.py:
--------------------------------------------------------------------------------
1 | import uuid
2 |
3 | import numpy as np
4 |
5 |
6 | class SingletonMeta(type):
7 | _instances = {}
8 |
9 | def __call__(cls, *args, **kwargs):
10 | if cls not in cls._instances:
11 | instance = super().__call__(*args, **kwargs)
12 | cls._instances[cls] = instance
13 | return cls._instances[cls]
14 |
15 |
16 | class FaceStorage(metaclass=SingletonMeta):
17 | def __init__(self):
18 | self.known_faces = [] # 存储已知人脸的信息,每个条目是一个字典
19 |
20 | def add_known_face(self, face_encoding, name):
21 | """将新的人脸编码和名称添加到存储中"""
22 | face_id = str(uuid.uuid4()) # 生成唯一标识符
23 | face = {
24 | "id": face_id,
25 | "name": name,
26 | "encoding": face_encoding
27 | }
28 | self.known_faces.append(face)
29 | return face
30 |
31 | def match_face(self, face_encoding, tolerance=0.6):
32 | """在已知的人脸编码中寻找匹配项"""
33 | if not self.known_faces:
34 | return None
35 | distances = np.linalg.norm([face["encoding"] for face in self.known_faces] - face_encoding, axis=1)
36 | best_match_index = np.argmin(distances)
37 | if distances[best_match_index] < tolerance:
38 | return self.known_faces[best_match_index]
39 | return None
40 |
41 | def update_face_encoding(self, face_id, new_encoding):
42 | """根据人脸ID更新人脸编码"""
43 | for face in self.known_faces:
44 | if face["id"] == face_id:
45 | face["encoding"] = new_encoding
46 | return True
47 | return False
48 |
49 | def rename_face(self, face_id, new_name):
50 | """根据人脸ID更新人脸名称"""
51 | for face in self.known_faces:
52 | if face["id"] == face_id:
53 | face["name"] = new_name
54 | return True
55 | return False
56 |
57 | def get_face_info(self, face_id):
58 | """根据人脸ID获取人脸信息"""
59 | for face in self.known_faces:
60 | if face["id"] == face_id:
61 | return face
62 | return None
63 |
--------------------------------------------------------------------------------
/business/xunfei/face_feature_client.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import hashlib
3 | import os.path
4 | import time
5 | from urllib.parse import urljoin
6 |
7 | import requests
8 |
9 | from .config import APP_ID, API_KEY_FACE_FEATURE
10 |
11 |
12 | class FaceFeatureClient:
13 | def __init__(self):
14 | self.base_url = "http://tupapi.xfyun.cn/v1/"
15 | self.types = ['age', 'sex', 'expression', 'face_score']
16 |
17 | def get_header(self, image_name):
18 | cur_time = str(int(time.time()))
19 | # param = {"image_name": image_name, "image_url": ''}
20 | param = "{\"image_name\":\"" + image_name + "\",\"image_url\":\"\"}"
21 | param_base64 = base64.b64encode(param.encode("utf-8"))
22 |
23 | m2 = hashlib.md5()
24 | m2.update((API_KEY_FACE_FEATURE + cur_time + str(param_base64, 'utf-8')).encode('utf-8'))
25 | check_sum = m2.hexdigest()
26 |
27 | header = {
28 | 'X-CurTime': cur_time,
29 | 'X-Param': param_base64,
30 | 'X-Appid': APP_ID,
31 | 'X-CheckSum': check_sum,
32 | }
33 | return header
34 |
35 | def analyze(self, type, image_path):
36 | url = urljoin(self.base_url, type)
37 | image_name = os.path.basename(image_path)
38 | headers = self.get_header(image_name)
39 | with open(image_path, 'rb') as f:
40 | data = f.read()
41 | response = requests.post(url, data, headers=headers)
42 | if response.status_code == 200:
43 | result = response.json()
44 | code = result['code']
45 | if code == 0:
46 | value = result['data']['fileList'][0]['label']
47 | else:
48 | value = result['desc']
49 | else:
50 | code = -1
51 | value = '请求错误'
52 |
53 | return code, value
54 |
55 | def analyze_all(self, image_path):
56 | results = {}
57 | for type in self.types:
58 | code, value = self.analyze(type, image_path)
59 | if code == 0:
60 | results[type] = value
61 | return {"results": results}
62 |
--------------------------------------------------------------------------------
/utils/face_quality.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | def is_face_forward(landmarks):
5 | """
6 | 判断人脸是否正对相机,并考虑人脸的俯仰角。
7 |
8 | 参数:
9 | - landmarks: 人脸的关键点坐标,假设是一个包含五个关键点(两只眼睛、鼻尖、两只嘴角)的列表。
10 |
11 | 返回:
12 | - is_forward: 布尔值,表示人脸是否正对相机,没有显著的俯仰、偏航或滚动角。
13 | """
14 | # 提取两只眼睛和鼻尖的坐标
15 | eye_left = np.array(landmarks[0])
16 | eye_right = np.array(landmarks[1])
17 | nose = np.array(landmarks[2])
18 | mouth_left = np.array(landmarks[3])
19 | mouth_right = np.array(landmarks[4])
20 |
21 | # 计算中点
22 | eye_center = (eye_left + eye_right) / 2
23 |
24 | # 计算方向向量
25 | direction_vector = eye_right - eye_left
26 |
27 | # 计算单位向量
28 | unit_vector = direction_vector / np.linalg.norm(direction_vector)
29 |
30 | # 计算鼻子到左右眼连线的向量
31 | nose_to_eye_line_vector = nose - eye_left
32 |
33 | # 计算投影长度
34 | projection_length = np.dot(nose_to_eye_line_vector, unit_vector)
35 |
36 | # 计算垂足坐标
37 | foot_of_perpendicular = eye_left + projection_length * unit_vector
38 |
39 | # 计算垂足到中点的距离
40 | foot_offset = np.linalg.norm(foot_of_perpendicular - eye_center)
41 | eye_dist = np.linalg.norm(eye_right - eye_left)
42 |
43 | # 设定偏移量阈值,判断是否为正面
44 | threshold = 0.1 * eye_dist
45 | if foot_offset < threshold:
46 | return True
47 | else:
48 | return False
49 |
50 |
51 | def evaluate_face_quality(box, prob, image, landmarks, quality_threshold=0.8):
52 | """
53 | 根据人脸的大小、置信度和其他因素来评估人脸的质量。
54 | 返回是否通过质量检查。
55 |
56 | 参数:
57 | - box: 人脸框(x1, y1, x2, y2)
58 | - prob: 人脸检测的置信度
59 | - image: 包含人脸的图像(PIL.Image格式)
60 | - landmarks: 人脸的关键点坐标
61 | - quality_threshold: 质量评分的阈值,高于此阈值表示质量足够
62 |
63 | 返回:
64 | - boolean: 表示人脸是否通过质量检查
65 | """
66 | # 基于人脸大小和置信度的简单评分:0-1
67 | face_area = (box[2] - box[0]) * (box[3] - box[1])
68 | size_score = np.sqrt(face_area) / 160 if np.sqrt(face_area) / 160 <= 1 else 1
69 |
70 | # 置信度分数,prob在0到1之间
71 | confidence_score = prob
72 |
73 | # 综合评分
74 | quality_score = size_score * confidence_score
75 |
76 | if quality_score > quality_threshold:
77 | return True
78 | else:
79 | return False
80 |
--------------------------------------------------------------------------------
/business/xunfei/face_compare_client.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import json
3 | from datetime import datetime
4 | from urllib.parse import urlencode
5 |
6 | import requests
7 |
8 | from .config import APP_ID, API_KEY_FACE_COMPARE, API_SECRET_FACE_COMPARE, SERVER_ID_FACE_COMPARE
9 | from .utils import parse_url, generate_signature, assemble_authorization_header, encode_image
10 |
11 |
12 | class FaceCompareClient:
13 | def __init__(self):
14 | self.base_url = f'http://api.xf-yun.com/v1/private/{SERVER_ID_FACE_COMPARE}'
15 |
16 | def generate_request_url(self):
17 | schema, host, path = parse_url(self.base_url)
18 | date = format(datetime.utcnow(), '%a, %d %b %Y %H:%M:%S GMT')
19 | signature_sha = generate_signature(API_SECRET_FACE_COMPARE, host, date, "POST", path)
20 | authorization = assemble_authorization_header(API_KEY_FACE_COMPARE, signature_sha)
21 | values = {"host": host, "date": date, "authorization": authorization}
22 | return f"{self.base_url}?{urlencode(values)}"
23 |
24 | def compare_faces(self, img1_path, img2_path):
25 | code = 0
26 | data = None
27 |
28 | request_url = self.generate_request_url()
29 | headers = {'content-type': "application/json", 'host': 'api.xf-yun.com', 'app_id': APP_ID}
30 |
31 | img1_encoded, img1_type = encode_image(img1_path)
32 | img2_encoded, img2_type = encode_image(img2_path)
33 |
34 | body = json.dumps({
35 | "header": {"app_id": APP_ID, "status": 3},
36 | "parameter": {SERVER_ID_FACE_COMPARE: {"service_kind": "face_compare",
37 | "face_compare_result": {"encoding": "utf8", "compress": "raw",
38 | "format": "json"}}},
39 | "payload": {
40 | "input1": {"encoding": img1_type, "status": 3, "image": img1_encoded},
41 | "input2": {"encoding": img2_type, "status": 3, "image": img2_encoded}
42 | }
43 | })
44 |
45 | response = requests.post(request_url, data=body, headers=headers)
46 | if response.status_code == 200:
47 | result = json.loads(response.text)
48 | code = result['header']['code']
49 | if code == 0:
50 | compare_result = json.loads(base64.b64decode(result['payload']['face_compare_result']['text']))
51 | code = compare_result['ret']
52 | if code == 0:
53 | data = compare_result['score']
54 | else:
55 | data = '非人像图片'
56 | else:
57 | data = result['header']['message']
58 | else:
59 | code = -1
60 | data = '请求错误'
61 |
62 | return code, data
63 |
--------------------------------------------------------------------------------
/services/recognition.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | from utils.face_detection import find_faces, align_face
4 | from utils.face_encoding import encode_face
5 | from utils.face_quality import is_face_forward, evaluate_face_quality
6 | from utils.face_storage import FaceStorage
7 |
8 | face_storage = FaceStorage()
9 | last_faces = []
10 | last_face_boxes = []
11 |
12 |
13 | def calculate_distance(box1, box2):
14 | center1 = ((box1[0] + box1[2]) / 2, (box1[1] + box1[3]) / 2)
15 | center2 = ((box2[0] + box2[2]) / 2, (box2[1] + box2[3]) / 2)
16 | distance = np.sqrt((center1[0] - center2[0]) ** 2 + (center1[1] - center2[1]) ** 2)
17 | return distance
18 |
19 |
20 | def has_new_face(face_boxes, threshold=50):
21 | global last_face_boxes, last_faces
22 | if len(face_boxes) == 0:
23 | return False
24 | # 如果当前帧和上一帧检测到的人脸数量不同,则认为有新的人脸出现
25 | if len(face_boxes) != len(last_face_boxes):
26 | return True
27 | else:
28 | # 计算当前帧与上一帧中人脸位置的最小距离
29 | for box in face_boxes:
30 | is_far = True
31 | for last_box in last_face_boxes:
32 | distance = calculate_distance(box, last_box)
33 | # 如果当前人脸与上一帧中所有人脸的最小距离超过阈值,则认为是新的人脸
34 | if distance <= threshold:
35 | is_far = False
36 | break
37 | if is_far:
38 | return True
39 |
40 | return False
41 |
42 |
43 | def recognize_faces(image):
44 | global last_face_boxes, last_faces
45 | boxes, probs, landmarks = find_faces(image)
46 |
47 | faces = []
48 | if has_new_face(boxes) or any(face['name'] == "忽略" for face in last_faces):
49 | for box, prob, landmark in zip(boxes, probs, landmarks):
50 | is_forward = is_face_forward(landmark)
51 | face_quality_ok = evaluate_face_quality(box, prob, image, landmark)
52 |
53 | if is_forward and face_quality_ok:
54 | aligned_face = align_face(image, box, landmark)
55 | face_encoding = encode_face(aligned_face)
56 | face = face_storage.match_face(face_encoding)
57 | if face is None:
58 | face = face_storage.add_known_face(face_encoding, "未知")
59 | else:
60 | face = {'id': None, 'name': "忽略"}
61 |
62 | faces.append(face)
63 | else:
64 | faces = last_faces
65 |
66 | last_face_boxes = boxes
67 | last_faces = faces
68 |
69 | # 构建识别结果,包括未识别和被忽略的人脸
70 | recognized_faces = []
71 | for face, (left, top, right, bottom), prob, landmark in zip(faces, boxes, probs, landmarks):
72 | face_id = face['id']
73 | name = face['name']
74 | location = (top, right, bottom, left)
75 | recognized_faces.append({
76 | 'id': face_id,
77 | 'location': location,
78 | 'name': name,
79 | 'prob': prob,
80 | 'landmark': landmark.tolist()
81 | })
82 |
83 | return recognized_faces
84 |
85 |
86 | def rename_face(face_id, name):
87 | face_storage.rename_face(face_id, name)
88 |
--------------------------------------------------------------------------------
/business/xunfei/spark.py:
--------------------------------------------------------------------------------
1 | import base64
2 | import hashlib
3 | import hmac
4 | import json
5 | import ssl
6 | from datetime import datetime
7 | from time import mktime
8 | from urllib.parse import urlencode, urlparse
9 | from wsgiref.handlers import format_date_time
10 |
11 | import websocket
12 |
13 | from .config import APP_ID, API_KEY_SPARK, API_SECRET_SPARK
14 |
15 |
16 | class SparkAPI:
17 | def __init__(self, app_id: str = APP_ID, api_key: str = API_KEY_SPARK, api_secret: str = API_SECRET_SPARK,
18 | service_url: str = "wss://spark-api.xf-yun.com/v3.5/chat"):
19 | self.app_id = app_id
20 | self.api_key = api_key
21 | self.api_secret = api_secret
22 | self.host = urlparse(service_url).netloc
23 | self.path = urlparse(service_url).path
24 | self.service_url = service_url
25 | self.domain = self._get_model_domain(self.path)
26 |
27 | def _get_model_domain(self, path: str) -> str:
28 | domain_map = {
29 | "/v1.1/chat": "general",
30 | "/v2.1/chat": "generalv2",
31 | "/v3.1/chat": "generalv3",
32 | "/v3.5/chat": "generalv3.5",
33 | }
34 | return domain_map.get(path, "unknown")
35 |
36 | def generate_auth_url(self) -> str:
37 | timestamp = datetime.now()
38 | formatted_date = format_date_time(mktime(timestamp.timetuple()))
39 | signature = self._create_signature(formatted_date)
40 | authorization_origin = f'api_key="{self.api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature}"'
41 | authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode('utf-8')
42 | url_params = {"authorization": authorization, "date": formatted_date, "host": self.host}
43 | return f"{self.service_url}?{urlencode(url_params)}"
44 |
45 | def _create_signature(self, date: str) -> str:
46 | signature_origin = f"host: {self.host}\ndate: {date}\nGET {self.path} HTTP/1.1"
47 | signature_sha = hmac.new(self.api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
48 | hashlib.sha256).digest()
49 | return base64.b64encode(signature_sha).decode('utf-8')
50 |
51 | def connect_and_query(self, on_message, messages: list):
52 | url = self.generate_auth_url()
53 | websocket.enableTrace(False)
54 | ws = websocket.WebSocketApp(url,
55 | on_message=lambda ws, msg: self.on_message(on_message, msg),
56 | on_error=self.on_error,
57 | on_close=self.on_close,
58 | on_open=lambda ws: self.on_open(ws, messages))
59 | ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
60 |
61 | def on_message(self, on_message, message: str):
62 | data = json.loads(message)
63 | on_message(data)
64 |
65 | def on_error(self, ws, error):
66 | print(f"WebSocket error: {error}")
67 |
68 | def on_close(self, ws, close_status_code, close_msg):
69 | print("WebSocket closed")
70 |
71 | def on_open(self, ws, messages):
72 | data = {
73 | "header": {
74 | "app_id": self.app_id,
75 | "uid": "1234"
76 | },
77 | "parameter": {
78 | "chat": {
79 | "domain": self.domain,
80 | "temperature": 0.5,
81 | "max_tokens": 4096,
82 | "top_k": 5,
83 | "auditing": "default"
84 | }
85 | },
86 | "payload": {
87 | "message": {
88 | "text": messages
89 | }
90 | }
91 | }
92 | ws.send(json.dumps(data))
93 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Python template
3 | # Byte-compiled / optimized / DLL files
4 | __pycache__/
5 | *.py[cod]
6 | *$py.class
7 |
8 | # C extensions
9 | *.so
10 |
11 | # Distribution / packaging
12 | .Python
13 | env/
14 | build/
15 | develop-eggs/
16 | dist/
17 | downloads/
18 | eggs/
19 | .eggs/
20 | lib/
21 | lib64/
22 | parts/
23 | sdist/
24 | var/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .coverage
43 | .coverage.*
44 | .cache
45 | nosetests.xml
46 | coverage.xml
47 | *,cover
48 | .hypothesis/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 |
58 | # Flask stuff:
59 | instance/
60 | .webassets-cache
61 |
62 | # Scrapy stuff:
63 | .scrapy
64 |
65 | # Sphinx documentation
66 | docs/_build/
67 |
68 | # PyBuilder
69 | target/
70 |
71 | # IPython Notebook
72 | .ipynb_checkpoints
73 |
74 | # pyenv
75 | .python-version
76 |
77 | # celery beat schedule file
78 | celerybeat-schedule
79 |
80 | # dotenv
81 | .env
82 |
83 | # virtualenv
84 | venv/
85 | ENV/
86 |
87 | # Spyder project settings
88 | .spyderproject
89 |
90 | # Rope project settings
91 | .ropeproject
92 | ### VirtualEnv template
93 | # Virtualenv
94 | # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
95 | [Bb]in
96 | [Ii]nclude
97 | [Ll]ib
98 | [Ll]ib64
99 | [Ll]ocal
100 | [Ss]cripts
101 | pyvenv.cfg
102 | .venv
103 | pip-selfcheck.json
104 |
105 | ### JetBrains template
106 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
107 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
108 |
109 | # User-specific stuff
110 | .idea/**/workspace.xml
111 | .idea/**/tasks.xml
112 | .idea/**/usage.statistics.xml
113 | .idea/**/dictionaries
114 | .idea/**/shelf
115 |
116 | # AWS User-specific
117 | .idea/**/aws.xml
118 |
119 | # Generated files
120 | .idea/**/contentModel.xml
121 |
122 | # Sensitive or high-churn files
123 | .idea/**/dataSources/
124 | .idea/**/dataSources.ids
125 | .idea/**/dataSources.local.xml
126 | .idea/**/sqlDataSources.xml
127 | .idea/**/dynamic.xml
128 | .idea/**/uiDesigner.xml
129 | .idea/**/dbnavigator.xml
130 |
131 | # Gradle
132 | .idea/**/gradle.xml
133 | .idea/**/libraries
134 |
135 | # Gradle and Maven with auto-import
136 | # When using Gradle or Maven with auto-import, you should exclude module files,
137 | # since they will be recreated, and may cause churn. Uncomment if using
138 | # auto-import.
139 | # .idea/artifacts
140 | # .idea/compiler.xml
141 | # .idea/jarRepositories.xml
142 | # .idea/modules.xml
143 | # .idea/*.iml
144 | # .idea/modules
145 | # *.iml
146 | # *.ipr
147 |
148 | # CMake
149 | cmake-build-*/
150 |
151 | # Mongo Explorer plugin
152 | .idea/**/mongoSettings.xml
153 |
154 | # File-based project format
155 | *.iws
156 |
157 | # IntelliJ
158 | out/
159 |
160 | # mpeltonen/sbt-idea plugin
161 | .idea_modules/
162 |
163 | # JIRA plugin
164 | atlassian-ide-plugin.xml
165 |
166 | # Cursive Clojure plugin
167 | .idea/replstate.xml
168 |
169 | # SonarLint plugin
170 | .idea/sonarlint/
171 |
172 | # Crashlytics plugin (for Android Studio and IntelliJ)
173 | com_crashlytics_export_strings.xml
174 | crashlytics.properties
175 | crashlytics-build.properties
176 | fabric.properties
177 |
178 | # Editor-based Rest Client
179 | .idea/httpRequests
180 |
181 | # Android studio 3.1+ serialized cache file
182 | .idea/caches/build_file_checksums.ser
183 |
184 | # idea folder, uncomment if you don't need it
185 | # .idea
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
1 | import os
2 | import tempfile
3 | import uuid
4 |
5 | from flask import Flask, request, session
6 | from flask import jsonify
7 | from flask_cors import CORS
8 | from flask_socketio import SocketIO, Namespace, emit, disconnect
9 |
10 | from business.xunfei import FaceCompareClient, FaceFeatureClient, SparkAPI
11 | from services.authentication import authenticate_face
12 | from services.recognition import recognize_faces, rename_face
13 | from services.registration import register_face
14 | from utils.face_detection import find_primary_face
15 | from utils.face_quality import is_face_forward
16 | from utils.image_processing import parse_frame_data
17 |
18 | # Set this variable to "threading", "eventlet" or "gevent" to test the
19 | # different async modes, or leave it set to None for the application to choose
20 | # the best option based on installed packages.
21 | async_mode = None
22 |
23 | app = Flask(__name__)
24 | CORS(app)
25 | socketio = SocketIO(app, cors_allowed_origins="*")
26 |
27 | # 配置上传文件夹和允许的扩展
28 | UPLOAD_FOLDER = 'static/uploads'
29 | ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'bmp'}
30 | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
31 |
32 |
33 | # Utility function to check allowed file
34 | def allowed_file(filename):
35 | return '.' in filename and \
36 | filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
37 |
38 |
39 | # Utility function to generate a secure filename
40 | def secure_filename(filename):
41 | # 使用UUID或其他方法生成唯一的文件名
42 | unique_filename = str(uuid.uuid4())
43 | ext = filename.rsplit('.', 1)[1].lower() if '.' in filename else ''
44 | safe_filename = f"{unique_filename}.{ext}" if ext else unique_filename
45 | return safe_filename
46 |
47 |
48 | # 讯飞API - 人脸比对
49 | @app.route('/api/xunfei/face-compare', methods=['POST'])
50 | def face_compare():
51 | # 检查是否上传了两个文件
52 | if 'image1' not in request.files or 'image2' not in request.files:
53 | return jsonify({'error': '缺少文件参数'}), 400
54 | file1 = request.files['image1']
55 | file2 = request.files['image2']
56 | if file1.filename == '' or file2.filename == '':
57 | return jsonify({'error': '未选择文件'}), 400
58 | elif not allowed_file(file1.filename) or not allowed_file(file2.filename):
59 | return jsonify({'error': '文件类型不正确'}), 400
60 |
61 | # 使用临时文件
62 | with tempfile.TemporaryDirectory() as tmpdirname:
63 | filepath1 = os.path.join(tmpdirname, secure_filename(file1.filename))
64 | filepath2 = os.path.join(tmpdirname, secure_filename(file2.filename))
65 |
66 | file1.save(filepath1)
67 | file2.save(filepath2)
68 |
69 | # 调用人脸比对服务
70 | client = FaceCompareClient()
71 | code, data = client.compare_faces(filepath1, filepath2)
72 |
73 | if code == 0:
74 | return jsonify({'message': '比对成功', 'data': data}), 200
75 | else:
76 | return jsonify({'error': data}), 400
77 |
78 |
79 | # 讯飞API - 人脸特征分析
80 | @app.route('/api/xunfei/face-features', methods=['POST'])
81 | def face_features():
82 | if 'image' not in request.files:
83 | return jsonify({'error': '缺少文件参数'}), 400
84 | file = request.files['image']
85 | if file.filename == '':
86 | return jsonify({'error': '未选择文件或文件类型不正确'}), 400
87 | elif not allowed_file(file.filename):
88 | return jsonify({'error': '文件类型不正确'}), 400
89 |
90 | # 使用临时文件
91 | with tempfile.NamedTemporaryFile(delete=False) as tmpfile:
92 | file.save(tmpfile.name)
93 | # 分析人脸特征
94 | client = FaceFeatureClient()
95 | result = client.analyze_all(tmpfile.name)
96 |
97 | # 清理临时文件
98 | os.remove(tmpfile.name)
99 | return jsonify(result)
100 |
101 |
102 | # 人脸认证的命名空间
103 | class FaceAuthNamespace(Namespace):
104 | def on_connect(self):
105 | print("Client connected to Face Auth")
106 |
107 | def on_disconnect(self):
108 | print("Client disconnected from Face Auth")
109 |
110 | def on_frame(self, data):
111 | image_data = data['image']
112 | timestamp = data['timestamp']
113 | if image_data.endswith('data:,'):
114 | print('empty frame data')
115 | return
116 | image = parse_frame_data(image_data)
117 |
118 | primary_face = find_primary_face(image)
119 | if primary_face:
120 | box, prob, landmark = primary_face
121 |
122 | if is_face_forward(landmark):
123 | left, top, right, bottom = box
124 | location = (top, right, bottom, left)
125 | result = {'success': True, 'face': {'location': location, 'landmark': landmark.tolist()},
126 | 'timestamp': timestamp}
127 | else:
128 | result = {'success': False, 'message': "人脸质量不符合要求或非正脸", 'timestamp': timestamp}
129 | else:
130 | result = {'success': False, 'message': "未检测到人脸", 'timestamp': timestamp}
131 |
132 | emit('detection_result', result)
133 |
134 | def on_register(self, data):
135 | """
136 | 处理用户注册事件。
137 | """
138 | image_data = data['image']
139 | username = data['username']
140 | if image_data.endswith('data:,'):
141 | result = {'success': False, 'message': "帧数据为空"}
142 | else:
143 | image = parse_frame_data(image_data)
144 | success, message = register_face(image, username)
145 | result = {'success': success, 'message': message}
146 |
147 | emit('register_response', result)
148 |
149 | def on_login(self, data):
150 | """
151 | 处理用户登录事件。
152 | """
153 | image_data = data['image']
154 | if image_data.endswith('data:,'):
155 | print('Empty frame data')
156 | result = {'success': False, 'message': "帧数据为空"}
157 | else:
158 | image = parse_frame_data(image_data)
159 | success, message = authenticate_face(image)
160 | result = {'success': success, 'message': message}
161 |
162 | emit('login_response', result)
163 |
164 |
165 | # 实时人脸识别的命名空间
166 | class FaceRecognitionNamespace(Namespace):
167 |
168 | def on_disconnect_request(self):
169 | emit('my_response',
170 | {'data': 'Disconnected!', 'count': session['receive_count']})
171 | disconnect()
172 |
173 | # WebSocket事件处理,接收视频帧
174 | def on_frame(self, data):
175 | image_data = data['image']
176 | timestamp = data['timestamp']
177 | if image_data.endswith('data:,'):
178 | print('empty frame data')
179 | return
180 | image = parse_frame_data(image_data)
181 |
182 | # 在这里调用你的人脸检测逻辑
183 | faces = recognize_faces(image)
184 | emit('detection_results', {'faces': faces, 'timestamp': timestamp})
185 |
186 | def on_rename_face(self, data):
187 | # TODO: 增加对重命名结果的处理
188 | face_id = data['id']
189 | name = data['name']
190 | rename_face(face_id, name)
191 |
192 | def on_connect(self):
193 | print("Client connected to Face Recognition")
194 |
195 | def on_disconnect(self):
196 | print('Client disconnected from Face Recognition', request.sid)
197 |
198 |
199 | class ChatNamespace(Namespace):
200 |
201 | def on_connect(self):
202 | print("Client connected to Chat")
203 |
204 | def on_disconnect(self):
205 | print('Client disconnected from Chat', request.sid)
206 |
207 | def on_send_message(self, data):
208 | messages = data['messages']
209 | spark_api = SparkAPI()
210 | spark_api.connect_and_query(self.on_response, messages)
211 | return jsonify({"status": "connecting"})
212 |
213 | def on_response(self, data):
214 | if data['header']['code'] != 0:
215 | print(data['header']['code'])
216 | emit('error', {'error': f"Error from API: {data['header']['code']}"})
217 | else:
218 | choices = data["payload"]['choices']
219 | status = choices['status']
220 | seq = choices['seq']
221 | text = choices['text'][0]
222 | emit('message_response', {
223 | 'status': status,
224 | 'seq': seq,
225 | 'text': {
226 | 'role': text['role'],
227 | 'content': text['content']
228 | }
229 | })
230 |
231 |
232 | # 注册命名空间
233 | socketio.on_namespace(FaceAuthNamespace('/api/face-auth'))
234 | socketio.on_namespace(FaceRecognitionNamespace('/api/face-recognition'))
235 |
236 | socketio.on_namespace(ChatNamespace('/api/chat'))
237 |
238 | if __name__ == '__main__':
239 | socketio.run(app, debug=True, allow_unsafe_werkzeug=True)
240 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
35 |
36 |
37 |
38 |
39 | {
40 | "lastFilter": {
41 | "state": "OPEN",
42 | "assignee": "p0ise"
43 | }
44 | }
45 | {
46 | "selectedUrlAndAccountId": {
47 | "url": "https://github.com/p0ise/iflyface-backend.git",
48 | "accountId": "1410cdc2-b2ba-469b-ae38-28d431d2598e"
49 | }
50 | }
51 | {
52 | "associatedIndex": 7
53 | }
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | {
63 | "keyToString": {
64 | "DefaultHtmlFileTemplate": "HTML File",
65 | "Flask 服务器.Flask (hello.py).executor": "Run",
66 | "Flask 服务器.iflyface.executor": "Run",
67 | "Python.app.executor": "Run",
68 | "Python.face_recognition.executor": "Run",
69 | "Python.spark.executor": "Run",
70 | "Python.sparkdemo.executor": "Run",
71 | "RunOnceActivity.OpenProjectViewOnStart": "true",
72 | "RunOnceActivity.ShowReadmeOnStart": "true",
73 | "SHARE_PROJECT_CONFIGURATION_FILES": "true",
74 | "git-widget-placeholder": "master",
75 | "ignore.virus.scanning.warn.message": "true",
76 | "last_opened_file_path": "C:/Users/ADMIN/PycharmProjects/iflyface-backend",
77 | "node.js.detected.package.eslint": "true",
78 | "node.js.detected.package.tslint": "true",
79 | "node.js.selected.package.eslint": "(autodetect)",
80 | "node.js.selected.package.tslint": "(autodetect)",
81 | "nodejs_package_manager_path": "npm",
82 | "settings.editor.selected.configurable": "com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable",
83 | "vue.rearranger.settings.migration": "true"
84 | }
85 | }
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 | 1711421904128
179 |
180 |
181 | 1711421904128
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 | 1711441519336
201 |
202 |
203 |
204 | 1711441519337
205 |
206 |
207 |
208 | 1711454004665
209 |
210 |
211 |
212 | 1711454004665
213 |
214 |
215 |
216 | 1711510214759
217 |
218 |
219 |
220 | 1711510214759
221 |
222 |
223 |
224 | 1711510311732
225 |
226 |
227 |
228 | 1711510311732
229 |
230 |
231 |
232 | 1711510330561
233 |
234 |
235 |
236 | 1711510330561
237 |
238 |
239 |
240 | 1711590145679
241 |
242 |
243 |
244 | 1711590145679
245 |
246 |
247 |
248 | 1711590286932
249 |
250 |
251 |
252 | 1711590286932
253 |
254 |
255 |
256 | 1711590597671
257 |
258 |
259 |
260 | 1711590597671
261 |
262 |
263 |
264 | 1711590829881
265 |
266 |
267 |
268 | 1711590829881
269 |
270 |
271 |
272 | 1711593136117
273 |
274 |
275 |
276 | 1711593136117
277 |
278 |
279 |
280 | 1712132073828
281 |
282 |
283 |
284 | 1712132073828
285 |
286 |
287 |
288 | 1712669125321
289 |
290 |
291 |
292 | 1712669125321
293 |
294 |
295 |
296 | 1712669454753
297 |
298 |
299 |
300 | 1712669454753
301 |
302 |
303 |
304 | 1712740097757
305 |
306 |
307 |
308 | 1712740097757
309 |
310 |
311 |
312 | 1712817583332
313 |
314 |
315 |
316 | 1712817583332
317 |
318 |
319 |
320 | 1712818305452
321 |
322 |
323 |
324 | 1712818305452
325 |
326 |
327 |
328 | 1712830465973
329 |
330 |
331 |
332 | 1712830465973
333 |
334 |
335 |
336 | 1712830511653
337 |
338 |
339 |
340 | 1712830511653
341 |
342 |
343 |
344 | 1712850404800
345 |
346 |
347 |
348 | 1712850404800
349 |
350 |
351 |
352 | 1712850569044
353 |
354 |
355 |
356 | 1712850569044
357 |
358 |
359 |
360 | 1712869635423
361 |
362 |
363 |
364 | 1712869635423
365 |
366 |
367 |
368 | 1712869699723
369 |
370 |
371 |
372 | 1712869699723
373 |
374 |
375 |
376 | 1712869730458
377 |
378 |
379 |
380 | 1712869730458
381 |
382 |
383 |
384 | 1712869744915
385 |
386 |
387 |
388 | 1712869744915
389 |
390 |
391 |
392 | 1713323256766
393 |
394 |
395 |
396 | 1713323256766
397 |
398 |
399 |
400 | 1713323328040
401 |
402 |
403 |
404 | 1713323328040
405 |
406 |
407 |
408 | 1713400385116
409 |
410 |
411 |
412 | 1713400385117
413 |
414 |
415 |
416 | 1713400640524
417 |
418 |
419 |
420 | 1713400640524
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
--------------------------------------------------------------------------------
/poetry.lock:
--------------------------------------------------------------------------------
1 | [[package]]
2 | name = "bidict"
3 | version = "0.23.1"
4 | description = "The bidirectional mapping library for Python."
5 | category = "main"
6 | optional = false
7 | python-versions = ">=3.8"
8 |
9 | [[package]]
10 | name = "blinker"
11 | version = "1.7.0"
12 | description = "Fast, simple object-to-object and broadcast signaling"
13 | category = "main"
14 | optional = false
15 | python-versions = ">=3.8"
16 |
17 | [[package]]
18 | name = "certifi"
19 | version = "2024.2.2"
20 | description = "Python package for providing Mozilla's CA Bundle."
21 | category = "main"
22 | optional = false
23 | python-versions = ">=3.6"
24 |
25 | [[package]]
26 | name = "charset-normalizer"
27 | version = "3.3.2"
28 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
29 | category = "main"
30 | optional = false
31 | python-versions = ">=3.7.0"
32 |
33 | [[package]]
34 | name = "click"
35 | version = "8.1.7"
36 | description = "Composable command line interface toolkit"
37 | category = "main"
38 | optional = false
39 | python-versions = ">=3.7"
40 |
41 | [package.dependencies]
42 | colorama = { version = "*", markers = "platform_system == \"Windows\"" }
43 |
44 | [[package]]
45 | name = "colorama"
46 | version = "0.4.6"
47 | description = "Cross-platform colored terminal text."
48 | category = "main"
49 | optional = false
50 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
51 |
52 | [[package]]
53 | name = "facenet-pytorch"
54 | version = "2.5.3"
55 | description = "Pretrained Pytorch face detection and recognition models"
56 | category = "main"
57 | optional = false
58 | python-versions = "*"
59 |
60 | [package.dependencies]
61 | numpy = "*"
62 | pillow = "*"
63 | requests = "*"
64 | torchvision = "*"
65 |
66 | [[package]]
67 | name = "filelock"
68 | version = "3.13.3"
69 | description = "A platform independent file lock."
70 | category = "main"
71 | optional = false
72 | python-versions = ">=3.8"
73 |
74 | [package.extras]
75 | docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"]
76 | testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"]
77 | typing = ["typing-extensions (>=4.8)"]
78 |
79 | [[package]]
80 | name = "flask"
81 | version = "3.0.3"
82 | description = "A simple framework for building complex web applications."
83 | category = "main"
84 | optional = false
85 | python-versions = ">=3.8"
86 |
87 | [package.dependencies]
88 | blinker = ">=1.6.2"
89 | click = ">=8.1.3"
90 | itsdangerous = ">=2.1.2"
91 | Jinja2 = ">=3.1.2"
92 | Werkzeug = ">=3.0.0"
93 |
94 | [package.extras]
95 | async = ["asgiref (>=3.2)"]
96 | dotenv = ["python-dotenv"]
97 |
98 | [[package]]
99 | name = "flask-cors"
100 | version = "4.0.0"
101 | description = "A Flask extension adding a decorator for CORS support"
102 | category = "main"
103 | optional = false
104 | python-versions = "*"
105 |
106 | [package.dependencies]
107 | Flask = ">=0.9"
108 |
109 | [[package]]
110 | name = "flask-socketio"
111 | version = "5.3.6"
112 | description = "Socket.IO integration for Flask applications"
113 | category = "main"
114 | optional = false
115 | python-versions = ">=3.6"
116 |
117 | [package.dependencies]
118 | Flask = ">=0.9"
119 | python-socketio = ">=5.0.2"
120 |
121 | [package.extras]
122 | docs = ["sphinx"]
123 |
124 | [[package]]
125 | name = "fsspec"
126 | version = "2024.3.1"
127 | description = "File-system specification"
128 | category = "main"
129 | optional = false
130 | python-versions = ">=3.8"
131 |
132 | [package.extras]
133 | abfs = ["adlfs"]
134 | adl = ["adlfs"]
135 | arrow = ["pyarrow (>=1)"]
136 | dask = ["dask", "distributed"]
137 | devel = ["pytest", "pytest-cov"]
138 | dropbox = ["dropbox", "dropboxdrivefs", "requests"]
139 | full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"]
140 | fuse = ["fusepy"]
141 | gcs = ["gcsfs"]
142 | git = ["pygit2"]
143 | github = ["requests"]
144 | gs = ["gcsfs"]
145 | gui = ["panel"]
146 | hdfs = ["pyarrow (>=1)"]
147 | http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"]
148 | libarchive = ["libarchive-c"]
149 | oci = ["ocifs"]
150 | s3 = ["s3fs"]
151 | sftp = ["paramiko"]
152 | smb = ["smbprotocol"]
153 | ssh = ["paramiko"]
154 | tqdm = ["tqdm"]
155 |
156 | [[package]]
157 | name = "h11"
158 | version = "0.14.0"
159 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
160 | category = "main"
161 | optional = false
162 | python-versions = ">=3.7"
163 |
164 | [[package]]
165 | name = "idna"
166 | version = "3.6"
167 | description = "Internationalized Domain Names in Applications (IDNA)"
168 | category = "main"
169 | optional = false
170 | python-versions = ">=3.5"
171 |
172 | [[package]]
173 | name = "itsdangerous"
174 | version = "2.1.2"
175 | description = "Safely pass data to untrusted environments and back."
176 | category = "main"
177 | optional = false
178 | python-versions = ">=3.7"
179 |
180 | [[package]]
181 | name = "jinja2"
182 | version = "3.1.3"
183 | description = "A very fast and expressive template engine."
184 | category = "main"
185 | optional = false
186 | python-versions = ">=3.7"
187 |
188 | [package.dependencies]
189 | MarkupSafe = ">=2.0"
190 |
191 | [package.extras]
192 | i18n = ["Babel (>=2.7)"]
193 |
194 | [[package]]
195 | name = "markupsafe"
196 | version = "2.1.5"
197 | description = "Safely add untrusted strings to HTML/XML markup."
198 | category = "main"
199 | optional = false
200 | python-versions = ">=3.7"
201 |
202 | [[package]]
203 | name = "mpmath"
204 | version = "1.3.0"
205 | description = "Python library for arbitrary-precision floating-point arithmetic"
206 | category = "main"
207 | optional = false
208 | python-versions = "*"
209 |
210 | [package.extras]
211 | develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"]
212 | docs = ["sphinx"]
213 | gmpy = ["gmpy2 (>=2.1.0a4)"]
214 | tests = ["pytest (>=4.6)"]
215 |
216 | [[package]]
217 | name = "networkx"
218 | version = "3.3"
219 | description = "Python package for creating and manipulating graphs and networks"
220 | category = "main"
221 | optional = false
222 | python-versions = ">=3.10"
223 |
224 | [package.extras]
225 | default = ["matplotlib (>=3.6)", "numpy (>=1.23)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"]
226 | developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"]
227 | doc = ["myst-nb (>=1.0)", "numpydoc (>=1.7)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"]
228 | extra = ["lxml (>=4.6)", "pydot (>=2.0)", "pygraphviz (>=1.12)", "sympy (>=1.10)"]
229 | test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"]
230 |
231 | [[package]]
232 | name = "numpy"
233 | version = "1.26.4"
234 | description = "Fundamental package for array computing in Python"
235 | category = "main"
236 | optional = false
237 | python-versions = ">=3.9"
238 |
239 | [[package]]
240 | name = "nvidia-cublas-cu12"
241 | version = "12.1.3.1"
242 | description = "CUBLAS native runtime libraries"
243 | category = "main"
244 | optional = false
245 | python-versions = ">=3"
246 |
247 | [[package]]
248 | name = "nvidia-cuda-cupti-cu12"
249 | version = "12.1.105"
250 | description = "CUDA profiling tools runtime libs."
251 | category = "main"
252 | optional = false
253 | python-versions = ">=3"
254 |
255 | [[package]]
256 | name = "nvidia-cuda-nvrtc-cu12"
257 | version = "12.1.105"
258 | description = "NVRTC native runtime libraries"
259 | category = "main"
260 | optional = false
261 | python-versions = ">=3"
262 |
263 | [[package]]
264 | name = "nvidia-cuda-runtime-cu12"
265 | version = "12.1.105"
266 | description = "CUDA Runtime native Libraries"
267 | category = "main"
268 | optional = false
269 | python-versions = ">=3"
270 |
271 | [[package]]
272 | name = "nvidia-cudnn-cu12"
273 | version = "8.9.2.26"
274 | description = "cuDNN runtime libraries"
275 | category = "main"
276 | optional = false
277 | python-versions = ">=3"
278 |
279 | [package.dependencies]
280 | nvidia-cublas-cu12 = "*"
281 |
282 | [[package]]
283 | name = "nvidia-cufft-cu12"
284 | version = "11.0.2.54"
285 | description = "CUFFT native runtime libraries"
286 | category = "main"
287 | optional = false
288 | python-versions = ">=3"
289 |
290 | [[package]]
291 | name = "nvidia-curand-cu12"
292 | version = "10.3.2.106"
293 | description = "CURAND native runtime libraries"
294 | category = "main"
295 | optional = false
296 | python-versions = ">=3"
297 |
298 | [[package]]
299 | name = "nvidia-cusolver-cu12"
300 | version = "11.4.5.107"
301 | description = "CUDA solver native runtime libraries"
302 | category = "main"
303 | optional = false
304 | python-versions = ">=3"
305 |
306 | [package.dependencies]
307 | nvidia-cublas-cu12 = "*"
308 | nvidia-cusparse-cu12 = "*"
309 | nvidia-nvjitlink-cu12 = "*"
310 |
311 | [[package]]
312 | name = "nvidia-cusparse-cu12"
313 | version = "12.1.0.106"
314 | description = "CUSPARSE native runtime libraries"
315 | category = "main"
316 | optional = false
317 | python-versions = ">=3"
318 |
319 | [package.dependencies]
320 | nvidia-nvjitlink-cu12 = "*"
321 |
322 | [[package]]
323 | name = "nvidia-nccl-cu12"
324 | version = "2.19.3"
325 | description = "NVIDIA Collective Communication Library (NCCL) Runtime"
326 | category = "main"
327 | optional = false
328 | python-versions = ">=3"
329 |
330 | [[package]]
331 | name = "nvidia-nvjitlink-cu12"
332 | version = "12.4.127"
333 | description = "Nvidia JIT LTO Library"
334 | category = "main"
335 | optional = false
336 | python-versions = ">=3"
337 |
338 | [[package]]
339 | name = "nvidia-nvtx-cu12"
340 | version = "12.1.105"
341 | description = "NVIDIA Tools Extension"
342 | category = "main"
343 | optional = false
344 | python-versions = ">=3"
345 |
346 | [[package]]
347 | name = "opencv-python"
348 | version = "4.9.0.80"
349 | description = "Wrapper package for OpenCV python bindings."
350 | category = "main"
351 | optional = false
352 | python-versions = ">=3.6"
353 |
354 | [package.dependencies]
355 | numpy = [
356 | { version = ">=1.21.2", markers = "python_version >= \"3.10\"" },
357 | { version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\"" },
358 | { version = ">=1.23.5", markers = "python_version >= \"3.11\"" },
359 | { version = ">=1.26.0", markers = "python_version >= \"3.12\"" },
360 | { version = ">=1.19.3", markers = "python_version >= \"3.6\" and platform_system == \"Linux\" and platform_machine == \"aarch64\" or python_version >= \"3.9\"" },
361 | { version = ">=1.17.0", markers = "python_version >= \"3.7\"" },
362 | { version = ">=1.17.3", markers = "python_version >= \"3.8\"" },
363 | ]
364 |
365 | [[package]]
366 | name = "pillow"
367 | version = "10.3.0"
368 | description = "Python Imaging Library (Fork)"
369 | category = "main"
370 | optional = false
371 | python-versions = ">=3.8"
372 |
373 | [package.extras]
374 | docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"]
375 | fpx = ["olefile"]
376 | mic = ["olefile"]
377 | tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"]
378 | typing = ["typing-extensions"]
379 | xmp = ["defusedxml"]
380 |
381 | [[package]]
382 | name = "python-engineio"
383 | version = "4.9.0"
384 | description = "Engine.IO server and client for Python"
385 | category = "main"
386 | optional = false
387 | python-versions = ">=3.6"
388 |
389 | [package.dependencies]
390 | simple-websocket = ">=0.10.0"
391 |
392 | [package.extras]
393 | asyncio-client = ["aiohttp (>=3.4)"]
394 | client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
395 | docs = ["sphinx"]
396 |
397 | [[package]]
398 | name = "python-socketio"
399 | version = "5.11.2"
400 | description = "Socket.IO server and client for Python"
401 | category = "main"
402 | optional = false
403 | python-versions = ">=3.8"
404 |
405 | [package.dependencies]
406 | bidict = ">=0.21.0"
407 | python-engineio = ">=4.8.0"
408 |
409 | [package.extras]
410 | asyncio-client = ["aiohttp (>=3.4)"]
411 | client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
412 | docs = ["sphinx"]
413 |
414 | [[package]]
415 | name = "requests"
416 | version = "2.31.0"
417 | description = "Python HTTP for Humans."
418 | category = "main"
419 | optional = false
420 | python-versions = ">=3.7"
421 |
422 | [package.dependencies]
423 | certifi = ">=2017.4.17"
424 | charset-normalizer = ">=2,<4"
425 | idna = ">=2.5,<4"
426 | urllib3 = ">=1.21.1,<3"
427 |
428 | [package.extras]
429 | socks = ["PySocks (>=1.5.6,!=1.5.7)"]
430 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
431 |
432 | [[package]]
433 | name = "simple-websocket"
434 | version = "1.0.0"
435 | description = "Simple WebSocket server and client for Python"
436 | category = "main"
437 | optional = false
438 | python-versions = ">=3.6"
439 |
440 | [package.dependencies]
441 | wsproto = "*"
442 |
443 | [package.extras]
444 | docs = ["sphinx"]
445 |
446 | [[package]]
447 | name = "sympy"
448 | version = "1.12"
449 | description = "Computer algebra system (CAS) in Python"
450 | category = "main"
451 | optional = false
452 | python-versions = ">=3.8"
453 |
454 | [package.dependencies]
455 | mpmath = ">=0.19"
456 |
457 | [[package]]
458 | name = "torch"
459 | version = "2.2.2"
460 | description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration"
461 | category = "main"
462 | optional = false
463 | python-versions = ">=3.8.0"
464 |
465 | [package.dependencies]
466 | filelock = "*"
467 | fsspec = "*"
468 | jinja2 = "*"
469 | networkx = "*"
470 | nvidia-cublas-cu12 = { version = "12.1.3.1", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
471 | nvidia-cuda-cupti-cu12 = { version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
472 | nvidia-cuda-nvrtc-cu12 = { version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
473 | nvidia-cuda-runtime-cu12 = { version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
474 | nvidia-cudnn-cu12 = { version = "8.9.2.26", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
475 | nvidia-cufft-cu12 = { version = "11.0.2.54", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
476 | nvidia-curand-cu12 = { version = "10.3.2.106", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
477 | nvidia-cusolver-cu12 = { version = "11.4.5.107", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
478 | nvidia-cusparse-cu12 = { version = "12.1.0.106", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
479 | nvidia-nccl-cu12 = { version = "2.19.3", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
480 | nvidia-nvtx-cu12 = { version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\"" }
481 | sympy = "*"
482 | triton = { version = "2.2.0", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and python_version < \"3.12\"" }
483 | typing-extensions = ">=4.8.0"
484 |
485 | [package.extras]
486 | opt-einsum = ["opt-einsum (>=3.3)"]
487 | optree = ["optree (>=0.9.1)"]
488 |
489 | [[package]]
490 | name = "torchvision"
491 | version = "0.17.2"
492 | description = "image and video datasets and models for torch deep learning"
493 | category = "main"
494 | optional = false
495 | python-versions = ">=3.8"
496 |
497 | [package.dependencies]
498 | numpy = "*"
499 | pillow = ">=5.3.0,<8.3.0 || >=8.4.0"
500 | torch = "2.2.2"
501 |
502 | [package.extras]
503 | scipy = ["scipy"]
504 |
505 | [[package]]
506 | name = "triton"
507 | version = "2.2.0"
508 | description = "A language and compiler for custom Deep Learning operations"
509 | category = "main"
510 | optional = false
511 | python-versions = "*"
512 |
513 | [package.dependencies]
514 | filelock = "*"
515 |
516 | [package.extras]
517 | build = ["cmake (>=3.20)", "lit"]
518 | tests = ["autopep8", "flake8", "isort", "numpy", "pytest", "scipy (>=1.7.1)", "torch"]
519 | tutorials = ["matplotlib", "pandas", "tabulate", "torch"]
520 |
521 | [[package]]
522 | name = "typing-extensions"
523 | version = "4.11.0"
524 | description = "Backported and Experimental Type Hints for Python 3.8+"
525 | category = "main"
526 | optional = false
527 | python-versions = ">=3.8"
528 |
529 | [[package]]
530 | name = "urllib3"
531 | version = "2.2.1"
532 | description = "HTTP library with thread-safe connection pooling, file post, and more."
533 | category = "main"
534 | optional = false
535 | python-versions = ">=3.8"
536 |
537 | [package.extras]
538 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
539 | h2 = ["h2 (>=4,<5)"]
540 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
541 | zstd = ["zstandard (>=0.18.0)"]
542 |
543 | [[package]]
544 | name = "websocket-client"
545 | version = "1.7.0"
546 | description = "WebSocket client for Python with low level API options"
547 | category = "main"
548 | optional = false
549 | python-versions = ">=3.8"
550 |
551 | [package.extras]
552 | docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"]
553 | optional = ["python-socks", "wsaccel"]
554 | test = ["websockets"]
555 |
556 | [[package]]
557 | name = "werkzeug"
558 | version = "3.0.2"
559 | description = "The comprehensive WSGI web application library."
560 | category = "main"
561 | optional = false
562 | python-versions = ">=3.8"
563 |
564 | [package.dependencies]
565 | MarkupSafe = ">=2.1.1"
566 |
567 | [package.extras]
568 | watchdog = ["watchdog (>=2.3)"]
569 |
570 | [[package]]
571 | name = "wsproto"
572 | version = "1.2.0"
573 | description = "WebSockets state-machine based protocol implementation"
574 | category = "main"
575 | optional = false
576 | python-versions = ">=3.7.0"
577 |
578 | [package.dependencies]
579 | h11 = ">=0.9.0,<1"
580 |
581 | [metadata]
582 | lock-version = "1.1"
583 | python-versions = "^3.10"
584 | content-hash = "957ce99cae5fd8d4a7b4b242751e99d3e83dc03e98d45f38868ef3b018a38c70"
585 |
586 | [metadata.files]
587 | bidict = [
588 | { file = "bidict-0.23.1-py3-none-any.whl", hash = "sha256:5dae8d4d79b552a71cbabc7deb25dfe8ce710b17ff41711e13010ead2abfc3e5" },
589 | { file = "bidict-0.23.1.tar.gz", hash = "sha256:03069d763bc387bbd20e7d49914e75fc4132a41937fa3405417e1a5a2d006d71" },
590 | ]
591 | blinker = [
592 | { file = "blinker-1.7.0-py3-none-any.whl", hash = "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9" },
593 | { file = "blinker-1.7.0.tar.gz", hash = "sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182" },
594 | ]
595 | certifi = [
596 | { file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" },
597 | { file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f" },
598 | ]
599 | charset-normalizer = [
600 | { file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5" },
601 | { file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3" },
602 | { file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027" },
603 | { file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03" },
604 | { file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d" },
605 | { file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e" },
606 | { file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6" },
607 | { file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5" },
608 | { file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537" },
609 | { file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c" },
610 | { file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12" },
611 | { file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f" },
612 | { file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269" },
613 | { file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519" },
614 | { file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73" },
615 | { file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09" },
616 | { file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db" },
617 | { file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96" },
618 | { file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e" },
619 | { file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f" },
620 | { file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574" },
621 | { file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4" },
622 | { file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8" },
623 | { file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc" },
624 | { file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae" },
625 | { file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887" },
626 | { file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae" },
627 | { file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce" },
628 | { file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f" },
629 | { file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab" },
630 | { file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77" },
631 | { file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8" },
632 | { file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b" },
633 | { file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6" },
634 | { file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a" },
635 | { file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389" },
636 | { file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa" },
637 | { file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b" },
638 | { file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed" },
639 | { file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26" },
640 | { file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d" },
641 | { file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068" },
642 | { file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143" },
643 | { file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4" },
644 | { file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7" },
645 | { file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001" },
646 | { file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c" },
647 | { file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5" },
648 | { file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985" },
649 | { file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6" },
650 | { file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714" },
651 | { file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786" },
652 | { file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5" },
653 | { file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c" },
654 | { file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8" },
655 | { file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711" },
656 | { file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811" },
657 | { file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4" },
658 | { file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99" },
659 | { file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a" },
660 | { file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac" },
661 | { file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a" },
662 | { file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33" },
663 | { file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238" },
664 | { file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a" },
665 | { file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2" },
666 | { file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8" },
667 | { file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898" },
668 | { file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99" },
669 | { file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d" },
670 | { file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04" },
671 | { file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087" },
672 | { file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25" },
673 | { file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b" },
674 | { file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4" },
675 | { file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d" },
676 | { file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0" },
677 | { file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269" },
678 | { file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c" },
679 | { file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519" },
680 | { file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796" },
681 | { file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185" },
682 | { file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c" },
683 | { file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458" },
684 | { file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2" },
685 | { file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8" },
686 | { file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" },
687 | { file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f" },
688 | { file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d" },
689 | { file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc" },
690 | ]
691 | click = [
692 | { file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28" },
693 | { file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" },
694 | ]
695 | colorama = [
696 | { file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" },
697 | { file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44" },
698 | ]
699 | facenet-pytorch = [
700 | { file = "facenet-pytorch-2.5.3.tar.gz", hash = "sha256:98cc5b42a48f837c023eb92f2a571cd4ac6a46687c5e71b9e99b491087273e2b" },
701 | { file = "facenet_pytorch-2.5.3-py3-none-any.whl", hash = "sha256:b8002c3ee7a3af471c433cbda1fdcab9ae2d46a4aac43435ba08259c45ffc884" },
702 | ]
703 | filelock = [
704 | { file = "filelock-3.13.3-py3-none-any.whl", hash = "sha256:5ffa845303983e7a0b7ae17636509bc97997d58afeafa72fb141a17b152284cb" },
705 | { file = "filelock-3.13.3.tar.gz", hash = "sha256:a79895a25bbefdf55d1a2a0a80968f7dbb28edcd6d4234a0afb3f37ecde4b546" },
706 | ]
707 | flask = [
708 | { file = "flask-3.0.3-py3-none-any.whl", hash = "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3" },
709 | { file = "flask-3.0.3.tar.gz", hash = "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842" },
710 | ]
711 | flask-cors = [
712 | { file = "Flask-Cors-4.0.0.tar.gz", hash = "sha256:f268522fcb2f73e2ecdde1ef45e2fd5c71cc48fe03cffb4b441c6d1b40684eb0" },
713 | { file = "Flask_Cors-4.0.0-py2.py3-none-any.whl", hash = "sha256:bc3492bfd6368d27cfe79c7821df5a8a319e1a6d5eab277a3794be19bdc51783" },
714 | ]
715 | flask-socketio = [
716 | { file = "Flask-SocketIO-5.3.6.tar.gz", hash = "sha256:bb8f9f9123ef47632f5ce57a33514b0c0023ec3696b2384457f0fcaa5b70501c" },
717 | { file = "Flask_SocketIO-5.3.6-py3-none-any.whl", hash = "sha256:9e62d2131842878ae6bfdd7067dfc3be397c1f2b117ab1dc74e6fe74aad7a579" },
718 | ]
719 | fsspec = [
720 | { file = "fsspec-2024.3.1-py3-none-any.whl", hash = "sha256:918d18d41bf73f0e2b261824baeb1b124bcf771767e3a26425cd7dec3332f512" },
721 | { file = "fsspec-2024.3.1.tar.gz", hash = "sha256:f39780e282d7d117ffb42bb96992f8a90795e4d0fb0f661a70ca39fe9c43ded9" },
722 | ]
723 | h11 = [
724 | { file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" },
725 | { file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d" },
726 | ]
727 | idna = [
728 | { file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" },
729 | { file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca" },
730 | ]
731 | itsdangerous = [
732 | { file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44" },
733 | { file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a" },
734 | ]
735 | jinja2 = [
736 | { file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa" },
737 | { file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90" },
738 | ]
739 | markupsafe = [
740 | { file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc" },
741 | { file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5" },
742 | { file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46" },
743 | { file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f" },
744 | { file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900" },
745 | { file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff" },
746 | { file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad" },
747 | { file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd" },
748 | { file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4" },
749 | { file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5" },
750 | { file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f" },
751 | { file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2" },
752 | { file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced" },
753 | { file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5" },
754 | { file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c" },
755 | { file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f" },
756 | { file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a" },
757 | { file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f" },
758 | { file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906" },
759 | { file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617" },
760 | { file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1" },
761 | { file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4" },
762 | { file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee" },
763 | { file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5" },
764 | { file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b" },
765 | { file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a" },
766 | { file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f" },
767 | { file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169" },
768 | { file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad" },
769 | { file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb" },
770 | { file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f" },
771 | { file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf" },
772 | { file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a" },
773 | { file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52" },
774 | { file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9" },
775 | { file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df" },
776 | { file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50" },
777 | { file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371" },
778 | { file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2" },
779 | { file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a" },
780 | { file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46" },
781 | { file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532" },
782 | { file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab" },
783 | { file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68" },
784 | { file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0" },
785 | { file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4" },
786 | { file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3" },
787 | { file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff" },
788 | { file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029" },
789 | { file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf" },
790 | { file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2" },
791 | { file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8" },
792 | { file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3" },
793 | { file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465" },
794 | { file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e" },
795 | { file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea" },
796 | { file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6" },
797 | { file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf" },
798 | { file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5" },
799 | { file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b" },
800 | ]
801 | mpmath = [
802 | { file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c" },
803 | { file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f" },
804 | ]
805 | networkx = [
806 | { file = "networkx-3.3-py3-none-any.whl", hash = "sha256:28575580c6ebdaf4505b22c6256a2b9de86b316dc63ba9e93abde3d78dfdbcf2" },
807 | { file = "networkx-3.3.tar.gz", hash = "sha256:0c127d8b2f4865f59ae9cb8aafcd60b5c70f3241ebd66f7defad7c4ab90126c9" },
808 | ]
809 | numpy = [
810 | { file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0" },
811 | { file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a" },
812 | { file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4" },
813 | { file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f" },
814 | { file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a" },
815 | { file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2" },
816 | { file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07" },
817 | { file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5" },
818 | { file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71" },
819 | { file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef" },
820 | { file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e" },
821 | { file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5" },
822 | { file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a" },
823 | { file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a" },
824 | { file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20" },
825 | { file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2" },
826 | { file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218" },
827 | { file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b" },
828 | { file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b" },
829 | { file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed" },
830 | { file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a" },
831 | { file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0" },
832 | { file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110" },
833 | { file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818" },
834 | { file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c" },
835 | { file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be" },
836 | { file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764" },
837 | { file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3" },
838 | { file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd" },
839 | { file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c" },
840 | { file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6" },
841 | { file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea" },
842 | { file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30" },
843 | { file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c" },
844 | { file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0" },
845 | { file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010" },
846 | ]
847 | nvidia-cublas-cu12 = [
848 | { file = "nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl", hash = "sha256:ee53ccca76a6fc08fb9701aa95b6ceb242cdaab118c3bb152af4e579af792728" },
849 | { file = "nvidia_cublas_cu12-12.1.3.1-py3-none-win_amd64.whl", hash = "sha256:2b964d60e8cf11b5e1073d179d85fa340c120e99b3067558f3cf98dd69d02906" },
850 | ]
851 | nvidia-cuda-cupti-cu12 = [
852 | { file = "nvidia_cuda_cupti_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:e54fde3983165c624cb79254ae9818a456eb6e87a7fd4d56a2352c24ee542d7e" },
853 | { file = "nvidia_cuda_cupti_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:bea8236d13a0ac7190bd2919c3e8e6ce1e402104276e6f9694479e48bb0eb2a4" },
854 | ]
855 | nvidia-cuda-nvrtc-cu12 = [
856 | { file = "nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:339b385f50c309763ca65456ec75e17bbefcbbf2893f462cb8b90584cd27a1c2" },
857 | { file = "nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:0a98a522d9ff138b96c010a65e145dc1b4850e9ecb75a0172371793752fd46ed" },
858 | ]
859 | nvidia-cuda-runtime-cu12 = [
860 | { file = "nvidia_cuda_runtime_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:6e258468ddf5796e25f1dc591a31029fa317d97a0a94ed93468fc86301d61e40" },
861 | { file = "nvidia_cuda_runtime_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:dfb46ef84d73fababab44cf03e3b83f80700d27ca300e537f85f636fac474344" },
862 | ]
863 | nvidia-cudnn-cu12 = [
864 | { file = "nvidia_cudnn_cu12-8.9.2.26-py3-none-manylinux1_x86_64.whl", hash = "sha256:5ccb288774fdfb07a7e7025ffec286971c06d8d7b4fb162525334616d7629ff9" },
865 | ]
866 | nvidia-cufft-cu12 = [
867 | { file = "nvidia_cufft_cu12-11.0.2.54-py3-none-manylinux1_x86_64.whl", hash = "sha256:794e3948a1aa71fd817c3775866943936774d1c14e7628c74f6f7417224cdf56" },
868 | { file = "nvidia_cufft_cu12-11.0.2.54-py3-none-win_amd64.whl", hash = "sha256:d9ac353f78ff89951da4af698f80870b1534ed69993f10a4cf1d96f21357e253" },
869 | ]
870 | nvidia-curand-cu12 = [
871 | { file = "nvidia_curand_cu12-10.3.2.106-py3-none-manylinux1_x86_64.whl", hash = "sha256:9d264c5036dde4e64f1de8c50ae753237c12e0b1348738169cd0f8a536c0e1e0" },
872 | { file = "nvidia_curand_cu12-10.3.2.106-py3-none-win_amd64.whl", hash = "sha256:75b6b0c574c0037839121317e17fd01f8a69fd2ef8e25853d826fec30bdba74a" },
873 | ]
874 | nvidia-cusolver-cu12 = [
875 | { file = "nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl", hash = "sha256:8a7ec542f0412294b15072fa7dab71d31334014a69f953004ea7a118206fe0dd" },
876 | { file = "nvidia_cusolver_cu12-11.4.5.107-py3-none-win_amd64.whl", hash = "sha256:74e0c3a24c78612192a74fcd90dd117f1cf21dea4822e66d89e8ea80e3cd2da5" },
877 | ]
878 | nvidia-cusparse-cu12 = [
879 | { file = "nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl", hash = "sha256:f3b50f42cf363f86ab21f720998517a659a48131e8d538dc02f8768237bd884c" },
880 | { file = "nvidia_cusparse_cu12-12.1.0.106-py3-none-win_amd64.whl", hash = "sha256:b798237e81b9719373e8fae8d4f091b70a0cf09d9d85c95a557e11df2d8e9a5a" },
881 | ]
882 | nvidia-nccl-cu12 = [
883 | { file = "nvidia_nccl_cu12-2.19.3-py3-none-manylinux1_x86_64.whl", hash = "sha256:a9734707a2c96443331c1e48c717024aa6678a0e2a4cb66b2c364d18cee6b48d" },
884 | ]
885 | nvidia-nvjitlink-cu12 = [
886 | { file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57" },
887 | { file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-win_amd64.whl", hash = "sha256:fd9020c501d27d135f983c6d3e244b197a7ccad769e34df53a42e276b0e25fa1" },
888 | ]
889 | nvidia-nvtx-cu12 = [
890 | { file = "nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:dc21cf308ca5691e7c04d962e213f8a4aa9bbfa23d95412f452254c2caeb09e5" },
891 | { file = "nvidia_nvtx_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:65f4d98982b31b60026e0e6de73fbdfc09d08a96f4656dd3665ca616a11e1e82" },
892 | ]
893 | opencv-python = [
894 | { file = "opencv-python-4.9.0.80.tar.gz", hash = "sha256:1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1" },
895 | { file = "opencv_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:7e5f7aa4486651a6ebfa8ed4b594b65bd2d2f41beeb4241a3e4b1b85acbbbadb" },
896 | { file = "opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3" },
897 | { file = "opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a" },
898 | { file = "opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57" },
899 | { file = "opencv_python-4.9.0.80-cp37-abi3-win32.whl", hash = "sha256:dcf000c36dd1651118a2462257e3a9e76db789a78432e1f303c7bac54f63ef6c" },
900 | { file = "opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl", hash = "sha256:3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0" },
901 | ]
902 | pillow = [
903 | { file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45" },
904 | { file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c" },
905 | { file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf" },
906 | { file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599" },
907 | { file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475" },
908 | { file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf" },
909 | { file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3" },
910 | { file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5" },
911 | { file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2" },
912 | { file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f" },
913 | { file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b" },
914 | { file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795" },
915 | { file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57" },
916 | { file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27" },
917 | { file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994" },
918 | { file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451" },
919 | { file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd" },
920 | { file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad" },
921 | { file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c" },
922 | { file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09" },
923 | { file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d" },
924 | { file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f" },
925 | { file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84" },
926 | { file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19" },
927 | { file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338" },
928 | { file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1" },
929 | { file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462" },
930 | { file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a" },
931 | { file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef" },
932 | { file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3" },
933 | { file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d" },
934 | { file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b" },
935 | { file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a" },
936 | { file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b" },
937 | { file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2" },
938 | { file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa" },
939 | { file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383" },
940 | { file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d" },
941 | { file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd" },
942 | { file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d" },
943 | { file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3" },
944 | { file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b" },
945 | { file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999" },
946 | { file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936" },
947 | { file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002" },
948 | { file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60" },
949 | { file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375" },
950 | { file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57" },
951 | { file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8" },
952 | { file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9" },
953 | { file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb" },
954 | { file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572" },
955 | { file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb" },
956 | { file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f" },
957 | { file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355" },
958 | { file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9" },
959 | { file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2" },
960 | { file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463" },
961 | { file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced" },
962 | { file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3" },
963 | { file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170" },
964 | { file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32" },
965 | { file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828" },
966 | { file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f" },
967 | { file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015" },
968 | { file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5" },
969 | { file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a" },
970 | { file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591" },
971 | { file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d" },
972 | ]
973 | python-engineio = [
974 | { file = "python-engineio-4.9.0.tar.gz", hash = "sha256:e87459c15638e567711fd156e6f9c4a402668871bed79523f0ecfec744729ec7" },
975 | { file = "python_engineio-4.9.0-py3-none-any.whl", hash = "sha256:979859bff770725b75e60353d7ae53b397e8b517d05ba76733b404a3dcca3e4c" },
976 | ]
977 | python-socketio = [
978 | { file = "python-socketio-5.11.2.tar.gz", hash = "sha256:ae6a1de5c5209ca859dc574dccc8931c4be17ee003e74ce3b8d1306162bb4a37" },
979 | { file = "python_socketio-5.11.2-py3-none-any.whl", hash = "sha256:b9f22a8ff762d7a6e123d16a43ddb1a27d50f07c3c88ea999334f2f89b0ad52b" },
980 | ]
981 | requests = [
982 | { file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f" },
983 | { file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" },
984 | ]
985 | simple-websocket = [
986 | { file = "simple-websocket-1.0.0.tar.gz", hash = "sha256:17d2c72f4a2bd85174a97e3e4c88b01c40c3f81b7b648b0cc3ce1305968928c8" },
987 | { file = "simple_websocket-1.0.0-py3-none-any.whl", hash = "sha256:1d5bf585e415eaa2083e2bcf02a3ecf91f9712e7b3e6b9fa0b461ad04e0837bc" },
988 | ]
989 | sympy = [
990 | { file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5" },
991 | { file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8" },
992 | ]
993 | torch = [
994 | { file = "torch-2.2.2-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:bc889d311a855dd2dfd164daf8cc903a6b7273a747189cebafdd89106e4ad585" },
995 | { file = "torch-2.2.2-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:15dffa4cc3261fa73d02f0ed25f5fa49ecc9e12bf1ae0a4c1e7a88bbfaad9030" },
996 | { file = "torch-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:11e8fe261233aeabd67696d6b993eeb0896faa175c6b41b9a6c9f0334bdad1c5" },
997 | { file = "torch-2.2.2-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:b2e2200b245bd9f263a0d41b6a2dab69c4aca635a01b30cca78064b0ef5b109e" },
998 | { file = "torch-2.2.2-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:877b3e6593b5e00b35bbe111b7057464e76a7dd186a287280d941b564b0563c2" },
999 | { file = "torch-2.2.2-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:ad4c03b786e074f46606f4151c0a1e3740268bcf29fbd2fdf6666d66341c1dcb" },
1000 | { file = "torch-2.2.2-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:32827fa1fbe5da8851686256b4cd94cc7b11be962862c2293811c94eea9457bf" },
1001 | { file = "torch-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:f9ef0a648310435511e76905f9b89612e45ef2c8b023bee294f5e6f7e73a3e7c" },
1002 | { file = "torch-2.2.2-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:95b9b44f3bcebd8b6cd8d37ec802048c872d9c567ba52c894bba90863a439059" },
1003 | { file = "torch-2.2.2-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:49aa4126ede714c5aeef7ae92969b4b0bbe67f19665106463c39f22e0a1860d1" },
1004 | { file = "torch-2.2.2-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:cf12cdb66c9c940227ad647bc9cf5dba7e8640772ae10dfe7569a0c1e2a28aca" },
1005 | { file = "torch-2.2.2-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:89ddac2a8c1fb6569b90890955de0c34e1724f87431cacff4c1979b5f769203c" },
1006 | { file = "torch-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:451331406b760f4b1ab298ddd536486ab3cfb1312614cfe0532133535be60bea" },
1007 | { file = "torch-2.2.2-cp312-none-macosx_10_9_x86_64.whl", hash = "sha256:eb4d6e9d3663e26cd27dc3ad266b34445a16b54908e74725adb241aa56987533" },
1008 | { file = "torch-2.2.2-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:bf9558da7d2bf7463390b3b2a61a6a3dbb0b45b161ee1dd5ec640bf579d479fc" },
1009 | { file = "torch-2.2.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cd2bf7697c9e95fb5d97cc1d525486d8cf11a084c6af1345c2c2c22a6b0029d0" },
1010 | { file = "torch-2.2.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:b421448d194496e1114d87a8b8d6506bce949544e513742b097e2ab8f7efef32" },
1011 | { file = "torch-2.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:3dbcd563a9b792161640c0cffe17e3270d85e8f4243b1f1ed19cca43d28d235b" },
1012 | { file = "torch-2.2.2-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:31f4310210e7dda49f1fb52b0ec9e59382cfcb938693f6d5378f25b43d7c1d29" },
1013 | { file = "torch-2.2.2-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:c795feb7e8ce2e0ef63f75f8e1ab52e7fd5e1a4d7d0c31367ade1e3de35c9e95" },
1014 | { file = "torch-2.2.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:a6e5770d68158d07456bfcb5318b173886f579fdfbf747543901ce718ea94782" },
1015 | { file = "torch-2.2.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:67dcd726edff108e2cd6c51ff0e416fd260c869904de95750e80051358680d24" },
1016 | { file = "torch-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:539d5ef6c4ce15bd3bd47a7b4a6e7c10d49d4d21c0baaa87c7d2ef8698632dfb" },
1017 | { file = "torch-2.2.2-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:dff696de90d6f6d1e8200e9892861fd4677306d0ef604cb18f2134186f719f82" },
1018 | { file = "torch-2.2.2-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:3a4dd910663fd7a124c056c878a52c2b0be4a5a424188058fe97109d4436ee42" },
1019 | ]
1020 | torchvision = [
1021 | { file = "torchvision-0.17.2-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:1f2910fe3c21ad6875b2720d46fad835b2e4b336e9553d31ca364d24c90b1d4f" },
1022 | { file = "torchvision-0.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ecc1c503fa8a54fbab777e06a7c228032b8ab78efebf35b28bc8f22f544f51f1" },
1023 | { file = "torchvision-0.17.2-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:f400145fc108833e7c2fc28486a04989ca742146d7a2a2cc48878ebbb40cdbbd" },
1024 | { file = "torchvision-0.17.2-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:e9e4bed404af33dfc92eecc2b513d21ddc4c242a7fd8708b3b09d3a26aa6f444" },
1025 | { file = "torchvision-0.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:ba2e62f233eab3d42b648c122a3a29c47cc108ca314dfd5cbb59cd3a143fd623" },
1026 | { file = "torchvision-0.17.2-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:9b83e55ee7d0a1704f52b9c0ac87388e7a6d1d98a6bde7b0b35f9ab54d7bda54" },
1027 | { file = "torchvision-0.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e031004a1bc432c980a7bd642f6c189a3efc316e423fc30b5569837166a4e28d" },
1028 | { file = "torchvision-0.17.2-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:3bbc24b7713e8f22766992562547d8b4b10001208d372fe599255af84bfd1a69" },
1029 | { file = "torchvision-0.17.2-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:833fd2e4216ced924c8aca0525733fe727f9a1af66dfad7c5be7257e97c39678" },
1030 | { file = "torchvision-0.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:6835897df852fad1015e6a106c167c83848114cbcc7d86112384a973404e4431" },
1031 | { file = "torchvision-0.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:14fd1d4a033c325bdba2d03a69c3450cab6d3a625f85cc375781d9237ca5d04d" },
1032 | { file = "torchvision-0.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9c3acbebbe379af112b62b535820174277b1f3eed30df264a4e458d58ee4e5b2" },
1033 | { file = "torchvision-0.17.2-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:77d680adf6ce367166a186d2c7fda3a73807ab9a03b2c31a03fa8812c8c5335b" },
1034 | { file = "torchvision-0.17.2-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:f1c9ab3152cfb27f83aca072cac93a3a4c4e4ab0261cf0f2d516b9868a4e96f3" },
1035 | { file = "torchvision-0.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:3f784381419f3ed3f2ec2aa42fb4aeec5bf4135e298d1631e41c926e6f1a0dff" },
1036 | { file = "torchvision-0.17.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:b83aac8d78f48981146d582168d75b6c947cfb0a7693f76e219f1926f6e595a3" },
1037 | { file = "torchvision-0.17.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1ece40557e122d79975860a005aa7e2a9e2e6c350a03e78a00ec1450083312fd" },
1038 | { file = "torchvision-0.17.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:32dbeba3987e20f2dc1bce8d1504139fff582898346dfe8ad98d649f97ca78fa" },
1039 | { file = "torchvision-0.17.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:35ba5c1600c3203549d2316422a659bd20c0cfda1b6085eec94fb9f35f55ca43" },
1040 | { file = "torchvision-0.17.2-cp38-cp38-win_amd64.whl", hash = "sha256:2f69570f50b1d195e51bc03feffb7b7728207bc36efcfb1f0813712b2379d881" },
1041 | { file = "torchvision-0.17.2-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:4868bbfa55758c8107e69a0e7dd5e77b89056035cd38b767ad5b98cdb71c0f0d" },
1042 | { file = "torchvision-0.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:efd6d0dd0668e15d01a2cffadc74068433b32cbcf5692e0c4aa15fc5cb250ce7" },
1043 | { file = "torchvision-0.17.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7dc85b397f6c6d9ef12716ce0d6e11ac2b803f5cccff6fe3966db248e7774478" },
1044 | { file = "torchvision-0.17.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d506854c5acd69b20a8b6641f01fe841685a21c5406b56813184f1c9fc94279e" },
1045 | { file = "torchvision-0.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:067095e87a020a7a251ac1d38483aa591c5ccb81e815527c54db88a982fc9267" },
1046 | ]
1047 | triton = [
1048 | { file = "triton-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2294514340cfe4e8f4f9e5c66c702744c4a117d25e618bd08469d0bfed1e2e5" },
1049 | { file = "triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da58a152bddb62cafa9a857dd2bc1f886dbf9f9c90a2b5da82157cd2b34392b0" },
1050 | { file = "triton-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af58716e721460a61886668b205963dc4d1e4ac20508cc3f623aef0d70283d5" },
1051 | { file = "triton-2.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8fe46d3ab94a8103e291bd44c741cc294b91d1d81c1a2888254cbf7ff846dab" },
1052 | { file = "triton-2.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8ce26093e539d727e7cf6f6f0d932b1ab0574dc02567e684377630d86723ace" },
1053 | { file = "triton-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:227cc6f357c5efcb357f3867ac2a8e7ecea2298cd4606a8ba1e931d1d5a947df" },
1054 | ]
1055 | typing-extensions = [
1056 | { file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" },
1057 | { file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0" },
1058 | ]
1059 | urllib3 = [
1060 | { file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d" },
1061 | { file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" },
1062 | ]
1063 | websocket-client = [
1064 | { file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6" },
1065 | { file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588" },
1066 | ]
1067 | werkzeug = [
1068 | { file = "werkzeug-3.0.2-py3-none-any.whl", hash = "sha256:3aac3f5da756f93030740bc235d3e09449efcf65f2f55e3602e1d851b8f48795" },
1069 | { file = "werkzeug-3.0.2.tar.gz", hash = "sha256:e39b645a6ac92822588e7b39a692e7828724ceae0b0d702ef96701f90e70128d" },
1070 | ]
1071 | wsproto = [
1072 | { file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736" },
1073 | { file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065" },
1074 | ]
1075 |
--------------------------------------------------------------------------------