当前位置: 首页 > news >正文

从PNG到CUR:开源游戏鼠标指针美化工具的技术实现与实战

1. 项目概述与核心价值

最近在折腾一个挺有意思的开源项目,叫“Reverse1999-Kursor”。乍一看这个名字,可能有点摸不着头脑,又是“文学萌”(bungaku-moe),又是“1999”,还有个“Kursor”。简单来说,这是一个为热门手游《重返未来:1999》设计的自定义鼠标指针美化工具。如果你是这个游戏的玩家,并且对千篇一律的系统鼠标指针感到审美疲劳,想给自己的桌面操作增添一点游戏内的仪式感和沉浸感,那这个项目就完全对上了你的需求。

它的核心功能,就是允许你将游戏《重返未来:1999》中的各种UI元素、角色标志、神秘术图标等素材,替换成你电脑上的鼠标指针。想象一下,当你日常办公或浏览网页时,你的鼠标变成了游戏里熟悉的“司辰”标志、或是某个你钟爱角色的代表性符号,那种微妙的联结感会让作为玩家的你会心一笑。这本质上属于“游戏周边文化”与“桌面个性化”交叉的一个小领域,技术门槛不高,但非常注重细节和趣味性,深受那些热爱美化桌面、追求独特体验的玩家喜爱。

这个项目托管在GitHub上,由“bungaku-moe”组织维护。从名字就能看出,团队偏向于“文学”与“萌”文化,其作品也多与ACGN(动画、漫画、游戏、小说)内容的美化、工具相关。因此,这个项目不仅仅是一个冷冰冰的转换工具,它更包含着创作者对游戏内容的理解和热爱,最终产出的是具有独特风格的美化方案。接下来,我会从技术实现、素材处理、实际应用以及常见问题这几个层面,带你彻底拆解这个项目,让你不仅能轻松用上这些精美的指针,更能理解背后的原理,甚至自己动手制作属于你的独一无二的指针方案。

2. 项目核心机制与实现原理拆解

2.1 鼠标指针文件格式与标准解析

要理解这个工具在做什么,首先得知道Windows系统下的鼠标指针是怎么回事。我们日常看到的那个箭头,其实并不是一个简单的图片文件。Windows使用的光标文件格式是.cur(静态光标)和.ani(动态光标)。.cur文件本质上是一种特殊的位图资源,它除了包含图像数据(通常是PNG或BMP格式的)之外,还必须包含一个至关重要的信息:“热点”(Hot Spot)。

你可以把“热点”理解为这个指针图片的“点击点”。比如,最常见的箭头指针,其热点就在箭头的尖端。当你点击按钮时,系统识别的点击位置是热点所在的那个像素点,而不是整个图片的左上角或其他位置。如果热点设置错误,就会出现“你以为点中了,但实际上没点到”的尴尬情况,用户体验会非常糟糕。.ani文件则更为复杂,它相当于一个多帧的.cur序列,可以实现指针的动画效果,比如沙漏等待指针的旋转。

那么,这个项目的核心工作流程就清晰了:它将《重返未来:1999》游戏中的静态图片素材(如PNG),通过一系列处理,封装成符合Windows标准的.cur.ani文件,并正确设置其热点位置。这听起来简单,但其中涉及到图像处理、资源编译和系统注册等多个环节。

2.2 工具链与自动化处理流程

项目通常不会要求用户手动使用Photoshop和晦涩的资源编译器来制作指针。为了提升用户体验,开发者会构建一个工具链,实现“一键化”或“半自动化”的转换。这个流程一般包含以下几步:

  1. 素材提取与规整:首先需要从《重返未来:1999》的游戏资源文件中,提取出合适的UI图标、Logo等。这可能需要一些游戏解包工具(注意版权和用户协议,仅用于个人学习与美化)。提取出的素材往往是尺寸不一、背景不透明的PNG序列(对于动画)或单张图片。
  2. 图像预处理:这是非常关键的一步。鼠标指针通常需要是背景透明的,并且尺寸不宜过大(常见尺寸如32x32, 48x48, 64x64像素)。原始游戏素材可能尺寸很大,或者带有底色。因此,需要使用图像处理工具(如Python的PIL/Pillow库,或开源工具GIMP的脚本功能)进行批量处理:调整尺寸、剥离背景(如果需要)、优化边缘抗锯齿。对于动态指针,还需要将动画序列分解为单帧图片,并确保每一帧的尺寸和热点对齐。
  3. 热点坐标定义:这是最具主观性和经验性的环节。对于不同类型的指针,热点位置不同。例如:
    • 普通箭头/链接选择:热点在指尖。
    • 手型指针:热点在食指指尖。
    • 文本输入I型光标:热点在竖线底部。
    • 十字精度选择:热点在十字中心。 开发者需要根据每个素材的视觉设计,判断并指定一个合理的(x, y)坐标。这个坐标信息通常会写在一个配置文件(如ini,jsonxml)里,与图片文件一一对应。
  4. 编译生成光标文件:这是技术核心。通过一个编译工具,将预处理好的图片和配置文件中的热点信息,打包成.cur.ani文件。在Windows环境下,传统上可以使用Resource Hacker或微软的RC编译器配合资源脚本(.rc文件)。但在开源和跨平台趋势下,更常见的做法是使用像cur2pngpng2cur这类开源命令行工具,或者直接使用Python的win32api等库进行编程生成,以实现批量和自动化。
  5. 打包与部署脚本:最后,将生成的所有光标文件,按照Windows指针方案的结构进行组织,并编写一个安装脚本(通常是.inf文件或一个简单的批处理.bat文件)。用户只需右键点击安装文件,选择“安装”,系统就会自动将这些指针文件复制到系统目录,并注册到鼠标属性设置中供用户选用。

注意:直接修改系统文件存在一定风险。优秀的项目会提供完整的还原方案,比如一个“卸载”脚本,能够将指针设置恢复为系统默认,避免因指针文件错误导致操作困难。

3. 从素材到指针:详细实操步骤

假设我们现在手头有一些从《重返未来:1999》中提取的、已经处理好的透明背景PNG图标,目标是制作一套完整的指针方案。以下是一个基于常见开源工具链的实操流程。

3.1 环境准备与工具选型

我们选择一条以Python为核心、依赖开源命令行工具的路径,它跨平台且易于脚本化。

  1. 安装Python:确保系统已安装Python 3.6及以上版本。
  2. 安装Pillow库:用于图像处理。在命令行中执行pip install Pillow
  3. 获取光标编译工具:我们需要一个能将图片+热点信息转换为.cur的工具。例如,可以使用开源工具png2cur。你可能需要从GitHub等平台找到其源码并编译,或者直接下载他人编译好的可执行文件(务必从可信来源下载)。假设我们得到的可执行文件名为png2cur.exe,将其放在一个方便调用的目录,或加入系统环境变量。
  4. 准备素材目录:创建一个项目文件夹,例如Reverse1999_Cursors。在里面建立子文件夹:
    • src_png/:存放所有源PNG图片。
    • config/:存放热点配置文件。
    • output_cur/:用于存放生成的.cur文件。
    • final_package/:最终打包的安装包。

3.2 素材预处理与热点配置

将你的PNG素材放入src_png/。假设我们有一个箭头素材arrow.png,尺寸为64x64像素,我们希望热点在(50, 10)的位置(即从左上角算起,向右50像素,向下10像素)。

我们需要创建一个配置文件来关联素材和热点。一个简单的方式是使用JSON格式。在config/下创建hotspots.json

{ "scheme_name": "Reverse1999 - 司辰之仪", "author": "YourName", "pointers": [ { "src_file": "arrow.png", "cursor_name": "Normal Select", "output_file": "arrow.cur", "hotspot_x": 50, "hotspot_y": 10 }, { "src_file": "hand.png", "cursor_name": "Link Select", "output_file": "hand.cur", "hotspot_x": 15, "hotspot_y": 5 } // ... 添加更多指针配置 ] }

这里,cursor_name最好遵循Windows标准指针的命名,以便系统正确识别和替换,例如:“Normal Select”(正常选择)、“Link Select”(链接选择)、“Text Select”(文本选择)、“Busy”(忙)等。

如果素材尺寸不合适,我们可以编写一个简单的Python脚本进行批量调整。创建resize_images.py

from PIL import Image import os import json config_path = './config/hotspots.json' src_dir = './src_png/' output_dir = './src_png_resized/' # 新建一个目录存放调整后的图片 os.makedirs(output_dir, exist_ok=True) with open(config_path, 'r', encoding='utf-8') as f: config = json.load(f) target_size = (32, 32) # 统一调整到32x32,这是最安全的指针尺寸 for ptr in config['pointers']: src_path = os.path.join(src_dir, ptr['src_file']) if os.path.exists(src_path): img = Image.open(src_path) # 保持比例调整大小,使用高质量的Lanczos重采样算法 img.thumbnail(target_size, Image.Resampling.LANCZOS) # 创建一个新的透明底画布 new_img = Image.new('RGBA', target_size, (0, 0, 0, 0)) # 将调整后的图片粘贴到画布中央 paste_x = (target_size[0] - img.size[0]) // 2 paste_y = (target_size[1] - img.size[1]) // 2 new_img.paste(img, (paste_x, paste_y), img) # 最后一个参数是遮罩,用于透明通道 # 保存调整后的图片,覆盖原配置中的文件名指向(或使用新文件名) resized_path = os.path.join(output_dir, ptr['src_file']) new_img.save(resized_path, 'PNG') print(f"Resized and centered: {ptr['src_file']}") # 更新热点坐标!因为图片尺寸和位置变了,热点需要等比例调整。 scale_x = img.size[0] / target_size[0] scale_y = img.size[1] / target_size[1] # 这是一个简化计算,假设热点相对于原图内容的位置比例不变 # 更精确的做法需要根据粘贴位置(paste_x, paste_y)重新计算 # 此处为示例,实际项目需要更严谨的坐标转换逻辑 ptr['hotspot_x'] = int(ptr['hotspot_x'] * scale_x) + paste_x ptr['hotspot_y'] = int(ptr['hotspot_y'] * scale_y) + paste_y else: print(f"Warning: Source file not found - {ptr['src_file']}") # 保存更新了热点坐标的配置(可选,或新建一个配置) with open('./config/hotspots_resized.json', 'w', encoding='utf-8') as f: json.dump(config, f, indent=2, ensure_ascii=False) print("Image resizing and hotspot adjustment complete.")

实操心得:热点坐标的转换是整个流程中最容易出错的地方。上述脚本中的坐标转换是一个简化示例。在真实项目中,建议在图像预处理阶段就固定好画布尺寸和素材位置,然后直接在固定尺寸的画布上用图像编辑软件(如GIMP)目测确定热点坐标,并记录到配置中,这样可以避免复杂的坐标换算,减少错误。

3.3 编译生成光标文件

有了调整好的图片和最终的热点配置,我们就可以调用png2cur工具进行编译。编写一个批处理脚本build_cursors.bat(Windows)或Shell脚本build_cursors.sh(Linux/macOS,但生成的.cur文件主要用于Windows)。

以Windows批处理为例:

@echo off setlocal enabledelayedexpansion set PNG2CUR_PATH=C:\Tools\png2cur.exe REM 请修改为你的png2cur实际路径 set CONFIG_FILE=config\hotspots_resized.json set SRC_DIR=src_png_resized set OUTPUT_DIR=output_cur if not exist %OUTPUT_DIR% mkdir %OUTPUT_DIR% REM 这里需要一个能解析JSON的简单方法。我们可以用Python来驱动。 REM 创建一个Python脚本 build.py 来执行更复杂的逻辑会更方便。 echo 请使用Python脚本进行构建,此批处理文件仅作示意。 pause

实际上,更高效的做法是直接用一个Python脚本完成所有工作:读取配置、调用子进程执行png2cur命令。创建build.py

import json import os import subprocess config_path = './config/hotspots_resized.json' src_dir = './src_png_resized/' output_dir = './output_cur/' png2cur_exe = r'C:\Tools\png2cur.exe' # 修改为你的路径 os.makedirs(output_dir, exist_ok=True) with open(config_path, 'r', encoding='utf-8') as f: config = json.load(f) for ptr in config['pointers']: src_png = os.path.join(src_dir, ptr['src_file']) output_cur = os.path.join(output_dir, ptr['output_file']) x, y = ptr['hotspot_x'], ptr['hotspot_y'] if not os.path.exists(src_png): print(f"Error: Source PNG not found for {ptr['cursor_name']}") continue # 构建命令行参数。png2cur工具的参数格式可能类似:png2cur input.png output.cur -x 50 -y 10 # 请根据你使用的工具实际参数进行调整。 cmd = [png2cur_exe, src_png, output_cur, '-x', str(x), '-y', str(y)] try: result = subprocess.run(cmd, capture_output=True, text=True, check=True) print(f"Success: {ptr['cursor_name']} -> {ptr['output_file']}") except subprocess.CalledProcessError as e: print(f"Failed to build {ptr['cursor_name']}: {e.stderr}") except FileNotFoundError: print(f"Error: png2cur tool not found at {png2cur_exe}. Please check the path.") break print("Build process finished.")

运行这个脚本,你就能在output_cur/目录下得到一系列.cur文件。

3.4 创建安装信息文件(.INF)

为了让Windows系统识别并安装这套指针方案,我们需要一个安装信息文件。在final_package/目录下创建Reverse1999_Kursor.inf

[Version] signature="$CHICAGO$" AdvancedINF=2.5 [DefaultInstall] CopyFiles = Scheme.Cur, Scheme.Sys AddReg = Scheme.Reg [DestinationDirs] Scheme.Cur = 10,"%CUR_DIR%" Scheme.Sys = 10,"%SYS_DIR%" ; 定义变量,便于管理 [Strings] CUR_DIR = "Cursors" SYS_DIR = "System32" SCHEME_NAME = "Reverse1999 - 司辰之仪" ; 复制文件段 [Scheme.Cur] "arrow.cur" "hand.cur" ; ... 列出所有.cur文件 [Scheme.Sys] ; 如果需要替换系统级指针(不推荐),可在此列出,但一般用户方案只需放在Cursors目录 ; 注册表段,将方案添加到鼠标属性 [Scheme.Reg] HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Control Panel\Cursors\Schemes","%SCHEME_NAME%",,"%CUR_DIR%\arrow.cur,%CUR_DIR%\help.cur,%CUR_DIR%\work.cur,%CUR_DIR%\busy.cur,%CUR_DIR%\cross.cur,%CUR_DIR%\Text.cur,%CUR_DIR%\Hand.cur,%CUR_DIR%\Unavail.cur,%CUR_DIR%\Vert.cur,%CUR_DIR%\Horz.cur,%CUR_DIR%\Dgn1.cur,%CUR_DIR%\Dgn2.cur,%CUR_DIR%\move.cur,%CUR_DIR%\Alt.cur,%CUR_DIR%\Link.cur" [SourceDisksNames] 55="Reverse1999 Cursors","",1 [SourceDisksFiles] arrow.cur=55 hand.cur=55 ; ... 对应所有文件

这个.inf文件定义了文件复制路径和注册表信息。其中注册表项Schemes下的字符串值,其名称就是方案名(SCHEME_NAME),值是一长串以逗号分隔的.cur文件路径,分别对应“正常选择”、“帮助选择”、“后台运行”等十余种标准指针状态。顺序非常重要,必须与Windows定义的顺序一致。

最后,将output_cur/下的所有.cur文件复制到final_package/目录,与.inf文件放在一起。右键点击Reverse1999_Kursor.inf,选择“安装”,系统会提示安装驱动程序,点击确认即可。安装完成后,进入“设置 -> 蓝牙和其他设备 -> 鼠标 -> 其他鼠标设置 -> 指针”,就可以在方案下拉列表中看到并选择“Reverse1999 - 司辰之仪”了。

4. 常见问题、排查技巧与深度优化

4.1 安装后指针不显示或显示异常

这是最常见的问题,可能的原因和排查步骤如下:

  1. 文件路径或名称错误:检查.inf文件中[Scheme.Cur]节列出的文件名是否与final_package/目录下的.cur文件完全一致(包括大小写)。检查[DestinationDirs]中定义的目录是否正确。用户方案通常复制到%CUR_DIR%(即C:\Windows\Cursors\)。
  2. 热点设置不合理:热点坐标超出了图像范围。例如,一个32x32的图片,热点坐标设为(40,40)。这会导致指针行为诡异。使用一些光标预览工具(如Cursor Editor)打开生成的.cur文件,检查热点位置是否在图像可见区域内且位置合理。
  3. 指针状态顺序错误.inf文件中注册表项那长串路径的顺序至关重要。如果“正常选择”和“链接选择”的文件顺序放反了,就会导致点击链接时显示箭头,平时却显示手型。请严格按照Windows标准指针顺序排列。一个常见的正确顺序参考如下表:
顺序指针状态 (英文)指针状态 (中文描述)
1Normal Select正常选择
2Help Select帮助选择
3Working In Background后台运行
4Busy
5Precision Select精度选择
6Text Select文本选择
7Handwriting手写
8Unavailable不可用
9Vertical Resize垂直调整
10Horizontal Resize水平调整
11Diagonal Resize 1对角线调整 1
12Diagonal Resize 2对角线调整 2
13Move移动
14Alternate Select候选选择
15Link Select链接选择
  1. 权限问题:如果尝试替换系统默认指针(%SYS_DIR%),需要管理员权限,且风险较高,可能导致系统恢复点失效或出现意外错误。强烈建议仅安装为用户方案,这样更安全,也便于卸载。
  2. 缓存问题:安装后,有时需要注销或重启资源管理器(任务管理器 -> 重启“Windows资源管理器”进程)才能使新方案生效。

4.2 如何制作动态光标(.ani)

动态光标.ani的制作更复杂一些。你需要准备一个图片序列(多帧PNG),并且每一帧都可以有独立的热点(但通常所有帧使用同一热点)。.ani文件还包含帧速率(每帧显示时间)和步进方式(是否循环、如何循环)等信息。

有一些专门的工具可以编辑.ani文件,如AniTunerMicroangelo等。在开源自动化流程中,可能需要使用更底层的库或工具。一个可行的思路是:先将所有帧图片和热点信息生成多个.cur文件,然后使用工具(如cur2ani)将这些.cur文件合并成一个.ani,并指定帧速率。这通常需要更专门的脚本或工具支持,超出了基础流程的范围。对于“Reverse1999-Kursor”这类项目,初期可能只提供静态指针,动态指针属于进阶内容。

4.3 风格统一与视觉设计建议

一套好的指针方案,不仅仅是替换图标,更要注重统一性和可用性。

  1. 尺寸统一:尽量将所有指针的视觉大小控制在相近的范围内。一个巨大的“正常选择”箭头配一个微小的“文本选择”竖线,会非常不协调。
  2. 色彩与风格:紧扣《重返未来:1999》的游戏美术风格——复古、神秘、带有欧式装饰艺术感。可以使用游戏UI的主色调(如暗金色、墨绿色、象牙白),并融入游戏中的标志性图形元素,如“基金会”徽记、神秘术回路图案、时代尘埃的颗粒感等。
  3. 识别度优先:指针的首要功能是操作指示。无论设计得多好看,必须保证每种状态(选择、链接、忙碌、移动等)能被用户快速、无误地识别。避免为了追求美观而让“链接选择”和“正常选择”过于相似。
  4. 为高DPI屏幕优化:现代屏幕分辨率很高,建议提供多套尺寸的指针方案(如32x32, 48x48, 64x64),或者在.inf安装时根据系统缩放比例自动选择,以在高分屏上保持清晰。

4.4 进阶:使用资源脚本(.rc)和编译器

对于追求极致控制或需要集成到更大安装包的项目,可以使用微软官方的资源编译方式。

  1. 创建一个资源脚本文件cursors.rc,用文本编辑器编写:
    #include <windows.h> // 定义光标资源ID #define IDC_ARROW 101 #define IDC_HAND 102 // 声明光标资源 IDC_ARROW CURSOR DISCARDABLE "output_cur\\arrow.cur" IDC_HAND CURSOR DISCARDABLE "output_cur\\hand.cur"
  2. 使用微软的资源编译器rc.exe编译.rc文件为.res文件:rc cursors.rc
  3. 如果需要,可以将.res文件链接到DLL或EXE中,或者使用其他工具进行封装。

这种方式更底层,是传统Windows开发的做法,对于纯指针方案包来说,.inf文件的方式对普通用户更加友好。

5. 项目维护与社区生态构建

一个开源的美化项目,其生命力在于持续的维护和活跃的社区。

  1. 版本管理与游戏更新同步:《重返未来:1999》会不断推出新版本、新角色、新活动。对应的,指针方案也可以更新,加入新的角色主题指针(例如,以“红弩箭”的火箭图标作为“忙”状态,以“泥鯭的士”的出租车作为“移动”状态)。项目需要建立清晰的版本号体系,与游戏版本或自身更新内容关联。
  2. 模块化与主题包:可以设计成核心工具+主题包的模式。核心工具负责安装、管理和卸载框架;主题包则是具体的指针素材集合。用户可以选择安装“1.1版本经典UI主题”、“六星角色主题合集”等,增加可玩性。
  3. 提供自定义教程:在项目Wiki或README中,详细提供从零开始制作自定义指针的教程(即本文所阐述内容的简化版),鼓励用户贡献自己创作的指针方案。可以建立模板和素材规范,降低创作门槛。
  4. 安全与信任:由于涉及修改系统设置和文件,必须在项目显著位置声明安全条款:本工具仅修改用户级的鼠标方案,不篡改系统核心文件,并提供一键还原功能。所有代码开源,可供审查。发布安装包时,建议使用代码签名证书(如果条件允许)来减少系统的安全警告。
  5. 反馈与问题收集:建立Issues模板,引导用户反馈问题时提供系统版本、屏幕缩放比例、安装步骤截图等信息,便于快速定位问题。对于常见的安装失败、显示异常问题,整理成FAQ文档。

通过这样从技术实现到用户体验,再到社区运营的完整闭环,一个像“Reverse1999-Kursor”这样的开源桌面美化项目,才能从一个简单的创意,成长为一个受玩家社区喜爱、持续焕发生机的作品。它不仅仅是替换了几个图标,更是玩家将游戏情感延伸至数字生活空间的一座桥梁。

http://www.jsqmd.com/news/822940/

相关文章:

  • 2026 软文发稿平台避坑指南!五大主流平台深度测评,GEO中小企业必看 - 速递信息
  • 盒马提货券回收主流操作方法,选择契合的处置路径 - 京回收小程序
  • 从扫地机到自动驾驶:一文读懂语义地图如何让机器人‘看懂’世界
  • 河北东风养殖品牌介绍,靠谱吗? - 工业推荐榜
  • 三步构建高效笔记迁移系统:Obsidian Importer完全指南
  • 独立开发者如何借助Taotoken的Token Plan有效控制月度AI支出
  • 如何快速上手PCL点云库:10个核心模块详解与实践
  • 城隍庙玉石街:老板直言,十万以下别谈种水 - 奢侈品回收测评
  • DeepSeek RAG pipeline重构实录,KISS检查挽救了87%的推理延迟——从2300ms到290ms的极简跃迁
  • Modbus云网关:云端集中管控,免费搭建组态园区场景
  • 终极指南:使用MoocDownloader离线保存中国大学MOOC课程
  • 东风养殖场专业不专业?值得信赖不? - 工业推荐榜
  • Vue3-DateTime-Picker:企业级日期时间选择器的5大架构创新与实战指南
  • 基于GitOps的API网关治理实践:从配置即代码到策略即代码
  • linux 设备目录/dev 学习
  • 如何使用Redis优化Trigger.dev任务队列:提升AI工作流性能的完整指南
  • 为hermes agent配置taotoken自定义供应商的完整流程
  • 模型下载与转换实战:从HuggingFace到GGUF/SafeTensors,格式、量化与校验全解析
  • 物联网服务选型指南:从核心模块解析到实战避坑
  • 别让电源拖后腿!手把手教你用Sigrity PowerDC搞定PCB直流压降仿真(附HyperLynx SPD转换指南)
  • 甘肃大手印玫瑰科技的玫瑰精油美妆产品性价比高不高? - myqiye
  • OpenMC多群截面计算深度解析:传输修正合并的3种解决方案与性能优化实战
  • Six Degrees of Wikipedia完全教程:从零开始探索维基百科的六度分离
  • 星链引擎:企业级营销 SaaS 混合多租户架构设计与工程化落地
  • MoneyPrinterTurbo:智能AI视频生成工具的革命性解决方案
  • 2025届必备的十大AI写作工具实际效果
  • 如何快速掌握RSA参数计算:密码学开发的终极指南
  • BaklavaJS执行引擎详解:实现节点图的拓扑排序与数据流计算 [特殊字符]
  • 告别繁琐宏命令!GSE插件如何让魔兽世界技能管理变得轻松智能
  • 如何快速构建CLIP-as-service机器学习平台:与Kubeflow和MLflow的完整整合指南