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

相关文章

轻量级在线服装3D定制引擎Myway简介

我写的面向web元宇宙轻量级系列引擎中的另外一个,在线3D定制引擎Myway 3D。 用于在线商品定制,比如个性化服装的定制、日常用品(如杯子)、家装(被套)等物品的在线定制。 特性列表: 可更换衣服款式,按需定制更换模型可实时更改材质颜色可实时添加文本,并可实时修改大小、颜色和角度,支持自定义字体可实时添加艺术图标,并可实时修改大小、颜色和角度,支持翻转、各种对齐可更改衣服图案,按需求定制

亮相WOT全球技术创新大会,揭秘火山引擎边缘容器技术在泛CDN场景的应用与实践

2024年6月21日-22日,51CTO“WOT全球技术创新大会2024”在北京举办。火山引擎边缘计算架构师李志明受邀参与,以“边缘容器技术在泛CDN场景的应用和实践”为主题,与多位行业资深专家,共同探讨泛CDN行业技术架构以及云原生与边缘计算的发展和展望。 火山引擎边缘计算架构师李志明表示:为更好地解决传统泛CDN类业务运行中的问题,火山引擎边缘容器团队参考行业做法,结合实践经验,打造火山

【Unity Shader】片段着色器(Fragment Shader)的概念及其使用方法

在Unity和图形编程中,片段着色器(Fragment Shader)是渲染管线中的一个阶段,负责计算屏幕上每个像素(片段)的颜色和特性。片段着色器通常在顶点着色器和任何几何处理之后运行,是决定最终像素颜色的关键步骤。 Fragment Shader的概念: 像素处理:片段着色器处理经过顶点着色器和几何着色器处理后,映射到屏幕空间的像素。颜色计算:它计算每个像素的颜色值,这可能包括纹理采样、光

【Unity Shader】Alpha Blend(Alpha混合)的概念及其使用示例

在Unity和图形编程中,Alpha Blend(也称为Alpha混合)是一种用于处理像素透明度的技术。它允许像素与背景像素融合,从而实现透明或半透明的效果。Alpha Blend在渲染具有透明度的物体(如窗户、玻璃、水、雾等)时非常重要。 Alpha Blend的概念: Alpha值:Alpha值是一个介于0(完全透明)和1(完全不透明)的数值,用于表示像素的透明度。混合模式:Alpha B

示例:推荐一个基于第三方开源控件库DataGridFilter封装的FilterColumnDataGrid,可以像Excel拥有列头筛选器

一、目的:基于第三方开源控件库DataGridFilter封装的FilterColumnDataGrid,可以像Excel拥有列头筛选器,感兴趣的可以去下方链接地址查看开源控件库地址。本控件封装的目的在于将第三方库的皮肤和样式封装到皮肤库中可统一设置样式,同时生成nuget方便调用 二、效果如下 三、环境 VS2022 Net7 四、使用方式 1、安装nuget包:H.Con

游戏高度可配置化(一)通用数据引擎(data-e)及其在模块化游戏开发中的应用构想图解

游戏高度可配置化(一)通用数据引擎(data-e)及其在模块化游戏开发中的应用构想图解 码客 卢益贵 ygluu 关键词:游戏策划 可配置化 模块化配置 数据引擎 条件系统 红点系统 一、前言 在插件式模块化软件开发当中,既要模块高度独立(解耦)又要共享模块数据,最好的方法是有个中间平台(中间件)提供标准的接口来进行数据的交换,这在很多行业软件开发中已经广泛应用。但是,由于中间件的抽象和封

Class 对象在执行引擎中的初始化过程

一个 class 文件被加载到内存中需要经过 3 大步:装载、链接、初始化。 装载 装载是指 Java 虚拟机查找 .class 文件并生成字节流,然后根据字节流创建 java.lang.Class 对象的过程。 链接 链接过程分为 3 步:验证、准备、解析。 验证: 初始化 这是 class 加载的最后一步,这一阶段是执行类构造器方法的过程,并真正初始化类变量。 1.文件格式检验:检

Unity Meta Quest 开发:关闭 MR 应用的安全边界

社区链接: SpatialXR社区:完整课程、项目下载、项目孵化宣发、答疑、投融资、专属圈子 📕教程说明 这期教程我将介绍如何在应用中关闭 Quest 系统的安全边界。 视频讲解: https://www.bilibili.com/video/BV1Gm42157Zi 在 Unity 中导入 Meta XR SDK,进行环境配置后,打开 Assets > Plugins > An

基于感知哈希算法的视觉目标跟踪

偶然看到这三篇博文[1][2][3],提到图片检索网站TinEye和谷歌的相似图片搜索引擎的技术原理。以图搜图搜索引擎的使命是:你上传一张图片,然后他们尽全力帮你把互联网上所有与它相似的图片搜索出来。当然了,这只是他们认为的相似,所以有时候搜索结果也不一定对。事实上,以图搜图三大搜索引擎除了上面的老牌的TinEye和Google外,还有百度上线不算很久的新生儿:百度识图。之前听余凯老师的一个D

动手学深度学习(Pytorch版)代码实践 -计算机视觉-37微调

37微调 import osimport torchimport torchvisionfrom torch import nnimport liliPytorch as lpimport matplotlib.pyplot as pltfrom d2l import torch as d2l# 获取数据集d2l.DATA_HUB['hotdog'] = (d2l.DATA_U