XMWAI 0.4.1__tar.gz → 0.4.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of XMWAI might be problematic. Click here for more details.
- {xmwai-0.4.1 → xmwai-0.4.4}/MANIFEST.in +2 -1
- {xmwai-0.4.1/XMWAI.egg-info → xmwai-0.4.4}/PKG-INFO +2 -1
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/__init__.py +5 -3
- xmwai-0.4.4/XMWAI/assets/1.png +0 -0
- xmwai-0.4.4/XMWAI/assets/g.png +0 -0
- xmwai-0.4.4/XMWAI/assets/h.png +0 -0
- xmwai-0.4.4/XMWAI/assets/l.png +0 -0
- xmwai-0.4.4/XMWAI/assets/m.png +0 -0
- xmwai-0.4.4/XMWAI/assets/s.png +0 -0
- xmwai-0.4.4/XMWAI/assets/t.png +0 -0
- xmwai-0.4.4/XMWAI/assets//345/276/256/350/275/257/351/233/205/351/273/221.ttf +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/core.py +2 -2
- xmwai-0.4.4/XMWAI/gif/__init__.py +0 -0
- xmwai-0.4.4/XMWAI/snake_core.py +426 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/trial_class.py +53 -49
- {xmwai-0.4.1 → xmwai-0.4.4/XMWAI.egg-info}/PKG-INFO +2 -1
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI.egg-info/SOURCES.txt +10 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI.egg-info/requires.txt +1 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/setup.py +5 -2
- {xmwai-0.4.1 → xmwai-0.4.4}/LICENSE.txt +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/README.md +0 -0
- {xmwai-0.4.1/XMWAI/file → xmwai-0.4.4/XMWAI/assets}/__init__.py +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/bomb_core.py +0 -0
- {xmwai-0.4.1/XMWAI/gif → xmwai-0.4.4/XMWAI/file}/__init__.py +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/file/idiom.json +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/0.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/1.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/10.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/11.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/12.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/13.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/14.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/15.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/16.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/17.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/18.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/19.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/2.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/20.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/21.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/22.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/23.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/24.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/25.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/26.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/27.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/28.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/29.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/3.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/30.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/31.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/32.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/33.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/34.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/35.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/36.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/37.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/38.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/39.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/4.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/40.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/41.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/42.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/43.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/44.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/45.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/46.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/47.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/48.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/49.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/5.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/50.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/51.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/52.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/53.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/54.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/55.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/56.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/57.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/58.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/59.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/6.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/60.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/61.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/62.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/63.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/64.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/65.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/66.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/67.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/68.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/69.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/7.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/70.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/71.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/72.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/73.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/74.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/75.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/76.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/77.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/78.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/79.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/8.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/80.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/81.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/82.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/83.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/84.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/85.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/gif/9.gif +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/idiom_core.py +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/magic_core.py +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/burger.js +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/BottomBun.png +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/TopBun.png +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/beef.png +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/bg.jpeg +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/bg.png +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/cheese.png +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/lettuce.png +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/sauce.png +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/static/images/tomato.png +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/templates/burger.html +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/templates/nutrition_pie.html +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/templates//345/210/233/346/204/217/350/217/234/350/260/261.html" +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/web_core.py +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI.egg-info/dependency_links.txt +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/XMWAI.egg-info/top_level.txt +0 -0
- {xmwai-0.4.1 → xmwai-0.4.4}/setup.cfg +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
recursive-include XMWAI/gif *
|
|
2
2
|
recursive-include XMWAI/file *.json
|
|
3
3
|
recursive-include XMWAI/templates *.html
|
|
4
|
-
recursive-include XMWAI/static *.js *.css *.png *.jpg *.gif *.jpeg
|
|
4
|
+
recursive-include XMWAI/static *.js *.css *.png *.jpg *.gif *.jpeg
|
|
5
|
+
recursive-include XMWAI/assets *
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: XMWAI
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
4
4
|
Summary: Small code King AI related library
|
|
5
5
|
Home-page: https://github.com/Tonykai88/XMWAI.git
|
|
6
6
|
Author: pydevelopment
|
|
@@ -17,6 +17,7 @@ Requires-Dist: opencv-python>=3.4.18.65
|
|
|
17
17
|
Requires-Dist: numpy>=1.26.0
|
|
18
18
|
Requires-Dist: flask>=3.1.0
|
|
19
19
|
Requires-Dist: pyecharts>=2.0.8
|
|
20
|
+
Requires-Dist: cvzone>=1.6.1
|
|
20
21
|
Dynamic: author
|
|
21
22
|
Dynamic: author-email
|
|
22
23
|
Dynamic: classifier
|
|
@@ -2,10 +2,12 @@ from .core import story, photo, reply, poem, crack, show # 从子模块导入
|
|
|
2
2
|
from .magic_core import birthday # 从子模块导入函数到顶层
|
|
3
3
|
from .bomb_core import bomb # 从子模块导入函数到顶层
|
|
4
4
|
from .idiom_core import idiom, searchIdiom, get_json_path # 从子模块导入函数到顶层
|
|
5
|
-
from .trial_class import make, get_file_content_as_base64, save_pic,
|
|
5
|
+
from .trial_class import make, get_file_content_as_base64, save_pic, detect_scale, open_image, get_file_content_as_base64_2, cartoon # 从子模块导入函数到顶层
|
|
6
6
|
from .web_core import burger, cookbook # 从子模块导入函数到顶层
|
|
7
|
+
from .snake_core import SnakeGame
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
__all__ = ["story", "photo", "reply", "poem", 'birthday', 'bomb',
|
|
9
11
|
"idiom", "searchIdiom", "get_json_path", "crack", "show",
|
|
10
|
-
"make", "get_file_content_as_base64", "save_pic", "
|
|
11
|
-
"get_file_content_as_base64_2", "cartoon", "burger", "cookbook"] # 可选:明确导出的内容
|
|
12
|
+
"make", "get_file_content_as_base64", "save_pic", "detect_scale", "open_image",
|
|
13
|
+
"get_file_content_as_base64_2", "cartoon", "burger", "cookbook", "SnakeGame"] # 可选:明确导出的内容
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -36,7 +36,7 @@ def story(role, time, address, event, key=""):
|
|
|
36
36
|
print("秘钥错误!请重新输入!")
|
|
37
37
|
return "秘钥错误!请重新输入!"
|
|
38
38
|
header = {
|
|
39
|
-
"Authorization": "AQRVzyCpgQdFQnclClou:FwsxoAqSoVsEedfhiDkK"
|
|
39
|
+
"Authorization": "Bearer AQRVzyCpgQdFQnclClou:FwsxoAqSoVsEedfhiDkK"
|
|
40
40
|
}
|
|
41
41
|
response = requests.post(url, headers=header, json=data, stream=True)
|
|
42
42
|
|
|
@@ -135,7 +135,7 @@ def reply(role, content, key=""):
|
|
|
135
135
|
print("秘钥错误!请重新输入!")
|
|
136
136
|
return "秘钥错误!请重新输入!"
|
|
137
137
|
header = {
|
|
138
|
-
"Authorization": "AQRVzyCpgQdFQnclClou:FwsxoAqSoVsEedfhiDkK"
|
|
138
|
+
"Authorization": "Bearer AQRVzyCpgQdFQnclClou:FwsxoAqSoVsEedfhiDkK"
|
|
139
139
|
}
|
|
140
140
|
response = requests.post(url, headers=header, json=data, stream=True)
|
|
141
141
|
|
|
File without changes
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import cv2
|
|
2
|
+
import math
|
|
3
|
+
import random
|
|
4
|
+
import cvzone
|
|
5
|
+
import numpy as np
|
|
6
|
+
from cvzone.HandTrackingModule import HandDetector
|
|
7
|
+
from PIL import ImageFont, ImageDraw, Image
|
|
8
|
+
import os
|
|
9
|
+
import time
|
|
10
|
+
import importlib.resources as pkg_resources
|
|
11
|
+
import XMWAI.assets # 引入资源目录
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# ---------- 工具函数:从 assets 读取资源 ----------
|
|
15
|
+
def get_asset_path(filename: str) -> str:
|
|
16
|
+
"""
|
|
17
|
+
获取包内资源的绝对路径 (兼容 pip 安装后的情况)
|
|
18
|
+
"""
|
|
19
|
+
with pkg_resources.path(XMWAI.assets, filename) as p:
|
|
20
|
+
return str(p)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SnakeGame:
|
|
24
|
+
def __init__(self, width=720, height=720, snakeInitLength=150, snakeGrowth=50,
|
|
25
|
+
snakeLineWidth=10, snakeHeadSize=15, foodPaths=None, foodNames=None, foodScores=None,
|
|
26
|
+
obstaclePaths=None, fontPath=None):
|
|
27
|
+
|
|
28
|
+
self.resolution = (width, height)
|
|
29
|
+
self.snakeInitLength = snakeInitLength
|
|
30
|
+
self._snakeGrowth = snakeGrowth
|
|
31
|
+
self._snakeHeadSize = snakeHeadSize
|
|
32
|
+
self._foodScores = foodScores if foodScores is not None else [3, 2, 1]
|
|
33
|
+
self.snakeLineWidth = snakeLineWidth
|
|
34
|
+
|
|
35
|
+
# 默认资源路径
|
|
36
|
+
if foodPaths is None:
|
|
37
|
+
foodPaths = [get_asset_path("h.png"),
|
|
38
|
+
get_asset_path("s.png"),
|
|
39
|
+
get_asset_path("t.png")]
|
|
40
|
+
if foodNames is None:
|
|
41
|
+
foodNames = ["汉堡", "薯条", "甜甜圈"]
|
|
42
|
+
if obstaclePaths is None:
|
|
43
|
+
obstaclePaths = [get_asset_path("g.png"),
|
|
44
|
+
get_asset_path("l.png"),
|
|
45
|
+
get_asset_path("m.png")]
|
|
46
|
+
if fontPath is None:
|
|
47
|
+
fontPath = get_asset_path("微软雅黑.ttf")
|
|
48
|
+
|
|
49
|
+
self.foodPaths = foodPaths
|
|
50
|
+
self.foodNames = foodNames
|
|
51
|
+
self.obstaclePaths = obstaclePaths
|
|
52
|
+
self.fontPath = fontPath
|
|
53
|
+
|
|
54
|
+
self.cap = None
|
|
55
|
+
self.detector = None
|
|
56
|
+
self.snake = None
|
|
57
|
+
self.foodManager = None
|
|
58
|
+
self.obstacleManager = None
|
|
59
|
+
self.img = None
|
|
60
|
+
self.overlayTexts = []
|
|
61
|
+
|
|
62
|
+
self.timer = 30
|
|
63
|
+
self.start_time = None
|
|
64
|
+
|
|
65
|
+
self._init_game_objects()
|
|
66
|
+
self.open_window()
|
|
67
|
+
|
|
68
|
+
# ----------- 属性自动同步 -----------
|
|
69
|
+
@property
|
|
70
|
+
def snakeHeadSize(self):
|
|
71
|
+
return self._snakeHeadSize
|
|
72
|
+
|
|
73
|
+
@snakeHeadSize.setter
|
|
74
|
+
def snakeHeadSize(self, value):
|
|
75
|
+
self._snakeHeadSize = value
|
|
76
|
+
if self.snake:
|
|
77
|
+
self.snake.headSize = value
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def foodScores(self):
|
|
81
|
+
return self._foodScores
|
|
82
|
+
|
|
83
|
+
@foodScores.setter
|
|
84
|
+
def foodScores(self, scores):
|
|
85
|
+
self._foodScores = scores
|
|
86
|
+
if self.foodManager:
|
|
87
|
+
self.foodManager.foodScores = scores
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def snakeGrowth(self):
|
|
91
|
+
return self._snakeGrowth
|
|
92
|
+
|
|
93
|
+
@snakeGrowth.setter
|
|
94
|
+
def snakeGrowth(self, value):
|
|
95
|
+
self._snakeGrowth = value
|
|
96
|
+
|
|
97
|
+
# ---------------- 工具函数 ----------------
|
|
98
|
+
def _putChineseText(self, img, text, pos, fontSize=40, color=(0, 0, 255)):
|
|
99
|
+
img_pil = Image.fromarray(img)
|
|
100
|
+
draw = ImageDraw.Draw(img_pil)
|
|
101
|
+
try:
|
|
102
|
+
font = ImageFont.truetype(self.fontPath, fontSize)
|
|
103
|
+
except OSError:
|
|
104
|
+
font = ImageFont.load_default()
|
|
105
|
+
draw.text(pos, text, font=font, fill=color)
|
|
106
|
+
return np.array(img_pil)
|
|
107
|
+
|
|
108
|
+
def _init_game_objects(self):
|
|
109
|
+
self.snake = self.Snake(color=(0, 0, 255), initLength=self.snakeInitLength,
|
|
110
|
+
lineWidth=self.snakeLineWidth, headSize=self._snakeHeadSize)
|
|
111
|
+
self.foodManager = self.FoodManager(
|
|
112
|
+
self.foodPaths, self.foodNames, self._foodScores)
|
|
113
|
+
self.obstacleManager = self.ObstacleManager(self.obstaclePaths)
|
|
114
|
+
self.obstacleManager.randomObstacles()
|
|
115
|
+
|
|
116
|
+
def _render_frame(self, show_food=True, show_obstacle=True):
|
|
117
|
+
success, self.img = self.cap.read()
|
|
118
|
+
if not success:
|
|
119
|
+
return
|
|
120
|
+
self.img = cv2.flip(self.img, 1)
|
|
121
|
+
hands, self.img = self.detector.findHands(self.img, flipType=False)
|
|
122
|
+
player_head = tuple(hands[0]['lmList'][8][0:2]) if hands else None
|
|
123
|
+
|
|
124
|
+
if not self.snake.gameOver and player_head:
|
|
125
|
+
self.snake.update(self.img, player_head, self.obstacleManager)
|
|
126
|
+
|
|
127
|
+
if not self.snake.gameOver and player_head and show_food:
|
|
128
|
+
cx, cy = player_head
|
|
129
|
+
rx, ry = self.foodManager.foodPoint
|
|
130
|
+
w, h = self.foodManager.wFood, self.foodManager.hFood
|
|
131
|
+
if rx - w//2 <= cx <= rx + w//2 and ry - h//2 <= cy <= ry + h//2:
|
|
132
|
+
self.snake.score += self.foodManager.foodScores[self.foodManager.foodIndex]
|
|
133
|
+
self.snake.allowedLength += self._snakeGrowth
|
|
134
|
+
self.foodManager.randomFoodLocation(self.obstacleManager)
|
|
135
|
+
|
|
136
|
+
if show_obstacle:
|
|
137
|
+
self.img = self.obstacleManager.draw(self.img)
|
|
138
|
+
self.obstacleManager.moveObstacles(
|
|
139
|
+
self.resolution[0], self.resolution[1])
|
|
140
|
+
|
|
141
|
+
if show_food:
|
|
142
|
+
self.img = self.foodManager.draw(self.img)
|
|
143
|
+
|
|
144
|
+
# ---------------- 对外接口 ----------------
|
|
145
|
+
def open_window(self):
|
|
146
|
+
self.cap = cv2.VideoCapture(0)
|
|
147
|
+
self.cap.set(3, self.resolution[0])
|
|
148
|
+
self.cap.set(4, self.resolution[1])
|
|
149
|
+
self.detector = HandDetector(detectionCon=0.7, maxHands=1)
|
|
150
|
+
success, self.img = self.cap.read()
|
|
151
|
+
if not success:
|
|
152
|
+
print("摄像头打开失败")
|
|
153
|
+
return
|
|
154
|
+
self.img = cv2.flip(self.img, 1)
|
|
155
|
+
cv2.imshow("AI Snake", self.img)
|
|
156
|
+
cv2.waitKey(1)
|
|
157
|
+
|
|
158
|
+
def hand(self):
|
|
159
|
+
if self.cap is None:
|
|
160
|
+
print("请先调用 open_window()")
|
|
161
|
+
return
|
|
162
|
+
if self.detector is None:
|
|
163
|
+
self.detector = HandDetector(detectionCon=0.8, maxHands=1)
|
|
164
|
+
while True:
|
|
165
|
+
success, self.img = self.cap.read()
|
|
166
|
+
if not success:
|
|
167
|
+
break
|
|
168
|
+
self.img = cv2.flip(self.img, 1)
|
|
169
|
+
hands, self.img = self.detector.findHands(self.img, flipType=False)
|
|
170
|
+
cv2.imshow("AI Snake", self.img)
|
|
171
|
+
key = cv2.waitKey(1) & 0xFF
|
|
172
|
+
if hands or key == ord('q'):
|
|
173
|
+
break
|
|
174
|
+
|
|
175
|
+
def display(self):
|
|
176
|
+
if self.img is None:
|
|
177
|
+
self._render_frame(show_food=False)
|
|
178
|
+
self.foodManager.randomFoodLocation(self.obstacleManager)
|
|
179
|
+
self._render_frame(show_food=True)
|
|
180
|
+
self.overlayTexts = [
|
|
181
|
+
(f'玩家分数:{self.snake.score}', (50, 50), 30, (255, 0, 255)),
|
|
182
|
+
(f'倒计时:{self.timer} 秒', (50, 120), 30, (255, 0, 255))
|
|
183
|
+
]
|
|
184
|
+
img_copy = self.img.copy()
|
|
185
|
+
for txt, pos, size, color in self.overlayTexts:
|
|
186
|
+
img_copy = self._putChineseText(img_copy, txt, pos, size, color)
|
|
187
|
+
cv2.imshow("AI Snake", img_copy)
|
|
188
|
+
cv2.waitKey(1)
|
|
189
|
+
|
|
190
|
+
# ---------------- 重置游戏 ----------------
|
|
191
|
+
def reset_game(self):
|
|
192
|
+
self.snake.reset()
|
|
193
|
+
self.snake.headSize = self._snakeHeadSize
|
|
194
|
+
self.obstacleManager.randomObstacles()
|
|
195
|
+
self.foodManager.foodScores = self._foodScores
|
|
196
|
+
self.foodManager.randomFoodLocation(self.obstacleManager)
|
|
197
|
+
self.start_time = time.time()
|
|
198
|
+
self.timer = 30
|
|
199
|
+
if self.cap is None or not self.cap.isOpened():
|
|
200
|
+
self.open_window()
|
|
201
|
+
|
|
202
|
+
# ---------------- 游戏结束 ----------------
|
|
203
|
+
def gameover(self, path=None, size=(100, 100)):
|
|
204
|
+
if path is None:
|
|
205
|
+
path = get_asset_path("1.png")
|
|
206
|
+
|
|
207
|
+
if os.path.exists(path):
|
|
208
|
+
gameover_img = cv2.imread(path)
|
|
209
|
+
gameover_img = cv2.resize(gameover_img, self.resolution)
|
|
210
|
+
else:
|
|
211
|
+
gameover_img = np.zeros(
|
|
212
|
+
(self.resolution[1], self.resolution[0], 3), np.uint8)
|
|
213
|
+
cv2.putText(gameover_img, "Game Over Image Missing!", (50, 100),
|
|
214
|
+
cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 3)
|
|
215
|
+
|
|
216
|
+
gameover_img = self._putChineseText(
|
|
217
|
+
gameover_img, f"最终分数:{self.snake.score}", size, 40, (68, 84, 106))
|
|
218
|
+
|
|
219
|
+
while True:
|
|
220
|
+
cv2.imshow("AI Snake", gameover_img)
|
|
221
|
+
key = cv2.waitKey(0) & 0xFF
|
|
222
|
+
if key == ord('r'): # 重启游戏
|
|
223
|
+
self.reset_game()
|
|
224
|
+
self.start()
|
|
225
|
+
break
|
|
226
|
+
elif key == ord('q'): # 退出游戏
|
|
227
|
+
if self.cap is not None:
|
|
228
|
+
self.cap.release()
|
|
229
|
+
cv2.destroyAllWindows()
|
|
230
|
+
break
|
|
231
|
+
|
|
232
|
+
# ---------------- 游戏主循环 ----------------
|
|
233
|
+
def start(self):
|
|
234
|
+
if self.cap is None or not self.cap.isOpened():
|
|
235
|
+
self.open_window()
|
|
236
|
+
self.start_time = time.time()
|
|
237
|
+
self.timer = 30
|
|
238
|
+
|
|
239
|
+
while True:
|
|
240
|
+
if self.snake.gameOver or self.timer == 0:
|
|
241
|
+
# 游戏结束,进入 gameover 界面
|
|
242
|
+
self.gameover()
|
|
243
|
+
break
|
|
244
|
+
|
|
245
|
+
self._render_frame(show_food=True, show_obstacle=True)
|
|
246
|
+
elapsed = int(time.time() - self.start_time)
|
|
247
|
+
self.timer = max(0, 30 - elapsed)
|
|
248
|
+
|
|
249
|
+
self.overlayTexts = [
|
|
250
|
+
(f'玩家分数:{self.snake.score}', (50, 50), 30, (255, 0, 255)),
|
|
251
|
+
(f'倒计时:{self.timer} 秒', (50, 120), 30, (255, 0, 255))
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
if self.img is not None:
|
|
255
|
+
img_copy = self.img.copy()
|
|
256
|
+
for txt, pos, size, color in self.overlayTexts:
|
|
257
|
+
img_copy = self._putChineseText(
|
|
258
|
+
img_copy, txt, pos, size, color)
|
|
259
|
+
cv2.imshow("AI Snake", img_copy)
|
|
260
|
+
|
|
261
|
+
key = cv2.waitKey(1)
|
|
262
|
+
if key == ord('r'): # 游戏中途重置
|
|
263
|
+
self.reset_game()
|
|
264
|
+
elif key == ord('q'):
|
|
265
|
+
if self.cap is not None:
|
|
266
|
+
self.cap.release()
|
|
267
|
+
cv2.destroyAllWindows()
|
|
268
|
+
break
|
|
269
|
+
|
|
270
|
+
# ---------------- 内部类:蛇 ----------------
|
|
271
|
+
class Snake:
|
|
272
|
+
def __init__(self, color, initLength=150, lineWidth=10, headSize=15):
|
|
273
|
+
self.points = []
|
|
274
|
+
self.currentLength = 0
|
|
275
|
+
self.allowedLength = initLength
|
|
276
|
+
self.previousHead = None
|
|
277
|
+
self.score = 0
|
|
278
|
+
self.color = color
|
|
279
|
+
self.gameOver = False
|
|
280
|
+
self.lineWidth = lineWidth
|
|
281
|
+
self.headSize = headSize
|
|
282
|
+
|
|
283
|
+
def reset(self):
|
|
284
|
+
self.points = []
|
|
285
|
+
self.currentLength = 0
|
|
286
|
+
self.allowedLength = 150
|
|
287
|
+
self.previousHead = None
|
|
288
|
+
self.score = 0
|
|
289
|
+
self.gameOver = False
|
|
290
|
+
|
|
291
|
+
def update(self, imgMain, currentHead, obstacleManager=None):
|
|
292
|
+
if self.gameOver:
|
|
293
|
+
return
|
|
294
|
+
cx, cy = currentHead
|
|
295
|
+
if cx is None or cy is None:
|
|
296
|
+
return
|
|
297
|
+
if self.previousHead is None:
|
|
298
|
+
self.previousHead = (cx, cy)
|
|
299
|
+
px, py = self.previousHead
|
|
300
|
+
|
|
301
|
+
alpha = 0.7
|
|
302
|
+
cx = int(px * (1 - alpha) + cx * alpha)
|
|
303
|
+
cy = int(py * (1 - alpha) + cy * alpha)
|
|
304
|
+
|
|
305
|
+
maxStep = 50
|
|
306
|
+
dx = cx - px
|
|
307
|
+
dy = cy - py
|
|
308
|
+
distance = math.hypot(dx, dy)
|
|
309
|
+
if distance > maxStep:
|
|
310
|
+
steps = int(distance / maxStep)
|
|
311
|
+
for i in range(1, steps + 1):
|
|
312
|
+
ix = int(px + dx * i / steps)
|
|
313
|
+
iy = int(py + dy * i / steps)
|
|
314
|
+
self.points.append((ix, iy))
|
|
315
|
+
self.currentLength += maxStep
|
|
316
|
+
else:
|
|
317
|
+
self.points.append((cx, cy))
|
|
318
|
+
self.currentLength += distance
|
|
319
|
+
|
|
320
|
+
self.previousHead = (cx, cy)
|
|
321
|
+
|
|
322
|
+
while self.currentLength > self.allowedLength:
|
|
323
|
+
if len(self.points) > 1:
|
|
324
|
+
removed_dx = self.points[1][0] - self.points[0][0]
|
|
325
|
+
removed_dy = self.points[1][1] - self.points[0][1]
|
|
326
|
+
removed_dist = math.hypot(removed_dx, removed_dy)
|
|
327
|
+
self.currentLength -= removed_dist
|
|
328
|
+
self.points.pop(0)
|
|
329
|
+
|
|
330
|
+
for i in range(1, len(self.points)):
|
|
331
|
+
cv2.line(
|
|
332
|
+
imgMain, self.points[i-1], self.points[i], self.color, self.lineWidth)
|
|
333
|
+
|
|
334
|
+
snakeHeadColor = (random.randint(0, 255), random.randint(
|
|
335
|
+
0, 255), random.randint(0, 255))
|
|
336
|
+
cv2.circle(imgMain, (cx, cy), self.headSize,
|
|
337
|
+
snakeHeadColor, cv2.FILLED)
|
|
338
|
+
|
|
339
|
+
h, w, _ = imgMain.shape
|
|
340
|
+
margin = 5
|
|
341
|
+
if cx <= margin or cx >= w - margin or cy <= margin or cy >= h - margin:
|
|
342
|
+
self.gameOver = True
|
|
343
|
+
|
|
344
|
+
if obstacleManager:
|
|
345
|
+
for ox, oy, ow, oh, *_ in obstacleManager.obstacles:
|
|
346
|
+
if ox <= cx <= ox + ow and oy <= cy <= oy + oh:
|
|
347
|
+
self.gameOver = True
|
|
348
|
+
|
|
349
|
+
# ---------------- 内部类:食物 ----------------
|
|
350
|
+
class FoodManager:
|
|
351
|
+
def __init__(self, foodPaths, foodNames, foodScores):
|
|
352
|
+
self.foodImages = []
|
|
353
|
+
for path in foodPaths:
|
|
354
|
+
if os.path.exists(path):
|
|
355
|
+
self.foodImages.append(
|
|
356
|
+
cv2.imread(path, cv2.IMREAD_UNCHANGED))
|
|
357
|
+
else:
|
|
358
|
+
self.foodImages.append(np.zeros((50, 50, 4), np.uint8))
|
|
359
|
+
self.foodNames = foodNames
|
|
360
|
+
self.foodScores = foodScores
|
|
361
|
+
self.foodIndex = 0
|
|
362
|
+
self.hFood, self.wFood = 0, 0
|
|
363
|
+
self.foodPoint = 0, 0
|
|
364
|
+
self.randomFoodLocation()
|
|
365
|
+
|
|
366
|
+
def randomFoodLocation(self, obstacleManager=None):
|
|
367
|
+
max_attempts = 100
|
|
368
|
+
for _ in range(max_attempts):
|
|
369
|
+
self.foodPoint = random.randint(
|
|
370
|
+
50, 1230), random.randint(50, 670)
|
|
371
|
+
self.foodIndex = random.randint(0, len(self.foodImages)-1)
|
|
372
|
+
self.hFood, self.wFood, _ = self.foodImages[self.foodIndex].shape
|
|
373
|
+
if obstacleManager:
|
|
374
|
+
overlap = False
|
|
375
|
+
for ox, oy, ow, oh, *_ in obstacleManager.obstacles:
|
|
376
|
+
if ox < self.foodPoint[0] < ox + ow and oy < self.foodPoint[1] < oy + oh:
|
|
377
|
+
overlap = True
|
|
378
|
+
break
|
|
379
|
+
if not overlap:
|
|
380
|
+
return
|
|
381
|
+
return
|
|
382
|
+
|
|
383
|
+
def draw(self, imgMain):
|
|
384
|
+
rx, ry = self.foodPoint
|
|
385
|
+
imgMain = cvzone.overlayPNG(imgMain, self.foodImages[self.foodIndex],
|
|
386
|
+
(rx - self.wFood//2, ry - self.hFood//2))
|
|
387
|
+
return imgMain
|
|
388
|
+
|
|
389
|
+
# ---------------- 内部类:障碍 ----------------
|
|
390
|
+
class ObstacleManager:
|
|
391
|
+
def __init__(self, obstaclePaths):
|
|
392
|
+
self.obstacleImages = []
|
|
393
|
+
for path in obstaclePaths:
|
|
394
|
+
if os.path.exists(path):
|
|
395
|
+
self.obstacleImages.append(
|
|
396
|
+
cv2.imread(path, cv2.IMREAD_UNCHANGED))
|
|
397
|
+
else:
|
|
398
|
+
self.obstacleImages.append(np.zeros((50, 50, 4), np.uint8))
|
|
399
|
+
self.obstacles = []
|
|
400
|
+
|
|
401
|
+
def randomObstacles(self):
|
|
402
|
+
self.obstacles.clear()
|
|
403
|
+
for img in self.obstacleImages:
|
|
404
|
+
h, w, _ = img.shape
|
|
405
|
+
x = random.randint(150, 1230)
|
|
406
|
+
y = random.randint(50, 670)
|
|
407
|
+
dx = random.choice([-5, 5])
|
|
408
|
+
dy = random.choice([-5, 5])
|
|
409
|
+
self.obstacles.append([x, y, w, h, dx, dy, img])
|
|
410
|
+
|
|
411
|
+
def moveObstacles(self, wMax, hMax):
|
|
412
|
+
for obs in self.obstacles:
|
|
413
|
+
x, y, ow, oh, dx, dy, img = obs
|
|
414
|
+
x += dx
|
|
415
|
+
y += dy
|
|
416
|
+
if x <= 0 or x + ow >= wMax:
|
|
417
|
+
dx *= -1
|
|
418
|
+
if y <= 0 or y + oh >= hMax:
|
|
419
|
+
dy *= -1
|
|
420
|
+
obs[0], obs[1], obs[4], obs[5] = x, y, dx, dy
|
|
421
|
+
|
|
422
|
+
def draw(self, imgMain):
|
|
423
|
+
for obs in self.obstacles:
|
|
424
|
+
x, y, w, h, dx, dy, img = obs
|
|
425
|
+
imgMain = cvzone.overlayPNG(imgMain, img, (int(x), int(y)))
|
|
426
|
+
return imgMain
|
|
@@ -13,6 +13,9 @@ import cv2
|
|
|
13
13
|
import numpy as np
|
|
14
14
|
|
|
15
15
|
'''-----------体验课1-----------'''
|
|
16
|
+
import urllib.parse
|
|
17
|
+
import platform
|
|
18
|
+
from io import BytesIO
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
def make(screen):
|
|
@@ -57,9 +60,8 @@ def make(screen):
|
|
|
57
60
|
# 发送创建任务请求
|
|
58
61
|
response = requests.post(create_url, headers=headers,
|
|
59
62
|
data=create_payload.encode("utf-8"))
|
|
60
|
-
response.raise_for_status()
|
|
63
|
+
response.raise_for_status()
|
|
61
64
|
task_id = response.json()["data"]["task_id"]
|
|
62
|
-
# print(f"任务已创建,ID: {task_id}")
|
|
63
65
|
|
|
64
66
|
# 轮询检查任务状态
|
|
65
67
|
query_payload = json.dumps({"task_id": task_id}, ensure_ascii=False)
|
|
@@ -71,16 +73,15 @@ def make(screen):
|
|
|
71
73
|
query_url, headers=headers, data=query_payload.encode("utf-8"))
|
|
72
74
|
response.raise_for_status()
|
|
73
75
|
task_status = response.json()["data"]["task_status"]
|
|
74
|
-
# print(f"任务状态: {task_status}")
|
|
75
76
|
|
|
76
77
|
# 处理任务结果
|
|
77
78
|
if task_status == "SUCCESS":
|
|
78
79
|
picture = requests.get(response.json()[
|
|
79
|
-
|
|
80
|
+
"data"]["sub_task_result_list"][0]["final_image_list"][0]["img_url"])
|
|
80
81
|
image_data = BytesIO(picture.content)
|
|
81
82
|
image = Image.open(image_data)
|
|
82
83
|
image.save('image.gif')
|
|
83
|
-
|
|
84
|
+
open_image("image.gif")
|
|
84
85
|
else:
|
|
85
86
|
print(f"任务失败,状态: {task_status}")
|
|
86
87
|
|
|
@@ -99,14 +100,31 @@ def get_file_content_as_base64(path, urlencoded=False):
|
|
|
99
100
|
return content
|
|
100
101
|
|
|
101
102
|
|
|
103
|
+
def detect_scale():
|
|
104
|
+
"""
|
|
105
|
+
跨平台缩放比例检测
|
|
106
|
+
- Windows: 检测实际 DPI
|
|
107
|
+
- macOS/Linux: 默认返回 1.0
|
|
108
|
+
"""
|
|
109
|
+
if platform.system() == "Windows":
|
|
110
|
+
try:
|
|
111
|
+
user32 = ctypes.windll.user32
|
|
112
|
+
user32.SetProcessDPIAware()
|
|
113
|
+
if hasattr(user32, 'GetDpiForSystem'):
|
|
114
|
+
dpi = user32.GetDpiForSystem()
|
|
115
|
+
return dpi / 96.0
|
|
116
|
+
screen_width = user32.GetSystemMetrics(0)
|
|
117
|
+
return screen_width / 1920.0
|
|
118
|
+
except Exception:
|
|
119
|
+
return 1.0
|
|
120
|
+
else:
|
|
121
|
+
return 1.0
|
|
122
|
+
|
|
123
|
+
|
|
102
124
|
def save_pic(screen, output_file="pic.png"):
|
|
103
125
|
"""
|
|
104
126
|
精准截取turtle绘图区域,不包含窗口边框和标题栏
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
参数:
|
|
108
|
-
screen: turtle的Screen对象
|
|
109
|
-
output_file: 输出文件名
|
|
127
|
+
跨平台支持 (Windows/macOS/Linux)
|
|
110
128
|
"""
|
|
111
129
|
canvas = screen.getcanvas()
|
|
112
130
|
screen.update()
|
|
@@ -118,62 +136,48 @@ def save_pic(screen, output_file="pic.png"):
|
|
|
118
136
|
width = canvas.winfo_width()
|
|
119
137
|
height = canvas.winfo_height()
|
|
120
138
|
|
|
121
|
-
#
|
|
122
|
-
scale_factor =
|
|
123
|
-
# print(f"检测到屏幕缩放比例: {scale_factor}x")
|
|
139
|
+
# 检测屏幕缩放比例
|
|
140
|
+
scale_factor = detect_scale()
|
|
124
141
|
|
|
125
|
-
#
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
title_height = int(
|
|
142
|
+
# Windows 上要扣除边框和标题栏
|
|
143
|
+
border_width = int(
|
|
144
|
+
8 * scale_factor) if platform.system() == "Windows" else 0
|
|
145
|
+
title_height = int(
|
|
146
|
+
30 * scale_factor) if platform.system() == "Windows" else 0
|
|
129
147
|
|
|
130
148
|
# 计算实际绘图区域
|
|
131
149
|
img = ImageGrab.grab(
|
|
132
150
|
bbox=(
|
|
133
|
-
x + border_width,
|
|
134
|
-
y + title_height,
|
|
135
|
-
x + width - border_width,
|
|
136
|
-
y + height - border_width
|
|
151
|
+
x + border_width,
|
|
152
|
+
y + title_height,
|
|
153
|
+
x + width - border_width,
|
|
154
|
+
y + height - border_width
|
|
137
155
|
)
|
|
138
156
|
)
|
|
139
157
|
|
|
140
|
-
# 保存为PNG
|
|
141
158
|
img.save(output_file)
|
|
142
|
-
# print(f"已保存图形到 {output_file} (尺寸: {img.size})")
|
|
143
159
|
except Exception as e:
|
|
144
160
|
print(f"截图时出错: {e}")
|
|
145
|
-
print("提示:
|
|
161
|
+
print("提示: 可以尝试手动截图或使用其他方法")
|
|
146
162
|
|
|
147
163
|
|
|
148
|
-
def
|
|
164
|
+
def open_image(file_path):
|
|
149
165
|
"""
|
|
150
|
-
|
|
151
|
-
|
|
166
|
+
跨平台打开图片
|
|
167
|
+
- Windows: os.startfile
|
|
168
|
+
- macOS: open
|
|
169
|
+
- Linux: xdg-open
|
|
152
170
|
"""
|
|
171
|
+
system = platform.system()
|
|
153
172
|
try:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
#
|
|
159
|
-
|
|
160
|
-
dpi = user32.GetDpiForSystem()
|
|
161
|
-
return dpi / 96.0 # Windows标准DPI是96
|
|
162
|
-
|
|
163
|
-
# 尝试获取显示器DPI (Windows 10及以上)
|
|
164
|
-
if hasattr(user32, 'GetDpiForWindow'):
|
|
165
|
-
root = tk.Tk()
|
|
166
|
-
dpi = user32.GetDpiForWindow(root.winfo_id())
|
|
167
|
-
root.destroy()
|
|
168
|
-
return dpi / 96.0
|
|
169
|
-
|
|
170
|
-
# 兼容方法:获取屏幕尺寸并与标准尺寸比较
|
|
171
|
-
screen_width = user32.GetSystemMetrics(0)
|
|
172
|
-
return screen_width / 1920.0 # 假设标准分辨率为1920x1080
|
|
173
|
+
if system == "Windows":
|
|
174
|
+
os.startfile(file_path)
|
|
175
|
+
elif system == "Darwin": # macOS
|
|
176
|
+
os.system(f"open {file_path}")
|
|
177
|
+
else: # Linux / 其他
|
|
178
|
+
os.system(f"xdg-open {file_path}")
|
|
173
179
|
except Exception as e:
|
|
174
|
-
print(f"
|
|
175
|
-
print("使用默认缩放比例1.0")
|
|
176
|
-
return 1.0
|
|
180
|
+
print(f"打开图片失败: {e}")
|
|
177
181
|
|
|
178
182
|
|
|
179
183
|
'''-----------体验课2-----------'''
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: XMWAI
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.4
|
|
4
4
|
Summary: Small code King AI related library
|
|
5
5
|
Home-page: https://github.com/Tonykai88/XMWAI.git
|
|
6
6
|
Author: pydevelopment
|
|
@@ -17,6 +17,7 @@ Requires-Dist: opencv-python>=3.4.18.65
|
|
|
17
17
|
Requires-Dist: numpy>=1.26.0
|
|
18
18
|
Requires-Dist: flask>=3.1.0
|
|
19
19
|
Requires-Dist: pyecharts>=2.0.8
|
|
20
|
+
Requires-Dist: cvzone>=1.6.1
|
|
20
21
|
Dynamic: author
|
|
21
22
|
Dynamic: author-email
|
|
22
23
|
Dynamic: classifier
|
|
@@ -7,6 +7,7 @@ XMWAI/bomb_core.py
|
|
|
7
7
|
XMWAI/core.py
|
|
8
8
|
XMWAI/idiom_core.py
|
|
9
9
|
XMWAI/magic_core.py
|
|
10
|
+
XMWAI/snake_core.py
|
|
10
11
|
XMWAI/trial_class.py
|
|
11
12
|
XMWAI/web_core.py
|
|
12
13
|
XMWAI.egg-info/PKG-INFO
|
|
@@ -14,6 +15,15 @@ XMWAI.egg-info/SOURCES.txt
|
|
|
14
15
|
XMWAI.egg-info/dependency_links.txt
|
|
15
16
|
XMWAI.egg-info/requires.txt
|
|
16
17
|
XMWAI.egg-info/top_level.txt
|
|
18
|
+
XMWAI/assets/1.png
|
|
19
|
+
XMWAI/assets/__init__.py
|
|
20
|
+
XMWAI/assets/g.png
|
|
21
|
+
XMWAI/assets/h.png
|
|
22
|
+
XMWAI/assets/l.png
|
|
23
|
+
XMWAI/assets/m.png
|
|
24
|
+
XMWAI/assets/s.png
|
|
25
|
+
XMWAI/assets/t.png
|
|
26
|
+
XMWAI/assets/微软雅黑.ttf
|
|
17
27
|
XMWAI/file/__init__.py
|
|
18
28
|
XMWAI/file/idiom.json
|
|
19
29
|
XMWAI/gif/0.gif
|
|
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
|
|
|
3
3
|
|
|
4
4
|
setup(
|
|
5
5
|
name="XMWAI", # 包名(pip install XMWAI)
|
|
6
|
-
version="0.4.
|
|
6
|
+
version="0.4.4", # 每次上传记得升级版本号
|
|
7
7
|
author="pydevelopment", # 作者
|
|
8
8
|
author_email="hekai@xiaoma.cn", # 邮箱
|
|
9
9
|
description="Small code King AI related library", # 简短描述
|
|
@@ -22,6 +22,8 @@ setup(
|
|
|
22
22
|
],
|
|
23
23
|
"XMWAI.gif": ["*.gif"], # gif 文件夹下的所有 GIF
|
|
24
24
|
"XMWAI.file": ["*.json"], # file 文件夹下的 json
|
|
25
|
+
"XMWAI.assets": ["*.png"], # assets 文件夹下的 png
|
|
26
|
+
"XMWAI.assets": ["*.ttf"] # assets 文件夹下的 ttf
|
|
25
27
|
},
|
|
26
28
|
install_requires=[
|
|
27
29
|
"requests>=2.32.3", # 依赖包
|
|
@@ -29,7 +31,8 @@ setup(
|
|
|
29
31
|
"opencv-python>=3.4.18.65", # OpenCV 库
|
|
30
32
|
"numpy>=1.26.0", # 数值计算库
|
|
31
33
|
"flask>=3.1.0", # Web 框架
|
|
32
|
-
"pyecharts>=2.0.8" # 图表绘制库
|
|
34
|
+
"pyecharts>=2.0.8", # 图表绘制库
|
|
35
|
+
"cvzone>=1.6.1" # 手势识别库
|
|
33
36
|
],
|
|
34
37
|
classifiers=[
|
|
35
38
|
"Programming Language :: Python :: 3",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{xmwai-0.4.1 → xmwai-0.4.4}/XMWAI/templates//345/210/233/346/204/217/350/217/234/350/260/261.html"
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|