ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

为 Vision Agent 编写自定义工具:模板匹配(Template Matching)Custom Tool 实战指南

为 Vision Agent 编写自定义工具:模板匹配(Template Matching)Custom Tool 实战指南 为 Vision Agent 编写自定义工具模板匹配Template MatchingCustom Tool 实战指南【免费下载链接】vision-agentThis tool has been deprecated. Use Agentic Document Extraction instead.项目地址: https://gitcode.com/GitHub_Trending/vi/vision-agent导读本指南以 examples/custom_tools/README.md 为主线完整讲解如何在 vision-agent 中开发一个模板匹配Template Matching自定义视觉工具并让VisionAgentCoderV2在求解问题时自动调用它。读完本文你将掌握自定义工具的注册方式、register_tool中 imports 参数的底层原理独立进程代码注入机制、旋转模板匹配算法的完整实现细节以及如何在对话中显式指定工具以获得稳定可靠的结果。一、示例概览这个 Custom Tool 能做什么官方在 examples/custom_tools/README.md 中提供了一个名为Template Matching Custom Tool的演示项目。它的业务目标是让 Vision Agent 使用自定义的template_match_工具在大图pid.png中找到小模板图pid_template.png出现的位置并进一步回答是否有匹配结果靠近 NOTE 5 区域这类空间关系问题。模板匹配本身并不是 Agent 内置工具列表里的能力而是由开发者通过register_tool机制注入给 Agent 的自定义工具。这一模式说明了 vision-agent 的工具系统是开放、可扩展的你可以把任意 Python 视觉算法封装成工具交给 Agent 在生成代码时按需调用。对应的示例目录examples/custom_tools/包含四个关键文件文件作用run_custom_tool.py自定义工具的注册代码 启动 Agent 的主流程template_match.py纯算法实现带旋转的模板匹配requirements.txt依赖声明torch、torchvisionpid.png/pid_template.png演示用目标图与模板图二、环境准备与快速运行README 给出了两条最直接的运行命令。第一步安装依赖pip install -r requirements.txt查看 examples/custom_tools/requirements.txt 可知示例的核心依赖非常精简只有两个torch torchvision其中torchvision用于调用torchvision.ops.nms做检测框的非极大值抑制NMStorch是其底层张量库。除此之外示例还依赖cv2OpenCV与numpy它们分别用于cv2.matchTemplate模板匹配和数组运算vision_agent本体则作为主框架提供注册与 Agent 能力。第二步运行示例python run_custom_tool.py脚本会完成两件事注册template_match自定义工具然后启动VisionAgentCoderV2向它提问在 pid.png 中找到 pid_template.png 的位置并判断是否有结果靠近 NOTE 5。Agent 会根据工具描述决定调用该自定义工具、生成并执行代码、最终返回带边界框的结果。说明与示例配套的完整问答流程同样可以在仓库内的 chat-app 演示examples/chat/中看到类似交互形态但本文聚焦于 custom_tools 这一最小可复现示例。三、注册自定义工具run_custom_tool.py 逐段解析examples/custom_tools/run_custom_tool.py 是自定义工具的标准模板我们逐段拆解。3.1 导入与装饰器注册import numpy as np from template_match import template_matching_with_rotation import vision_agent as va import vision_agent.tools as T import vision_agent.tools.planner_tools as pt from vision_agent.models import AgentMessage from vision_agent.utils.image_utils import get_image_size, normalize_bbox va.tools.register_tool( imports[ import numpy as np, from vision_agent.utils.image_utils import get_image_size, normalize_bbox, from template_match import template_matching_with_rotation, ] ) def template_match(target_image: np.ndarray, template_image: np.ndarray) - dict: ...几个关键点注册入口是va.tools.register_tool。vision_agent.tools包在 vision_agent/tools/init.py 中导出register_tool同时通过from .tools import ...导入大量内置工具目标检测、分割、OCR、视频追踪等。imports参数必须显式列出工具运行所需的全部导入语句。这是 README 强调的核心坑点后面第四节会深入原理。函数必须有规范的 docstring。AgentLLM正是通过 docstring 理解这个工具是干什么的、参数是什么、返回什么从而在写代码时决定是否调用它。示例的 docstring 给出了参数说明、返回值说明以及带cv2.imread的用法示例这是值得复用的最佳实践。3.2 工具函数体归一化边界框image_size get_image_size(target_image) matches template_matching_with_rotation(target_image, template_image) matches[bboxes] [normalize_bbox(box, image_size) for box in matches[bboxes]] return matches工具函数体做三件事用vision_agent.utils.image_utils的get_image_size获取目标图尺寸调用算法层template_matching_with_rotation得到原始像素坐标的边界框与得分用normalize_bbox把每个边界框归一化到 0~1 区间再原样返回。归一化是关键约定vision-agent 内置工具返回的 bbox 统一采用归一化坐标Agent 生成的代码例如画框、计算距离也都基于这一约定。自定义工具遵循同样的返回格式{bboxes: [...], scores: [...]}就能无缝融入 Agent 的代码生成与工具调用流程。3.3 主流程通过 AgentMessage 发起任务if __name__ __main__: agent va.agent.VisionAgentCoderV2(verboseTrue) result agent.generate_code( [ AgentMessage( roleuser, contentCan you find the locations of the pid_template.png in pid.png and tell me if any are nearby NOTE 5?, media[pid.png, pid_template.png], ) ] )va.agent包vision_agent/agent/init.py对外暴露VisionAgentCoderV2等 Agent 类。这里通过AgentMessage把用户问题与媒体文件media列表一起传入generate_code。Agent 内部会结合工具文档、规划结果生成可执行代码并运行最终给出带边界框的答案。四、核心算法template_match.py 的旋转模板匹配实现examples/custom_tools/template_match.py 是纯算法文件不依赖 vision-agent 的任何 API可以在任何 Python 环境单独复用。4.1 图像旋转辅助函数rotate_imagedef rotate_image(mat, angle): height, width mat.shape[:2] image_center (width / 2, height / 2) rotation_mat cv2.getRotationMatrix2D(image_center, angle, 1.0) abs_cos abs(rotation_mat[0, 0]) abs_sin abs(rotation_mat[0, 1]) bound_w int(height * abs_sin width * abs_cos) bound_h int(height * abs_cos width * abs_sin) rotation_mat[0, 2] bound_w / 2 - image_center[0] rotation_mat[1, 2] bound_h / 2 - image_center[1] rotated_mat cv2.warpAffine(mat, rotation_mat, (bound_w, bound_h)) return rotated_mat该函数对图像按指定角度旋转并通过计算旋转后的外接宽高bound_w/bound_h自动扩边避免旋转裁切。这是模板匹配支持任意旋转角度的前置条件。4.2 主函数template_matching_with_rotationdef template_matching_with_rotation( main_image, template, max_rotation360, step90, threshold0.75, visualizeFalse, ) - dict:核心参数与默认值如下参数默认值含义与影响max_rotation360旋转搜索的最大角度度step90角度步长。默认 90 度即只搜 0/90/180/270 四个方向可大幅降低耗时对任意角度模板可调小如 15/30 度threshold0.75cv2.matchTemplate归一化相关系数的命中阈值越高越严格visualizeFalse为True时用 OpenCV 窗口绘制并展示所有命中框调试用算法流程灰度化cv2.cvtColor(..., cv2.COLOR_BGR2GRAY)把目标图与模板转成灰度供cv2.matchTemplate使用多角度循环从0到max_rotation按step步进旋转模板若旋转后的模板尺寸大于目标图则跳过模板匹配对每个角度执行cv2.matchTemplate(main_image_gray, rotated_template, cv2.TM_CCOEFF_NORMED)用np.where(result threshold)找出所有得分超过阈值的坐标收集为(x, y, xw, yh)的边界框NMS 去重同一目标在多个角度/邻域可能产生多个重叠框因此调用torchvision.ops.nmsIOU 阈值0.2合并重叠框同时保留对应得分返回结果{bboxes: boxes, scores: scores}。返回值结构正是第三节中normalize_bbox与 Agent 所消费的标准格式bboxes为[x1, y1, x2, y2]列表scores为对应置信度列表。五、在对话中显式指定工具解决工具选择困难README 特别提醒了一个实战问题Tool choice can be difficult for the agent to get, so sometimes it helps to explicitly call out which tool you want to use.即让 LLM 自己从众多工具中选对自定义工具并不总是可靠。当存在大量内置工具目标检测、OCR、分割等时Agent 可能选错或编造不存在的工具名。缓解办法是在提问时点名工具import vision_agent as va agent va.agent.VisionAgentCoderV2(verbosity2) agent( Can you use the template_match_ tool to find the location of pid_template.png in pid.png?, mediapid.png, )注意两点指令中写的是template_match_带下划线后缀这是告诉 Agent 去工具列表里寻找以该前缀命名的工具media参数把图片传递给 Agent 会话如果需要同时传入模板图可像run_custom_tool.py的AgentMessage那样用media[pid.png, pid_template.png]列表形式。verbosity2README 示例与verboseTruerun_custom_tool.py 示例均为 Agent 的输出控制参数实际使用以你所安装版本的签名为准。显式点名工具之后Agent 生成代码时会优先匹配template_match_工具及其 docstring从而显著提升稳定性。六、底层原理为什么必须传 imports独立进程的代码注入机制README 的 Details 一节解释了自定义工具注册最核心的机制值得深挖Because we execute code on a separate process, we need to re-register the tools inside the new process. To do this,register_toolscopies the source code and prepends it to the code that is executed in the new process. But theres a catch, it cannot copy the imports needed to run the tool code.翻译过来即代码在独立进程中执行VisionAgentCoderV2生成的代码交由CodeInterpreter见 vision_agent/utils/execute.py在独立进程中运行新进程不认识自定义工具因此注册机制会把工具源码复制并前置拼接到新进程要执行的代码之前实现重新注册但源码复制不包含 import函数体里用到的cv2、numpy、template_match等依赖无法仅靠复制函数源码带入新进程所以必须由开发者在register_tool(imports[...])里显式声明。6.1 register_tool 的实现看 vision_agent/tools/init.py#L73-L88 的源码def register_tool(imports: Optional[List] None) - Callable: def decorator(tool: Callable) - Callable: import inspect global TOOLS, TOOLS_DF, TOOL_DESCRIPTIONS, TOOL_DOCSTRING, TOOLS_INFO from vision_agent.tools.tools import TOOLS if tool not in TOOLS: TOOLS.append(tool) globals()[tool.__name__] tool if imports is not None: for import_ in imports: __new_tools__.append(import_) __new_tools__.append(inspect.getsource(tool)) return tool return decorator逐行解读其行为把工具函数追加进全局TOOLS列表同时globals()[tool.__name__] tool使其可直接按名字访问将imports中的每条导入语句依次追加到__new_tools__用inspect.getsource(tool)取出工具完整源码也追加到__new_tools____new_tools__初始内容为[import vision_agent as va, from vision_agent.tools import register_tool]见 vision_agent/tools/init.py#L67-L70保证注入代码自身可解析。6.2 注入点DefaultImports.prepend_imports最终这些字符串被拼接到什么位置见 vision_agent/utils/agent.py#L195-L217 的DefaultImportsclass DefaultImports: common_imports [ import os, import numpy as np, from vision_agent.tools import *, from vision_agent.tools.planner_tools import judge_od_results, from typing import *, from pillow_heif import register_heif_opener, register_heif_opener(), ] staticmethod def to_code_string() - str: return \n.join(DefaultImports.common_imports T.__new_tools__) staticmethod def prepend_imports(code: str) - str: return DefaultImports.to_code_string() \n\n code可以看到Agent 每次执行代码前都会把common_imports含from vision_agent.tools import *与__new_tools__即所有已注册自定义工具的 imports 源码拼接再前置到目标代码上。这就是重新注册的完整链路common_imports默认导入 自定义工具 imports你显式传入的导入语句 自定义工具源码inspect.getsource 复制 换行 Agent 生成的业务代码由此也验证了 README 的告诫凡是工具函数体用到的第三方库都必须写进imports否则新进程执行注入代码时会直接NameError。反过来imports里只应放执行该工具所必需的导入避免污染执行环境。6.3 一条完整的最小注册示例README 给出了去掉业务逻辑的最小骨架import vision_agent as va va.register_tool( imports[import cv2], ) def custom_tool(*args): # Your tool code here pass与run_custom_tool.py中完整写法va.tools.register_tool等价只是注册路径的写法不同。两者的要点一致装饰器 imports 列表 规范 docstring。七、实战要点与最佳实践总结综合 README 与源码编写可被 Vision Agent 稳定调用的自定义工具应遵循以下要点注册三要素缺一不可va.tools.register_tool装饰器、完整的imports列表、描述清晰的 docstring含参数、返回与用法示例。返回格式对齐内置约定边界框归一化到 0~1用normalize_bbox返回{bboxes: ..., scores: ...}结构Agent 的后续代码画框、算距离、判断邻近关系才能正确消费。算法层与注册层分离template_match.py 只依赖cv2/numpy/torch与 vision-agent 解耦便于独立测试与复用run_custom_tool.py 只负责包装与注册。对话中显式点名工具提问时明确写template_match_这样的工具名降低 Agent 工具选择的随机性。依赖声明完整示例依赖torch/torchvision见 requirements.txt实际使用还应确保opencv-python、numpy与vision_agent本体安装到位。性能与精度权衡step决定角度搜索粒度——step90快但只覆盖四个方向需要任意角度匹配时调小步长同时匹配时间近似线性增长threshold0.75可根据实际误检情况上下调整。八、结语本文以 examples/custom_tools/README.md 为骨架从运行方式、注册代码、旋转模板匹配算法到register_tool的独立进程代码注入原理完整还原了为 Vision Agent 添加自定义工具的端到端流程。核心结论可以浓缩为一句话自定义工具 规范 docstring 的函数 register_tool注册 显式 imports 归一化 bbox 返回格式。掌握了这套模式你就能把任意 OpenCV / PyTorch 视觉算法快速武装成 Agent 的可调用能力。【免费下载链接】vision-agentThis tool has been deprecated. Use Agentic Document Extraction instead.项目地址: https://gitcode.com/GitHub_Trending/vi/vision-agent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表