clip-path 相关的的动画资料汇总

import cv2 import numpy as np import random from collections import deque import mediapipe as mp import json import os from datetime import datetime from PIL import Image, ImageDraw, ImageFont import platform # ------------------------------ # 检测系统并选择合适的中文字体路径 # ------------------------------ def get_chinese_font(): system = platform.system() font_path = None if system == "Windows": font_path = "C:/Windows/Fonts/simhei.ttf" # 黑体 elif system == "Darwin": # macOS font_path = "/System/Library/Fonts/PingFang.ttc" elif system == "Linux": for path in [ "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc", "/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc" ]: if os.path.exists(path): font_path = path break try: return ImageFont.truetype(font_path, 32) if font_path else ImageFont.load_default() except Exception as e: print(f"⚠️ 加载中文字体失败: {e}") return ImageFont.load_default() CHINESE_FONT = get_chinese_font() # ------------------------------ # 在 OpenCV 图像上绘制中文(使用 PIL) # ------------------------------ def put_chinese_text(image, text, position, color=(255, 255, 255), font_size=30): """使用 Pillow 绘制中文文本""" try: if hasattr(CHINESE_FONT, 'path'): font = ImageFont.truetype(CHINESE_FONT.path, font_size) else: font = ImageFont.load_default() print("⚠️ 使用默认字体渲染中文") except: font = ImageFont.load_default() pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) draw = ImageDraw.Draw(pil_image) draw.text(position, text, fill=tuple(color), font=font) return cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR) # ------------------------------ # 排行榜管理 # ------------------------------ RANKING_FILE = "snake_ranking.json" MAX_RECORDS = 100 def load_ranking(): if not os.path.exists(RANKING_FILE): return [] try: with open(RANKING_FILE, 'r', encoding='utf-8') as f: data = json.load(f) seen = set() unique_data = [] for item in data: key = (item.get('score', 0), item.get('timestamp', '')) if key not in seen: seen.add(key) unique_data.append(item) return sorted(unique_data, key=lambda x: x['score'], reverse=True) except Exception as e: print("加载排行榜失败:", e) return [] def save_best_score(score): ranking = load_ranking() current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") new_record = {"score": score, "timestamp": current_time} ranking.append(new_record) seen = set() unique_ranking = [] for r in ranking: key = (r['score'], r['timestamp']) if key not in seen: seen.add(key) unique_ranking.append(r) unique_ranking = sorted(unique_ranking, key=lambda x: x['score'], reverse=True)[:MAX_RECORDS] try: with open(RANKING_FILE, 'w', encoding='utf-8') as f: json.dump(unique_ranking, f, indent=2, ensure_ascii=False) except Exception as e: print("保存排行榜失败:", e) def clear_ranking(): frame = np.zeros((720, 1280, 3), dtype=np.uint8) for y in range(720): color_val = 20 + y // 20 frame[y, :] = [color_val, color_val // 2, 60] h, w = frame.shape[:2] center_x = w // 2 frame = put_chinese_text(frame, "⚠️ 清空所有记录?", (center_x - 240, h // 2 - 60), color=(0, 0, 255), font_size=48) frame = put_chinese_text(frame, "确定要清空吗?(Y=是, N=否)", (center_x - 260, h // 2), color=(255, 255, 255), font_size=36) frame = put_chinese_text(frame, "此操作不可撤销!", (center_x - 180, h // 2 + 50), color=(150, 150, 150), font_size=32) cv2.imshow("Hand-Controlled Snake Game", frame) while True: key = cv2.waitKey(1) & 0xFF if key in (ord('y'), ord('Y')): try: with open(RANKING_FILE, 'w') as f: f.write("[]") return True except Exception as e: print("清空失败:", e) return False elif key in (ord('n'), ord('N'), 27): # ESC return False # ------------------------------ # 主菜单界面 # ------------------------------ def show_ranking_menu(): ranking = load_ranking() frame = np.zeros((720, 1280, 3), dtype=np.uint8) for y in range(720): color_val = 20 + y // 20 frame[y, :] = [color_val, color_val // 2, 60] h, w = frame.shape[:2] center_x = w // 2 frame = put_chinese_text(frame, "🏆 贪吃蛇游戏排行榜 🏆", (center_x - 280, 40), color=(255, 255, 100), font_size=50) frame = put_chinese_text(frame, "名次 得分 时间", (center_x - 240, 90), color=(200, 255, 255), font_size=30) start_y = 140 for i, item in enumerate(ranking[:10]): text = f"{i + 1:2d} {item['score']:4d} {item['timestamp']}" color = (0, 255, 255) if i == 0 else (200, 255, 200) frame = put_chinese_text(frame, text, (center_x - 240, start_y + i * 32), color=color, font_size=28) if len(ranking) == 0: frame = put_chinese_text(frame, "暂无记录...", (center_x - 100, start_y), color=(150, 150, 150), font_size=30) button_w = 200 btn_y1, btn_y2 = h - 140, h - 80 # 开始按钮 start_x1, start_x2 = center_x - button_w - 50, center_x - 50 cv2.rectangle(frame, (start_x1, btn_y1), (start_x2, btn_y2), (0, 180, 0), -1) cv2.rectangle(frame, (start_x1, btn_y1), (start_x2, btn_y2), (0, 255, 0), 3) frame = put_chinese_text(frame, "开始游戏", (center_x - button_w // 2 - 50, h - 100), color=(255, 255, 255), font_size=40) # 退出按钮 quit_x1, quit_x2 = center_x + 50, center_x + button_w + 50 cv2.rectangle(frame, (quit_x1, btn_y1), (quit_x2, btn_y2), (180, 0, 0), -1) cv2.rectangle(frame, (quit_x1, btn_y1), (quit_x2, btn_y2), (255, 0, 0), 3) frame = put_chinese_text(frame, "退出游戏", (center_x + button_w // 2 - 40, h - 100), color=(255, 255, 255), font_size=40) # 清空按钮 clear_x1, clear_x2 = center_x - 100, center_x + 100 cv2.rectangle(frame, (clear_x1, h - 70), (clear_x2, h - 10), (100, 100, 100), -1) cv2.rectangle(frame, (clear_x1, h - 70), (clear_x2, h - 10), (200, 200, 200), 2) frame = put_chinese_text(frame, "清空记录", (center_x - 45, h - 30), color=(255, 255, 255), font_size=32) frame = put_chinese_text(frame, "按'S'开始|'Q'退出|'C'清空", (center_x - 240, h - 160), color=(200, 200, 255), font_size=24) cv2.imshow("Hand-Controlled Snake Game", frame) while True: key = cv2.waitKey(1) & 0xFF if key in (ord('s'), ord('S')): return "start" elif key in (ord('q'), ord('Q'), 27): return "quit" elif key in (ord('c'), ord('C')): result = clear_ranking() return "refresh" # ------------------------------ # 初始化 MediaPipe Hands # ------------------------------ mp_hands = mp.solutions.hands mp_draw = mp.solutions.drawing_utils hands = mp_hands.Hands( static_image_mode=False, max_num_hands=1, min_detection_confidence=0.7, min_tracking_confidence=0.5 ) # ------------------------------ # 游戏参数设置 # ------------------------------ width, height = 1280, 720 snake_speed = 8 snake_length = 3 score = 0 game_over = False walls = [] cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) snake = deque([(width // 2, height // 2)]) direction = np.array([1.0, 0.0]) target_pos = None food_radius = 15 food_color = (0, 255, 0) food = [random.randint(50, width - 50), random.randint(50, height - 50)] # ------------------------------ # 工具函数 # ------------------------------ def is_point_in_wall(x, y, walls): return any(wx <= x <= wx + ww and wy <= y <= wy + wh for (wx, wy, ww, wh) in walls) def check_wall_collision(head, walls): hx, hy = head return any(wx <= hx <= wx + ww and wy <= hy <= wy + wh for (wx, wy, ww, wh) in walls) def generate_food(snake_body, walls): max_attempts = 100 min_dist = 30 for _ in range(max_attempts): x = random.randint(50, width - 50) y = random.randint(50, height - 50) pos = np.array([x, y]) if is_point_in_wall(x, y, walls): continue if any(np.linalg.norm(pos - np.array(seg)) < min_dist for seg in snake_body): continue return [x, y] return [width - 60, height - 60] # BFS 路径可达性检查(略去以保持简洁,实际项目建议保留) # 此处简化为仅距离判断(用于快速测试) def is_path_available(head_pos, food_pos, walls): # 简化版:只要不直接被墙堵死就算通路 return not is_point_in_wall(food_pos[0], food_pos[1], walls) def add_wall_safely(walls_list, snake_body, food_pos): if len(walls_list) >= 5: return walls_list for _ in range(30): ww = random.randint(40, 150) wh = random.randint(40, 150) wx = random.randint(50, width - ww - 50) wy = random.randint(50, height - wh - 50) new_wall = (wx, wy, ww, wh) temp_walls = walls_list + [new_wall] if not is_point_in_wall(snake_body[0][0], snake_body[0][1], temp_walls) and \ not is_point_in_wall(food_pos[0], food_pos[1], temp_walls): walls_list.append(new_wall) break return walls_list # ------------------------------ # 主游戏循环 # ------------------------------ while True: action = show_ranking_menu() if action == "quit": break elif action == "refresh": continue elif action == "start": # 重置游戏 snake.clear() snake.append((width // 2, height // 2)) direction = np.array([1.0, 0.0]) snake_length = 3 score = 0 game_over = False walls = [] target_pos = None food = generate_food(snake, walls) while cap.isOpened(): ret, frame = cap.read() if not ret: break frame = cv2.flip(frame, 1) rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 👇 安全调用 MediaPipe 并检查结果 results = hands.process(rgb_frame) new_target = None # ✅ 关键修复:先检查是否检测到手 if not game_over and results is not None: # ✅ 使用 hasattr 和 None 判断避免 IDE 警告 if hasattr(results, 'multi_hand_landmarks') and results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: mp_draw.draw_landmarks(frame, hand_landmarks, mp_hands.HAND_CONNECTIONS) idx_tip = hand_landmarks.landmark[mp_hands.HandLandmark.INDEX_FINGER_TIP] x, y = int(idx_tip.x * width), int(idx_tip.y * height) # 更新目标点(平滑滤波) if target_pos is None: target_pos = (x, y) else: alpha = 0.3 target_pos = ( int(alpha * x + (1 - alpha) * target_pos[0]), int(alpha * y + (1 - alpha) * target_pos[1]) ) new_target = target_pos # 显示目标点(紫色圆圈) cv2.circle(frame, target_pos, 12, (255, 0, 255), -1) # 移动逻辑 if not game_over: head = np.array(snake[0]) if new_target is not None: to_target = np.array(new_target) - head dist = np.linalg.norm(to_target) if dist > 30: desired_dir = to_target / (dist + 1e-8) curr_dir_norm = direction / (np.linalg.norm(direction) + 1e-8) dot = np.clip(np.dot(curr_dir_norm, desired_dir), -1.0, 1.0) angle = np.arccos(dot) if angle > 0.25: # 最大转向弧度 w1 = np.sin(angle - 0.25) w2 = np.sin(0.25) sin_a = np.sin(angle) blended = (w1 * curr_dir_norm + w2 * desired_dir) / (sin_a + 1e-8) direction = blended / (np.linalg.norm(blended) + 1e-8) else: direction = desired_dir new_head = head + direction * snake_speed new_head = np.round(new_head).astype(int) snake.appendleft(tuple(new_head)) # 碰撞检测 if (check_wall_collision(new_head, walls) or new_head[0] <= 0 or new_head[0] >= width or new_head[1] <= 0 or new_head[1] >= height): game_over = True for i in range(4, len(snake)): seg = np.array(snake[i]) if np.linalg.norm(new_head - seg) < 15: game_over = True break # 吃食物 if np.linalg.norm(new_head - np.array(food)) < (food_radius + 10): old_score = score score += 1 food = generate_food(snake, walls) snake_length += 2 if score // 5 > old_score // 5: walls = add_wall_safely(walls, snake, food) while len(snake) > snake_length: snake.pop() # 绘图部分 for wall in walls: wx, wy, ww, wh = wall cv2.rectangle(frame, (wx, wy), (wx + ww, wy + wh), (255, 255, 0), -1) cv2.rectangle(frame, (wx, wy), (wx + ww, wy + wh), (0, 0, 0), 3) cv2.circle(frame, tuple(food), food_radius, food_color, -1) for i in range(1, len(snake)): alpha = i / len(snake) color = (0, int(255 * (1 - alpha)), int(100 * (1 - alpha))) cv2.line(frame, snake[i - 1], snake[i], color, 8) cv2.circle(frame, snake[0], 10, (255, 255, 255), -1) cv2.circle(frame, snake[0], 8, (0, 150, 0), -1) frame = put_chinese_text(frame, f"得分: {score}", (20, 15), color=(255, 255, 255), font_size=50) if game_over: overlay = frame.copy() cv2.rectangle(overlay, (width // 4, height // 4), (3 * width // 4, 3 * height // 4), (0, 0, 0), -1) cv2.addWeighted(overlay, 0.7, frame, 0.3, 0, frame) frame = put_chinese_text(frame, "游戏结束", (width // 2 - 120, height // 2 - 60), color=(0, 0, 255), font_size=60) frame = put_chinese_text(frame, "按任意键返回主菜单", (width // 2 - 160, height // 2), color=(255, 255, 255), font_size=36) frame = put_chinese_text(frame, f"最终得分: {score}", (width // 2 - 120, height // 2 + 50), color=(255, 255, 0), font_size=32) cv2.imshow("Hand-Controlled Snake Game", frame) cv2.waitKey(0) break cv2.imshow("Hand-Controlled Snake Game", frame) if cv2.waitKey(1) == 27: # ESC break # ------------------------------ # 释放资源 # ------------------------------ cap.release() cv2.destroyAllWindows() hands.close()
11-08
<template> <div class="home-container"> <el-tabs @tab-click="handleTabChange"> <el-tab-pane label="总览"> <div class="tab-content"> <div class="stats-row"> <el-col :span="6"> <el-card class="stat-card danger"> <div class="stat-title">当前通话数</div> <div class="stat-value">0</div> <div class="stat-sub"> 较昨日: <span style="color: #f56c6c">0</span> </div> </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> <div class="stat-title">今日通话数</div> <div class="stat-value">0</div> <div class="stat-sub"> 较昨日: <span style="color: #67c23a">0</span> </div> </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> <div class="stat-title">历史通话数</div> <div class="stat-value">0</div> <div class="stat-sub"> 较昨日: <span style="color: #67c23a">0</span> </div> </el-card> </el-col> <el-col :span="6"> <el-card class="stat-card"> <div class="stat-title">当前线路数</div> <div class="stat-value">0</div> <div class="stat-sub"> 较昨日: <span style="color: #67c23a">0</span> </div> </el-card> </el-col> </div> <div class="table-card"> <el-table :data="summaryTable" border> <el-table-column prop="label" label="指标"></el-table-column> <el-table-column prop="value" label="数值"></el-table-column> </el-table> </div> </div> </el-tab-pane> <el-tab-pane label="省份统计"> <div class="tab-content"> <el-table :data="provinceTable" border> <el-table-column prop="province" label="省份"></el-table-column> <el-table-column prop="currentCall" label="当前通话数" ></el-table-column> <el-table-column prop="todayCall" label="今日通话数" ></el-table-column> <el-table-column prop="historyCall" label="历史通话数" ></el-table-column> <el-table-column prop="currentLine" label="当前线路数" ></el-table-column> <el-table-column prop="circuit" label="电路线路数" ></el-table-column> <el-table-column prop="network" label="网络线路数" ></el-table-column> <el-table-column prop="todayLine" label="今日线路数" ></el-table-column> <el-table-column prop="todayCircuit" label="今日电路线路数" ></el-table-column> <el-table-column prop="todayNetwork" label="今日网络线路数" ></el-table-column> <el-table-column prop="historyLine" label="历史线路数" ></el-table-column> <el-table-column prop="historyCircuit" label="历史电路线路数" ></el-table-column> <el-table-column prop="historyNetwork" label="历史网络线路数" ></el-table-column> </el-table> </div> </el-tab-pane> <el-tab-pane label="趋势分析"> <div class="tab-content"> <div class="chart-placeholder"> <div class="mock-chart"> <div class="chart-line-container"> <div class="chart-line通话"></div> <div class="chart-line线路"></div> </div> <div class="chart-legend"> <span style="color: teal">通话数</span> | <span style="color: purple">线路数</span> </div> <div class="chart-buttons"> <el-button size="mini">近7天</el-button> <el-button size="mini">近30天</el-button> </div> </div> </div> </div> </el-tab-pane> </el-tabs> </div> </template> <script> import { userlist, getsuperes } from "@/utils/https.js"; export default { name: "HomeView", data() { return { summaryTable: [], provinceTable: [ { province: "江苏", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, { province: "上海", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, { province: "浙江", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, { province: "安徽", currentCall: 0, todayCall: 0, historyCall: 0, currentLine: 0, circuit: 0, network: 0, todayLine: 0, todayCircuit: 0, todayNetwork: 0, historyLine: 0, historyCircuit: 0, historyNetwork: 0, }, ], superEnterpriseList: [], // 新增的超级企业列表数据 }; }, mounted() { this.loadHomeData(); this.loadSuperEnterpriseList(); // 调用获取超级企业列表的方法 }, methods: { loadHomeData() { userlist() .then(data => { this.summaryTable = data.summary || []; this.provinceTable = data.provinces || this.provinceTable; }) .catch(error => { console.error("加载首页数据失败:", error); this.$message.error("加载数据失败"); }); }, loadSuperEnterpriseList() { getsuperes() .then(response => { this.superEnterpriseList = response.data || []; console.log('超级企业列表:', this.superEnterpriseList); }) .catch(error => { console.error('获取超级企业列表失败:', error); this.$message.error('获取超级企业列表失败'); }); }, handleTabChange(tab) { console.log("切换到:", tab.name); }, handleSizeChange(val) { this.pageSize = val; }, handleCurrentChange(val) { this.currentPage = val; }, }, }; </script> <style scoped> :root { --main-bg-color: #f5f7fa; --tab-bg-color: #ffffff; --stat-border-color: #f56c6c; } .home-container { padding: 20px; background: var(--main-bg-color); min-height: calc(100vh - 64px); } .tab-wrapper { background: var(--tab-bg-color); border: 1px solid #ebeef5; border-radius: 4px; } .tab-content { padding: 20px; border-top: none; } .stats-row { margin-top: 10px; } .stat-card { height: 160px; display: flex; flex-direction: column; justify-content: center; align-items: center; } .stat-card.danger { border-left: 4px solid var(--stat-border-color); } .stat-title { font-size: 16px; font-weight: 500; margin-bottom: 10px; } .stat-value { font-size: 24px; color: #303133; margin-bottom: 10px; } .stat-sub { font-size: 14px; color: #909399; } .table-card { padding: 20px; } .chart-placeholder { text-align: center; padding: 40px 0; } .mock-chart { position: relative; height: 300px; width: 100%; } .chart-line-container { position: absolute; bottom: 40px; left: 10%; width: 80%; height: 200px; border-bottom: 1px solid #e0e0e0; border-left: 1px solid #e0e0e0; } .chart-line通话 { position: absolute; bottom: 0; width: 100%; height: 30%; background: linear-gradient(to top, rgba(0, 128, 128, 0.2) 0%, teal 100%); clip-path: polygon( 0% 100%, 5% 80%, 10% 60%, 15% 70%, 20% 50%, 25% 60%, 30% 40%, 35% 50%, 40% 30%, 45% 40%, 50% 20%, 55% 30%, 60% 10%, 65% 20%, 70% 0%, 75% 10%, 80% 30%, 85% 20%, 90% 40%, 95% 30%, 100% 50%, 100% 100% ); } .chart-line线路 { position: absolute; bottom: 0; width: 100%; height: 60%; background: linear-gradient(to top, rgba(128, 0, 128, 0.2) 0%, purple 100%); clip-path: polygon( 0% 100%, 5% 90%, 10% 70%, 15% 80%, 20% 60%, 25% 70%, 30% 50%, 35% 60%, 40% 40%, 45% 50%, 50% 30%, 55% 40%, 60% 20%, 65% 30%, 70% 10%, 75% 20%, 80% 40%, 85% 30%, 90% 50%, 95% 40%, 100% 60%, 100% 100% ); } .chart-legend { position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); } .chart-buttons { position: absolute; bottom: -20px; left: 50%; transform: translateX(-50%); } .server-select, .province-select { width: 160px; margin-bottom: 20px; } </style>纠错
08-01
六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)内容概要:本文档围绕六自由度机械臂的ANN人工神经网络设计展开,详细介绍了正向与逆向运动学求解、正向动力学控制以及基于拉格朗日-欧拉法推导逆向动力学方程的理论与Matlab代码实现过程。文档还涵盖了PINN物理信息神经网络在微分方程求解、主动噪声控制、天线分析、电动汽车调度、储能优化等多个工程与科研领域的应用案例,并提供了丰富的Matlab/Simulink仿真资源和技术支持方向,体现了其在多学科交叉仿真与优化中的综合性价值。; 适合人群:具备一定Matlab编程基础,从事机器人控制、自动化、智能制造、电力系统或相关工程领域研究的科研人员、研究生及工程师。; 使用场景及目标:①掌握六自由度机械臂的运动学与动力学建模方法;②学习人工神经网络在复杂非线性系统控制中的应用;③借助Matlab实现动力学方程推导与仿真验证;④拓展至路径规划、优化调度、信号处理等相关课题的研究与复现。; 阅读建议:建议按目录顺序系统学习,重点关注机械臂建模与神经网络控制部分的代码实现,结合提供的网盘资源进行实践操作,并参考文中列举的优化算法与仿真方法拓展自身研究思路。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值