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

vlm识别桌面图标像素位置

qwen3-vl:8b:

qwen3-vl:235b-instruct-cloud:

等等再接个tool点击

qwen模型的视觉得缩放到1000*1000

import tkinter as tk from tkinter import filedialog import base64 import json import os from PIL import Image, ImageDraw, ImageFont from datetime import datetime import sys from ollama import chat # 使用Ollama官方客户端 sys.path.append(os.getcwd()) from api_key import ollama_vlm # 获取模型名称 # ==================== 配置区域 ==================== # 使用的Ollama模型 VL_MODEL ="qwen3-vl:235b-instruct-cloud" # 输出文件夹路径 OUTPUT_FOLDER = "output/grounding" # 是否启用坐标处理 # True: 将 0-1000 范围的归一化坐标映射回原始图像像素坐标 # False: 直接使用原始坐标 ENABLE_COORD_NORMALIZATION = True # ==================== 功能函数 ==================== def create_output_folder(): """创建输出文件夹,如果不存在的话""" if not os.path.exists(OUTPUT_FOLDER): os.makedirs(OUTPUT_FOLDER) print(f"已创建输出文件夹: {OUTPUT_FOLDER}") return OUTPUT_FOLDER def image_to_base64(image_path): """ 将图片文件转换为base64字符串 Args: image_path: 图片文件路径 Returns: str: base64编码的图像字符串 """ try: with open(image_path, "rb") as image_file: return base64.b64encode(image_file.read()).decode('utf-8') except Exception as e: print(f"[错误] 图像转换失败: {e}") raise e def get_bounding_boxes_from_ai(image_path, prompt=None): """ 使用Ollama VLM进行目标检测 Args: image_path: 图片文件路径 prompt: 自定义提示词 Returns: list: 检测到的边界框列表 """ # 如果没有传入自定义 prompt,使用针对游戏 UI 优化的默认 prompt if prompt is None: prompt = ( "请找出blender图标的位置。" "格式必须为严格的 JSON 数组,不要包含任何 Markdown 标记(如 ```json)。" "每个元素包含:'object_name' (物体或图标的具体名称), 'bbox' ([x_min, y_min, x_max, y_max])。" "**重要:坐标必须是原始的像素值 (Absolute Pixel Coordinates),基于图片的实际分辨率。" "不要返回 0-1000 的归一化坐标。**" "只返回 JSON 数据。" ) # 转换图像为base64 try: image_base64 = image_to_base64(image_path) except Exception as e: raise Exception(f"图像转换失败: {e}") # 构建消息内容,包含图像和文本 messages = [ { 'role': 'user', 'content': prompt, 'images': [image_base64] } ] try: print(f"[{datetime.now().strftime('%H:%M:%S')}] 正在调用Ollama模型 '{VL_MODEL}' 进行目标检测...") response = chat( model=VL_MODEL, messages=messages, ) result_text = response.message.content print(f"[{datetime.now().strftime('%H:%M:%S')}] AI分析完成") print(f"AI 返回结果:\n{result_text}") # 解析返回结果 bounding_boxes = extract_json_from_response(result_text) return bounding_boxes except Exception as e: print(f"[错误] Ollama调用失败: {e}") raise Exception(f"Ollama调用失败: {str(e)}") def extract_json_from_response(text): """ 从 AI 返回的文本中提取 JSON 数据 Args: text: AI 返回的文本 Returns: list: 解析后的边界框列表 """ import re # 先移除 Markdown 代码块标记 # 移除 ```json 和 ``` 标记 text = re.sub(r'```(?:json)?\s*', '', text) text = re.sub(r'```\s*', '', text) # 尝试查找 JSON 数组模式 json_pattern = r'\[\s*\{.*?\}\s*\]' matches = re.findall(json_pattern, text, re.DOTALL) if matches: try: data = json.loads(matches[0]) return data except json.JSONDecodeError as e: print(f"JSON 解析错误: {e}") print(f"原始文本: {matches[0]}") pass # 尝试直接解析整个文本 try: start_idx = text.find('[') end_idx = text.rfind(']') + 1 if start_idx != -1 and end_idx > start_idx: json_str = text[start_idx:end_idx] data = json.loads(json_str) return data except json.JSONDecodeError as e: print(f"JSON 解析错误: {e}") print(f"尝试解析的文本: {json_str}") pass except Exception as e: print(f"其他错误: {e}") pass # 返回空列表 return [] def draw_bounding_boxes(image_path, bounding_boxes, output_path=None): """ 在图片上绘制边界框 Args: image_path: 原图路径 bounding_boxes: 边界框列表 output_path: 输出路径 Returns: str: 保存后的图片路径 """ # 打开图片 img = Image.open(image_path) draw = ImageDraw.Draw(img) # 图片尺寸 img_width, img_height = img.size print(f"图片尺寸: {img_width}x{img_height}") # 颜色列表(用于不同物体不同颜色) colors = [ (255, 0, 0), # 红色 (0, 255, 0), # 绿色 (0, 0, 255), # 蓝色 (255, 255, 0), # 黄色 (255, 0, 255), # 紫色 (0, 255, 255), # 青色 (255, 128, 0), # 橙色 (128, 0, 255), # 紫色 ] # 尝试加载字体 try: font = ImageFont.truetype("simhei.ttf", 20) # 黑体 except: try: font = ImageFont.truetype("arial.ttf", 20) except: font = ImageFont.load_default() # 绘制每个边界框 for i, box in enumerate(bounding_boxes): try: # 获取边界框坐标 if isinstance(box, dict): # 支持多种字段名称 bbox = box.get('bbox', box.get('bbox_2d', box.get('bounding_box', []))) obj_name = box.get('object_name', box.get('name', box.get('label', f'object_{i}'))) elif isinstance(box, list): bbox = box[:4] if len(box) >= 4 else box obj_name = box[4] if len(box) > 4 else f'object_{i}' else: continue # 确保 bbox 有 4 个值 if len(bbox) < 4: print(f"跳过无效的 bbox: {bbox}") continue x_min, y_min, x_max, y_max = bbox[:4] # 根据配置决定坐标处理方式 if ENABLE_COORD_NORMALIZATION: # 如果坐标已经在 0-1000 范围内,则映射回原始图像尺寸 # 反向公式:x_pixel = (x_norm / 1000) * img_width x_min = int((x_min / 1000) * img_width) y_min = int((y_min / 1000) * img_height) x_max = int((x_max / 1000) * img_width) y_max = int((y_max / 1000) * img_height) # 确保坐标在图像边界内 x_min = max(0, min(img_width - 1, x_min)) y_min = max(0, min(img_height - 1, y_min)) x_max = max(0, min(img_width - 1, x_max)) y_max = max(0, min(img_height - 1, y_max)) else: # 不进行特殊处理,直接使用原始坐标 x_min, y_min, x_max, y_max = int(x_min), int(y_min), int(x_max), int(y_max) # 选择颜色 color = colors[i % len(colors)] # 绘制矩形框(线宽 3) draw.rectangle([x_min, y_min, x_max, y_max], outline=color, width=3) # 绘制标签背景 label = f"{obj_name}" text_bbox = draw.textbbox((x_min, y_min - 25), label, font=font) draw.rectangle([x_min, y_min - 25, text_bbox[2], y_min], fill=color) # 绘制标签文字 draw.text((x_min, y_min - 25), label, fill=(255, 255, 255), font=font) print(f"绘制物体 {i+1}: {obj_name} - [{x_min}, {y_min}, {x_max}, {y_max}]") except Exception as e: print(f"绘制第 {i+1} 个框失败:{e}") continue # 生成输出文件名 if output_path is None: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") original_name = os.path.basename(image_path) name, ext = os.path.splitext(original_name) output_path = os.path.join(OUTPUT_FOLDER, f"{name}_boxed_{timestamp}{ext}") # 保存图片 img.save(output_path) print(f"图片已保存到:{output_path}") return output_path def select_image_file(): """ 弹窗选择图像文件 Returns: str: 选择的图像文件路径,如果取消选择则返回None """ root = tk.Tk() root.withdraw() # 隐藏主窗口 image_path = filedialog.askopenfilename( title="选择要检测的图像", filetypes=[ ("图像文件", "*.jpg *.jpeg *.png *.bmp *.webp *.tiff *.tif"), ("所有文件", "*.*") ] ) root.destroy() return image_path def main(): """主函数 - 简洁的命令行版本""" print("=== AI 目标检测工具 ===") print("使用 Ollama VLM 模型进行图像目标检测") print() # 选择图片 print("正在打开文件选择窗口...") image_path = select_image_file() if not image_path: print("未选择图片,程序退出") return print(f"已选择图片: {image_path}") print() try: # 创建输出文件夹 create_output_folder() # 调用 AI 获取边界框 print("正在调用 AI 模型进行目标检测...") bounding_boxes = get_bounding_boxes_from_ai(image_path) if not bounding_boxes: print("⚠️ AI 未检测到任何物体") print("建议:尝试更换图片或调整提示词") return print(f"✓ 检测到 {len(bounding_boxes)} 个物体") print() # 绘制边界框 print("正在绘制边界框...") output_path = draw_bounding_boxes(image_path, bounding_boxes) print() print("=== 检测完成 ===") print(f"检测到的物体数量: {len(bounding_boxes)}") print(f"结果图片保存到: {output_path}") # 显示检测到的物体信息 print("\n检测到的物体:") for i, box in enumerate(bounding_boxes): if isinstance(box, dict): obj_name = box.get('object_name', box.get('name', f'object_{i}')) bbox = box.get('bbox', []) if bbox: print(f" {i+1}. {obj_name} - 坐标: {bbox}") else: print(f" {i+1}. 物体_{i} - 坐标: {box[:4] if len(box) >= 4 else box}") except Exception as e: print(f"❌ 错误: {str(e)}") return if __name__ == "__main__": main()
http://www.jsqmd.com/news/410107/

相关文章:

  • 互联网大厂Java面试:从Java基础到微服务应用场景解析
  • 还在无脑堆砌提示词?三分钟看懂 Vercel v0 价值千万的 System Prompt 底层逻辑
  • 329. 矩阵中的最长递增路径
  • 2026别错过!AI论文软件 千笔·专业学术智能体 VS WPS AI,研究生写作神器!
  • 好用还专业!9个降AI率工具测评对比,研究生必看
  • 2026年知名的新国标红木家具/缅甸花梨木红木家具实用供应商采购指南如何选 - 品牌宣传支持者
  • 全程用 Claude Code 搓了一个 macOS 原生应用:SkillDeck
  • 把 5G 搬上太空:Rel-19 如何剔除协议底层的“地球惯性”?
  • 一文讲透|AI论文平台 千笔写作工具 VS Checkjie,本科生写论文就选它!
  • 智能科学毕设最全方向思路
  • 2026年实测靠谱的芙蕊汇品牌商城/芙蕊汇APP下载更新厂家选择指南哪家好 - 品牌宣传支持者
  • 强烈安利! AI论文工具 千笔写作工具 VS 灵感风暴AI,本科生必备!
  • 简单理解:ARM 核心寄存器(SP、LR、PC、xPSR)
  • 2026年评价高的台下盆厨房水槽/洗菜盆厨房水槽厂家推荐与选择指南 - 品牌宣传支持者
  • 智能科学毕设创新的题目汇总
  • 【含文档+PPT+源码】基于Spring Boot的电脑网上商城
  • 北京狗狗训练基地哪家好?北京专业正规的狗狗训练基地名单 - 品牌2025
  • 10 个全新大模型方向毕业设计题目
  • python-flask乡村居民收入数据的可视化平台Pycharm vue django
  • 2026年评价高的反弹器/衣柜反弹器厂家选购参考建议 - 品牌宣传支持者
  • Ray:面向AI时代的下一代分布式计算框架
  • 2026年知名的锦纶面料/复合面料新厂实力推荐(更新) - 品牌宣传支持者
  • python-flask协同过滤算法的音乐推荐研究Pycharm vue django
  • 2026年优质正品的芙蕊汇美妆商城/芙蕊汇化妆品商城热门品牌推荐口碑排行 - 品牌宣传支持者
  • 用过才敢说 10个降AI率平台测评:继续教育必备工具全解析
  • 2026 程序员生存指南:纯开发降温,AI 工程化溢价 50%
  • 2026年靠谱的溯源燕窝礼盒/孕妇专用溯源燕窝热门品牌推荐口碑排行 - 品牌宣传支持者
  • 2026年口碑好的农业用褐藻寡糖,南非巨藻酶解液褐藻寡糖,高活性褐藻寡糖厂家选购决策指南 - 品牌鉴赏师
  • CDN 转发下的隐匿攻击:利用 Domain Fronting 与 Cloudflare Workers
  • 剑指offer-77、打印从1到最⼤的n位数