基于ollama与VLM的自动化测试元素定位实践

📅 2026/7/24 4:19:05
基于ollama与VLM的自动化测试元素定位实践
1. 项目背景与核心价值最近在自动化测试和RPA领域视觉语言模型VLM结合本地大语言模型LLM的方案越来越受到关注。这个项目探索了如何利用ollama部署的本地VLM模型实现屏幕界面元素的精准识别和定位。传统基于DOM结构的元素定位方式在面对老旧系统、游戏界面或自定义UI组件时常常失效而纯视觉方案又缺乏语义理解能力。VLM正好填补了这个空白——它能同时理解图像内容和自然语言指令。我在实际项目中发现当需要自动化操作一个没有API接口的桌面应用时最头疼的就是如何稳定地定位那些动态生成的按钮和控件。通过ollama运行开源VLM模型我们可以在本地环境实现用自然语言描述要查找的界面元素比如登录按钮或提交表单模型会直接返回该元素在屏幕中的像素级坐标。这种方法不依赖任何UI框架元数据对任何可见的界面元素都有效。2. 技术方案选型2.1 为什么选择ollamaollama作为本地化LLM运行环境有几个不可替代的优势完全离线运行适合处理敏感的屏幕图像数据支持量化模型8GB内存的笔记本就能流畅运行7B参数的VLM统一的模型管理接口方便切换不同视觉语言模型对多模态输入的原生支持如图像文本的prompt对比云端方案本地部署避免了截图上传的隐私风险也减少了网络延迟。我在测试中发现对于需要实时交互的场景如游戏自动化本地推理的响应速度比API调用快3-5倍。2.2 VLM模型选择经过实测对比推荐以下几个在ollama上表现优秀的开源VLM模型llava-1.5-7b-q4轻量级但识别准确率高适合大多数GUI元素bakllava-1对图标类元素识别更精准cogvlm-17b处理复杂界面时理解能力更强但需要更高配置重要提示模型不是越大越好。对于简单的按钮定位任务7B参数模型在保持90%准确率的同时推理速度是34B模型的6倍。3. 完整实现步骤3.1 环境准备首先安装ollama并拉取VLM模型curl -fsSL https://ollama.com/install.sh | sh ollama pull llava:1.5-7b-q4安装必要的Python依赖pip install pillow opencv-python pyautogui numpy3.2 屏幕捕获与预处理创建屏幕捕获工具类import pyautogui import cv2 import numpy as np class ScreenCapturer: staticmethod def get_screenshot(): # 获取屏幕截图并转换为RGB格式 screenshot pyautogui.screenshot() return cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR) staticmethod def save_temp_image(img, pathtemp_screen.png): cv2.imwrite(path, img) return path图像预处理的关键技巧将截图分辨率调整为模型训练尺寸通常为336x336或448x448保持原始宽高比进行padding避免元素变形对暗色界面适当提高gamma值1.2-1.53.3 ollama接口调用实现VLM查询封装import subprocess import json import time class VLMController: def __init__(self, model_namellava:1.5-7b-q4): self.model model_name def query_element_position(self, image_path, prompt): full_prompt f请精确识别图片中{prompt}的位置。 只返回JSON格式的边界框坐标格式如 {{x1: 100, y1: 200, x2: 300, y2: 400}} cmd [ ollama, run, self.model, --image, image_path, full_prompt ] start_time time.time() result subprocess.run(cmd, capture_outputTrue, textTrue) elapsed time.time() - start_time try: return json.loads(result.stdout.strip()), elapsed except json.JSONDecodeError: print(f解析失败原始输出{result.stdout}) return None, elapsed3.4 坐标后处理获取原始坐标后需要转换为屏幕绝对坐标def convert_to_screen_coordinates(bbox, original_size, model_input_size336): 将模型输出的相对坐标转换为屏幕绝对坐标 bbox: {x1: 100, y1: 200, x2: 300, y2: 400} original_size: (width, height) 原始截图尺寸 scale_x original_size[0] / model_input_size scale_y original_size[1] / model_input_size return { x1: int(bbox[x1] * scale_x), y1: int(bbox[y1] * scale_y), x2: int(bbox[x2] * scale_x), y2: int(bbox[y2] * scale_y) }4. 实战应用示例4.1 识别Chrome刷新按钮def locate_chrome_refresh_button(): capturer ScreenCapturer() vlm VLMController() # 获取屏幕截图 original_img capturer.get_screenshot() original_size (original_img.shape[1], original_img.shape[0]) # 保存临时图像 temp_path capturer.save_temp_image(original_img) # 查询元素位置 bbox, time_cost vlm.query_element_position( temp_path, Chrome浏览器的刷新按钮 ) if bbox: screen_bbox convert_to_screen_coordinates(bbox, original_size) print(f定位成功耗时{time_cost:.2f}s 坐标{screen_bbox}) return screen_bbox else: print(定位失败) return None4.2 自动化登录操作def auto_login(username, password): # 定位用户名输入框 username_field locate_element(用户名输入框) pyautogui.click( (username_field[x1] username_field[x2]) // 2, (username_field[y1] username_field[y2]) // 2 ) pyautogui.write(username) # 定位密码输入框 password_field locate_element(密码输入框) pyautogui.click( (password_field[x1] password_field[x2]) // 2, (password_field[y1] password_field[y2]) // 2 ) pyautogui.write(password) # 点击登录按钮 login_btn locate_element(登录按钮) pyautogui.click( (login_btn[x1] login_btn[x2]) // 2, (login_btn[y1] login_btn[y2]) // 2 )5. 性能优化技巧5.1 加速推理的实用方法区域截屏只截取屏幕相关区域而非全屏减少输入尺寸# 只截取屏幕中央800x600区域 region (screen_width//2-400, screen_height//2-300, 800, 600) screenshot pyautogui.screenshot(regionregion)prompt工程精确的prompt能显著提高识别准确率坏prompt找按钮好prompt识别蓝色矩形、带有提交文字的按钮温度参数调整通过--temperature 0.1减少随机性ollama run llava:1.5-7b-q4 --temperature 0.15.2 缓存策略对静态界面元素建立坐标缓存from functools import lru_cache lru_cache(maxsize50) def locate_element_cached(prompt, screen_hash): return locate_element(prompt)6. 常见问题排查6.1 识别准确率低症状返回的坐标明显错误或找不到元素解决方案检查截图质量 - 确保图像清晰无模糊优化prompt - 加入更多视觉特征描述尝试不同的VLM模型 - bakllava对图标识别更好6.2 响应速度慢症状单次查询超过5秒优化方案使用量化程度更高的模型如q4改为q3限制截图区域而非全屏捕获升级硬件 - 给ollama分配更多内存6.3 坐标偏移问题症状点击位置总是有偏移校正方法检查DPI缩放设置 - 特别是4K屏幕添加校准偏移量def apply_calibration(bbox, x_offset0, y_offset0): return { x1: bbox[x1] x_offset, y1: bbox[y1] y_offset, x2: bbox[x2] x_offset, y2: bbox[y2] y_offset }7. 进阶应用方向7.1 动态元素跟踪结合OpenCV实现实时元素追踪while True: element locate_element(移动的目标物体) if element: center_x (element[x1] element[x2]) // 2 center_y (element[y1] element[y2]) // 2 pyautogui.moveTo(center_x, center_y) time.sleep(0.1)7.2 多显示器支持扩展屏幕坐标处理def get_active_screen_region(): 获取当前活动显示器的区域 monitors pyautogui.getAllScreens() primary [m for m in monitors if m.is_primary][0] return ( primary.left, primary.top, primary.width, primary.height )7.3 与RPA工具集成通过HTTP服务暴露接口供UiPath等工具调用from flask import Flask, request, jsonify app Flask(__name__) vlm VLMController() app.route(/locate, methods[POST]) def locate_api(): data request.json img_path save_base64_image(data[image]) bbox, _ vlm.query_element_position(img_path, data[prompt]) return jsonify(bbox)在实际项目中我发现这套方案特别适合处理这些场景老旧ERP系统的自动化测试游戏内的UI自动化操作跨平台应用的功能测试快速原型开发时的界面自动化最后分享一个实用技巧当需要连续定位多个相似元素时如表格行可以在prompt中指定序号请识别第3个删除按钮。这比单独截取每个区域效率高得多。