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.json
        print(f"Received data: {data}")  # Debug: Log the received data
        
        image_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 image
        image_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 model
        msgs = [{"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 model
        answer = chat_model.chat(inputs)

        # Prepare the response
        response = {
            'answer': answer,
            'context': msgs
        }

        return jsonify(response)

    except Exception as e:
        print(f"Error: {str(e)}")  # Debug: Log any error that occurs
        return jsonify({'error': str(e)}), 500

if __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 webcam
        webCamTexture = 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 ready
        yield return new WaitUntil(() => webCamTexture.didUpdateThisFrame);

        // Dispose of the previous snap texture if it exists
        if (snap != null)
        {
            Destroy(snap);
        }

        // Get the current frame from the webcam
        snap = new Texture2D(webCamTexture.width, webCamTexture.height);
        snap.SetPixels(webCamTexture.GetPixels());
        snap.Apply();

        // Convert the image to base64
        string base64Image = ConvertTextureToBase64(snap);

        // Analyze the image
        yield 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 object
            Response response = JsonConvert.DeserializeObject<Response>(jsonResponse);

            // Use the response data
            Debug.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 webcam
        if (webCamTexture != null)
        {
            webCamTexture.Stop();
            webCamTexture = null;
        }
        // Dispose of the snap texture
        if (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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/673408.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

项目中MySQL数据库设计(尚庭公寓)

数据库设计 1 数据库设计理论 1.1 数据库模型 数据库设计中最常采用的模型为实体&#xff08;Entity&#xff09;关系&#xff08;Relationship&#xff09;模型&#xff0c;简称ER模型。其核心思想是将现实世界中的复杂数据表示为一组实体&#xff0c;并描述这些实体之间的…

minos 2.5 中断虚拟化——vGIC

首发公号&#xff1a;Rand_cs 该项目来自乐敏大佬&#xff1a;https://github.com/minosproject/minos 这一节开始讲述真正的中断虚拟化&#xff0c;首先来看硬件方面的虚拟化。前文 minos 2.3 中断虚拟化——GICv2 管理 主要讲述 GICv2 的 Distributor 和 CPU Interface&…

Nvidia Jetson/Orin +FPGA+AI大算力边缘计算盒子:3D扫描仪 实时创建 VR 内容

虽然 VR 技术彻底改变了娱乐、医疗、建筑、教育和产品设计等各个日常生活领域&#xff0c;但创建 VR 内容仍然是一项不易突破的挑战。 英伟达在旧金山举行的 Jetson TX2发布会上&#xff0c;展示了Jetson TX2如何能够加快 AI 计算、图形和计算机视觉的运行速度&#xff0c;并且…

【一小时学会Charles抓包详细教程】Charles 抓包相关设置 (7)

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 Charles 抓包相…

数据库学习总结

Mysql学习总结 汇总数据 聚集函数&#xff1a; 函数 说明 AVG() 返回某列的平均值 COUNT() 返回某列的行数 MAX() 返回某列的最大值 MIN() 返回某列的最小值 SUM() 返回某列值之和 例&#xff1a; AVG函数&#xff1a; select avg(grade) from topic; COUNT函…

WiFi蓝牙模块促进传统零售数字化转型:智能零售体验再升级

随着科技的不断发展&#xff0c;数字化转型已经成为了各行各业的必然趋势。在传统零售业中&#xff0c;WiFi蓝牙模块的应用正逐渐推动着行业的数字化转型&#xff0c;为消费者带来更加智能化、便捷化的零售体验。本文MesoonRF美迅物联网将从以下几个方面阐述WiFi蓝牙模块在传统…

稍微学学react

文章开始前&#xff0c;先划划水~ 今日份开心&#xff1a; 今天看之前发布的按钮npm包下载量有162次&#xff0c;早知道好好做了 今日份不开心&#xff1a; 爬岗位看到一个整体都挺满意的岗位&#xff0c;公司位置和发展大方向都好喜欢&#xff01;&#xff01;&#xff01;…

机器学习学习(2)

基于数据流图的编程范式:声明式编程(Declarative Programming )、命令式编程(Imperative Programming ); 声明式编程(Declarative Programming ) 代表性框架:TensorFlow, CNTK, Caffe2 特点:用户只需要表达模型结构和需要执行的任务,无需关注底层的执行流程,框…

【UE+GIS】UE5GIS CAD或shp构建3D地形

贴合地形的矢量图形实现方法 一、灰度图的制作和拉伸换算1、基于高程点集实现2、基于等高线实现3、拉伸计算 二、生成地形模型的实现方案1、3Dmax导入灰度图2、使用ArcMap/Arcpro/FME等GIS数据处理工具3、UE导入灰度图 三、地形上叠加地形渲染效果的实现方案1、贴花2、数据渲染…

【transformers】pytorch基础

传送门&#xff1a;https://transformers.run/c2/2021-12-14-transformers-note-3/ pytorch基础知识 tensor &#xff1a; 张量。 需要知道的内容&#xff1a; 张量构建张量计算自动微分形状调整广播机制索引与切片升降维度 Tensor 张量&#xff1a;理解成高纬度的向量就完…

【最新鸿蒙应用开发】——什么是状态管理?

状态管理 在声明式UI编程框架中&#xff0c;UI是程序状态的运行结果&#xff0c;用户构建了一个UI模型&#xff0c;其中应用的运行时的状态是参数。当参数改变时&#xff0c;UI作为返回结果&#xff0c;也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染&#xf…

系统安全及其应用

系统安全&#xff1a; 1&#xff09;保护数据安全&#xff0c; 2&#xff09;互联网&#xff0c;网络业务服务等&#xff0c;必须要通过工信部的资质审核 3&#xff09;保护品牌形象 应用&#xff1a; 账号安全 1&#xff09;把不需要或者不想登录的用户设置为nologin us…

echarts绘制三维柱状图

echarts ECharts 是一个使用 JavaScript 实现的开源可视化库&#xff0c;主要用于数据的可视化展示。ECharts 支持丰富的图表类型&#xff0c;如折线图、柱状图、饼图、地图、K线图等&#xff0c;可以满足不同类型数据的展示需求。 文档地址&#xff1a;echarts 本次所绘制三…

Django request.POST获取提交的表单数据

在Django中&#xff0c;request.POST 是一个特殊的属性&#xff0c;它是一个类似于字典的对象&#xff0c;用于访问通过POST方法提交的表单数据。如果你在视图中使用 print(request.POST.get(username))&#xff0c;这通常意味着你正在尝试从一个HTML表单中获取一个名为 userna…

数学建模之MATLAB入门教程(上)

前言&#xff1a; • MATLAB是美国Math Works公司出品的商业数学软件&#xff0c;用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人&#xff0c;控制系统等领域。 • MATLAB将数值分析、矩阵计算、科学数据可视化以及非线性动…

Ubuntu server 24 (Linux) 普通用户不能sudo 也不能使用root登录 忘记root密码 修复解决方案

一 普通用户无法sudo&#xff0c;同时也没有其他用户可用 #test用户使用sudo报错&#xff0c;没有权限 testtest:~$ sudo vi /etc/sudoers [sudo] password for test: test is not in the sudoers file. 二 关闭ubuntu 服务器&#xff0c;重新开机 按下ESC 键 1 出现GRUB…

【工具】探索 MOU:每用户通话时长

缘分让我们相遇乱世以外 命运却要我们危难中相爱 也许未来遥远在光年之外 我愿守候未知里为你等待 我没想到为了你我能疯狂到 山崩海啸没有你根本不想逃 我的大脑为了你已经疯狂到 脉搏心跳没有你根本不重要 &#x1f3b5; 邓紫棋《光年之外》 什么是 MOU…

RunLoop小白入门

核心概念 什么是 RunLoop ? RunLoop 是 iOS 和 macOS 应用程序框架中的一个核心概念&#xff0c;用于管理线程的事件处理。它可以看作是一个循环&#xff0c;用于持续接收和处理各种事件&#xff0c;如用户输入、定时器、网络事件等。RunLoop 在保持应用程序响应用户交互和系…

【再探】设计模式—备忘录模式与解释器模式

备忘录模式是用于保存对象在某个时刻的状态&#xff0c;来实现撤销操作。而解释器模式则是将文本按照定义的文法规则解析成对应的命令。 1 备忘录模式 需求&#xff1a;保存对象在某个时刻的状态&#xff0c;后面可以对该对象实行撤销操作。 1.1 备忘录模式介绍 提供一种状…

Anaconda创建python环境默认C盘,如何修改路径

文章目录 前言解决方案1.找到Anaconda的根目录2. 找到根目录文件夹&#xff0c;右键-属性-安全 测试-重新创建新的python环境 前言 使用 Anaconda创建python环境&#xff0c;默认在C盘。 如何修改到别的路径呢&#xff1f; base环境 是安装 Anaconda是安装的默认环境&#x…