Unity MiniCPM-V 让引擎拥有视觉

2024-06-03 00:36

本文主要是介绍Unity MiniCPM-V 让引擎拥有视觉,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Unity MiniCPM-V 让引擎拥有视觉

  • 前言
  • 项目
    • Python环境布置
    • Unity场景布置
    • 代码编写
    • 添加并设置脚本
    • 总结
  • 鸣谢
  • AI提示

前言

新发布的MiniCPM-V,忍不住玩一下,可以让之前制作的语音助手拥有一定的视觉能力(不是OpenCV不行,而是AI更加符合一个助手所需要的观察力)。这个简单的小项目中我只实现了少量交互代码,大部分全部由ChatGPT 3.5完成,可以在文末链接查看对话记录。

AI视觉识别

项目

Python环境布置

参考官网配置: https://github.com/OpenBMB/MiniCPM-V/tree/main

除了官网的配置还要安装一下flask库

pip install flask

将脚本放到根目录下,并运行

from flask import Flask, request, jsonify
from chat import MiniCPMVChat, img2base64
import torch
import json
import base64
from io import BytesIO
from PIL import Image# Initialize Flask app
app = Flask(__name__)# Initialize the chat model
torch.manual_seed(0)
chat_model = MiniCPMVChat('openbmb/MiniCPM-Llama3-V-2_5')def pil_image_to_base64(img):buffer = BytesIO()img.save(buffer, format="PNG")return base64.b64encode(buffer.getvalue()).decode()@app.route('/analyze', methods=['POST'])
def analyze_image():try:data = request.jsonprint(f"Received data: {data}")  # Debug: Log the received dataimage_base64 = data.get('image')question = data.get('question')if not image_base64 or not question:return jsonify({'error': 'Missing image or question'}), 400# Decode base64 imageimage_data = base64.b64decode(image_base64)image = Image.open(BytesIO(image_data))im_64 = pil_image_to_base64(image)  # Convert PIL image to base64 string# Prepare the inputs for the modelmsgs = [{"role": "user", "content": question}]inputs = {"image": im_64, "question": json.dumps(msgs)}print(f"Inputs for model: {inputs}")  # Debug: Log the inputs for the model# Get the answer from the modelanswer = chat_model.chat(inputs)# Prepare the responseresponse = {'answer': answer,'context': msgs}return jsonify(response)except Exception as e:print(f"Error: {str(e)}")  # Debug: Log any error that occursreturn jsonify({'error': str(e)}), 500if __name__ == '__main__':app.run(host='127.0.0.1', port=5000)

配置环境并运行Python脚本

Unity场景布置

Unity场景布置

代码编写

创建并挂载ImageAnalyzer.cs脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using System.Text;
using Newtonsoft.Json;
using UnityEngine.UI;public class Response
{[JsonProperty("answer")]public string Answer { get; set; }[JsonProperty("context")]public List<ContextItem> Context { get; set; }
}public class ContextItem
{[JsonProperty("role")]public string Role { get; set; }[JsonProperty("content")]public string Content { get; set; }
}
public class ImageAnalyzer : MonoBehaviour
{[SerializeField] private string serverUrl = "http://your_server_ip:5000/analyze";[SerializeField] private int webcamWidth = 1280;[SerializeField] private int webcamHeight = 720;[SerializeField] private int webcamFPS = 30;[SerializeField] private WebCamTexture webCamTexture;private Texture2D snap;public Text tipText;public Button clickButton;public RawImage rawImage;private void Start(){// Start the webcamwebCamTexture = new WebCamTexture(webcamWidth, webcamHeight);webCamTexture.Play();tipText.text = "请点击按钮询问";clickButton.interactable = true;rawImage.texture = webCamTexture;}private void Update(){if (Input.GetKeyDown(KeyCode.Q)){Debug.Log("按下了按钮");StartCoroutine(AnalyzeImageFromWebcam("用简短易懂的语言告诉我这张图上有什么?"));}}public void ClickButtonFunction(){tipText.text = "请等待。。。";clickButton.interactable = false;StartCoroutine(AnalyzeImageFromWebcam("用简短易懂的语言告诉我这张图上有什么?"));}public IEnumerator AnalyzeImageFromWebcam(string question){// Wait until the webcam is readyyield return new WaitUntil(() => webCamTexture.didUpdateThisFrame);// Dispose of the previous snap texture if it existsif (snap != null){Destroy(snap);}// Get the current frame from the webcamsnap = new Texture2D(webCamTexture.width, webCamTexture.height);snap.SetPixels(webCamTexture.GetPixels());snap.Apply();// Convert the image to base64string base64Image = ConvertTextureToBase64(snap);// Analyze the imageyield return StartCoroutine(AnalyzeImage(base64Image, question));}private string ConvertTextureToBase64(Texture2D texture){byte[] imageBytes = texture.EncodeToPNG();return System.Convert.ToBase64String(imageBytes);}public IEnumerator AnalyzeImage(string base64Image, string question){var formData = new Dictionary<string, string>{{ "image", base64Image },{ "question", question }};string jsonData = JsonConvert.SerializeObject(formData);byte[] postData = Encoding.UTF8.GetBytes(jsonData);UnityWebRequest request = new UnityWebRequest(serverUrl, "POST");request.uploadHandler = new UploadHandlerRaw(postData);request.downloadHandler = new DownloadHandlerBuffer();request.SetRequestHeader("Content-Type", "application/json");yield return request.SendWebRequest();if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError){Debug.LogError(request.error);tipText.text = request.error;clickButton.interactable = true;}else{string jsonResponse = request.downloadHandler.text;Debug.Log("Response JSON: " + jsonResponse); // Log the response for debugging// Process the JSON response here// Deserialize the JSON response to the Response objectResponse response = JsonConvert.DeserializeObject<Response>(jsonResponse);// Use the response dataDebug.Log("Answer: " + response.Answer);foreach (var contextItem in response.Context){Debug.Log($"Role: {contextItem.Role}, Content: {contextItem.Content}");}tipText.text = response.Answer;clickButton.interactable = true;}request.Dispose();}void OnDestroy(){// Stop the webcamif (webCamTexture != null){webCamTexture.Stop();webCamTexture = null;}// Dispose of the snap textureif (snap != null){Destroy(snap);snap = null;}}
}

添加并设置脚本

在按钮上添加一下事件,给ImageAnalyzer物体赋值即可
按钮添加事件

总结

除了交互部分,一行代码没写,这也是未来趋势,提前适应一下。

鸣谢

https://chatgpt.com/
https://github.com/OpenBMB/MiniCPM-V/tree/main

AI提示

点击下方链接可以查看我和ChatGPT 3.5的聊天记录并了解详细开发过程
Image Q&A Service

这篇关于Unity MiniCPM-V 让引擎拥有视觉的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1025539

相关文章

Python利用PySpark和Kafka实现流处理引擎构建指南

《Python利用PySpark和Kafka实现流处理引擎构建指南》本文将深入解剖基于Python的实时处理黄金组合:Kafka(分布式消息队列)与PySpark(分布式计算引擎)的化学反应,并构建一... 目录引言:数据洪流时代的生存法则第一章 Kafka:数据世界的中央神经系统消息引擎核心设计哲学高吞吐

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

C#和Unity中的中介者模式使用方式

《C#和Unity中的中介者模式使用方式》中介者模式通过中介者封装对象交互,降低耦合度,集中控制逻辑,适用于复杂系统组件交互场景,C#中可用事件、委托或MediatR实现,提升可维护性与灵活性... 目录C#中的中介者模式详解一、中介者模式的基本概念1. 定义2. 组成要素3. 模式结构二、中介者模式的特点

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

SpringBoot集成LiteFlow工作流引擎的完整指南

《SpringBoot集成LiteFlow工作流引擎的完整指南》LiteFlow作为一款国产轻量级规则引擎/流程引擎,以其零学习成本、高可扩展性和极致性能成为微服务架构下的理想选择,本文将详细讲解Sp... 目录一、LiteFlow核心优势二、SpringBoot集成实战三、高级特性应用1. 异步并行执行2

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.

MySQL 存储引擎 MyISAM详解(最新推荐)

《MySQL存储引擎MyISAM详解(最新推荐)》使用MyISAM存储引擎的表占用空间很小,但是由于使用表级锁定,所以限制了读/写操作的性能,通常用于中小型的Web应用和数据仓库配置中的只读或主要... 目录mysql 5.5 之前默认的存储引擎️‍一、MyISAM 存储引擎的特性️‍二、MyISAM 的主

MySQL常见的存储引擎和区别说明

《MySQL常见的存储引擎和区别说明》MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY、Archive、CSV和Blackhole,每种引擎有其特点和适用场景,选择存储引擎时需根... 目录mysql常见的存储引擎和区别说明1. InnoDB2. MyISAM3. MEMORY4. A