Unity 和 OpenCV:结合计算机视觉和游戏开发

news2024/10/2 10:40:20

文章目录

  • 前言
  • 一、Unity 中集成 OpenCV
    • 1. 安装OpenCV plus Unity 插件
    • 2. 导入 OpenCV 包
  • 二、图像处理应用程序的创建
    • 1. 实时轮廓检测
    • 2. 粒子发射器
    • 3. 碰撞区域
  • 三、效果
  • 四、总结


前言

Unity 和 OpenCV 是两个强大的开发工具,分别用于游戏开发和计算机视觉。结合它们可以实现一些有趣和创新的项目。本篇博客将介绍如何在 Unity 中集成 OpenCV,以及如何利用它们的结合来创建令人惊叹的应用程序。


一、Unity 中集成 OpenCV

1. 安装OpenCV plus Unity 插件

首先,我们需要在 Unity 中安装 OpenCV plus Unity插件。这个插件提供了与 OpenCV 库集成的功能,使我们能够在 Unity 中使用 OpenCV 的强大功能。
在这里插入图片描述

2. 导入 OpenCV 包

在安装插件后,我们需要导入 OpenCV 包到 Unity 项目中。这将包括所需的库文件和相关的脚本文件,以便我们可以开始在 Unity 中使用 OpenCV。
在这里插入图片描述

二、图像处理应用程序的创建

1. 实时轮廓检测

我们将使用 OpenCV 在 Unity 中实现实时轮廓检测。CountourFinder.cs将捕获摄像头输入,并使用 OpenCV 查找图像中的轮廓。检测到的轮廓将被用于在 Unity 中绘制形状,并且可以与游戏对象进行交互。
在这里插入图片描述

// CountourFinder.cs 脚本
// 使用 OpenCV 在 Unity 中实现实时轮廓检测
using System.Collections; 
using System.Collections.Generic; 
using System.IO; 
using OpenCvSharp;
using OpenCvSharp.Demo; 
using UnityEngine; 
using UnityEngine.UI; 

//继承 WebCamera 类
public class CountourFinder : WebCamera
{
    // 图像翻转模式
    [SerializeField] private FlipMode imageFlip;
    // 阈值
    [SerializeField] private float threshold = 96.4f;
    // 曲线精度
    [SerializeField] private float curveAccuracy = 10f;
    // 最小区域
    [SerializeField] private float minArea = 5000f; 
    // 多边形碰撞器
    [SerializeField] private PolygonCollider2D polygonCollider; 
    // 切换按钮
    [SerializeField] private Toggle toggle;
    
    private Mat _image; // 图像
    private Mat _processImage = new(); // 处理后的图像
    private Point[][] contours; // 轮廓
    private HierarchyIndex[] _hierarchy; // 层级
    private Vector2[] vertorList; // 点的列表

    // 重写 ProcessTexture 方法,处理图像纹理
    protected override bool ProcessTexture(WebCamTexture input, ref Texture2D output)
    {
        // 将输入的图像纹理转换为 Mat 类型
        _image = OpenCvSharp.Unity.TextureToMat(input); 

        // 翻转图像
        Cv2.Flip(_image, _image, imageFlip); 
        // 转换为灰度图
        Cv2.CvtColor(_image, _processImage, ColorConversionCodes.RGB2GRAY); 
        // 阈值化
        Cv2.Threshold(_processImage, _processImage, threshold, 255, ThresholdTypes.BinaryInv); 
        // 查找图像中的轮廓
        Cv2.FindContours(_processImage, out contours, out _hierarchy, RetrievalModes.Tree, 
            ContourApproximationModes.ApproxSimple, null); 

        // 重置碰撞器路径数
        polygonCollider.pathCount = 0; 
        // 遍历每个轮廓
        foreach (Point[] contour in contours)
        {
            // 近似多边形
            Point[] points = Cv2.ApproxPolyDP(contour, curveAccuracy, true); 
            // 计算轮廓面积
            var area = Cv2.ContourArea(contour); 
            // 如果面积大于最小面积
            if (area > minArea) 
            {
                // 绘制轮廓
                DrwaContour(_processImage, new Scalar(127, 1271, 127), 2, points); 
                // 增加碰撞器路径数
                polygonCollider.pathCount++; 
                // 设置碰撞路径
                polygonCollider.SetPath(polygonCollider.pathCount - 1, ToVertor2(points)); 
            }
        }

        if (output == null)
        {
            // 将图像转换为纹理
            output = OpenCvSharp.Unity.MatToTexture(toggle.isOn ? _processImage : _image); 
        }
        else
        {
            // 将图像转换为纹理
            OpenCvSharp.Unity.MatToTexture(toggle.isOn ? _processImage : _image, output); 
        }

        return true; // 返回 true
    }

    // 将 Point 数组转换为 Vector2 数组
    private Vector2[] ToVertor2(Point[] points)
    {
        vertorList = new Vector2[points.Length]; 
        for (int i = 0; i < points.Length; i++) 
        {
            // 将点转换为 Vector2
            vertorList[i] = new Vector2(points[i].X, points[i].Y); 
        }

        return vertorList; 
    }

    // 绘制轮廓
    private void DrwaContour(Mat image, Scalar color, int thickeness, Point[] points)
    {
        for (int i = 1; i < points.Length; i++) 
        {
            // 绘制线段
            Cv2.Line(image, points[i - 1], points[i], color, thickeness); 
        }

        // 绘制最后一条线段
        Cv2.Line(image, points[^1], points[0], color, thickeness); 
    }
}

2. 粒子发射器

在 Unity 中,我们可以创建一个粒子发射器,用于在场景中生成粒子效果。这个发射器可以与 OpenCV 实现的图像处理功能结合,根据检测到的图像特征来控制粒子的生成和运动。
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Emitter : MonoBehaviour
{
    [SerializeField] private GameObject spawnPrefab; // 生成的预制体
    [SerializeField] private float spawnRate = 0.1f; // 生成速率
    [SerializeField] private int maxParticles = 3; // 最大粒子数量
    [SerializeField] private Vector2 sizeRange; // 大小范围

    private GameObject[] _pool; // 对象池

    // Start is called before the first frame update
    void Start()
    {
        InitializePool(); // 初始化对象池
        Spawn(); // 开始生成粒子
    }

    // Update is called once per frame
    void Update()
    {
       
    }

    // 初始化对象池
    private void InitializePool()
    {
        _pool = new GameObject[maxParticles]; // 根据最大粒子数量创建对象池
        for (int i = 0; i < maxParticles; i++)
        {
            var particle = Instantiate(spawnPrefab); // 实例化预制体
            particle.SetActive(false); // 初始时将粒子设置为不激活状态
            _pool[i] = particle; // 将粒子添加到对象池中
        }
    }

    // 生成粒子
    private void Spawn()
    {
        foreach (var particle in _pool)
        {
            if (!particle.activeSelf) // 如果粒子不是激活状态
            {
                // 随机生成粒子位置,并转换为世界坐标系下的位置
                particle.transform.position = transform.TransformPoint(Random.insideUnitSphere * 0.5f);
                // 随机设置粒子大小
                particle.transform.localScale = Random.Range(sizeRange.x, sizeRange.y) * Vector3.one;
                particle.SetActive(true); // 激活粒子
                break; // 结束循环
            }
        }

        Invoke("Spawn", spawnRate); // 延迟 spawnRate 时间后再次调用 Spawn 方法
    }
}

3. 碰撞区域

最后,我们将在 Unity 中创建一个碰撞区域,用于检测粒子与特定区域的碰撞。当粒子进入碰撞区域时,将触发特定的事件,例如使粒子消失或触发特效。
在这里插入图片描述

// KillZone.cs 脚本
// 在 Unity 中创建碰撞区域,用于检测粒子与特定区域的碰撞

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KillZone : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D col)
    {
        col.gameObject.SetActive(false);
    }
}

三、效果

在这里插入图片描述

四、总结

结合 OpenCV 和 Unity 可以实现许多有趣和创新的项目。通过利用 OpenCV 在 Unity 中的集成,我们可以创建出令人惊叹的图像处理和游戏开发应用程序。无论是学习者还是专业开发者,都可以从这种结合中受益,并创造出令人印象深刻的作品。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【国产MCU】-CH32V307-SysTick中断与延时功能实现

SysTick中断与延时功能实现 文章目录 SysTick中断与延时功能实现1、SysTick介绍2、SysTick中断使用3、SysTick实现微秒和毫秒延时功能CH32V307的RISC-V内核控制器自带的一个64位可选递增或递减的计数器,用于产生SYSTICK异常(异常号:15),可专用于实时操作系统,为系统提供“…

大模型的“淬炼”

——大模型也要经历“琢石成玉”的过程。 大规模语言模型的训练流程的确可以根据不同的模型架构、应用场景以及资源限制等因素有所变化。预训练和微调是最基本也是最常见的两个阶段&#xff0c;几乎在所有现代大模型训练流程中都会出现。而诸如奖励建模、强化学习尤其是人类反馈…

(南京观海微电子)——I3C协议介绍

特点 两线制总线&#xff1a;I2C仅使用两条线——串行数据线&#xff08;SDA&#xff09;和串行时钟线&#xff08;SCL&#xff09;进行通信&#xff0c;有效降低了连接复杂性。多主多从设备支持&#xff1a;I2C支持多个主设备和多个从设备连接到同一总线上。每个设备都有唯一…

《JAVA与模式》之桥梁模式

系列文章目录 文章目录 系列文章目录前言一、桥梁模式的用意二、桥梁模式的结构三、使用场景四、不使用模式的解决方案五、实现发送加急消息前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂…

React-路由小知识

1.默认路由 说明&#xff1a;当访问的是一级路由时&#xff0c;默认的二级路由组件可以得到渲染&#xff0c;只需要在二级路由的位置去掉path,设置index.属性为true。 2.404路由 说明&#xff1a;当浏览器输入ul的路径在整个路由配置中都找不到对应的pth,为了用户体验&#x…

【SQL】185. 部门工资前三高的所有员工(窗口函数dense_rank();区分rank()、row_number())

前述 推荐阅读&#xff1a;通俗易懂的学会&#xff1a;SQL窗口函数 题目描述 leetcode题目 185. 部门工资前三高的所有员工 思路 先按照departmentId分组&#xff0c;再按照salary排序 >窗口函数dense_rank() over() select B.name as Department,A.name as Employee,A…

学会Web UI框架--Bootstrap,快速搭建出漂亮的前端界面

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属的专栏&#xff1a;前端泛海 景天的主页&#xff1a;景天科技苑 文章目录 Bootstrap1.Bootstrap介绍2.简单使用3.布局容器4.Bootstrap实现轮播…

2023护网蓝初面试

目录 一、渗透测试的流程 二、常见的漏洞 三、中间件漏洞 四、SQL注入原理、种类&#xff1f;防御&#xff1f;预编译原理&#xff0c;宽字节注入原理 预编译原理&#xff1a; 宽字节注入原理&#xff1a; 五、XSS的种类有哪些&#xff1f;区别&#xff1f;修复&#xf…

13. npm软件包管理器和Node.js常用命令总结

一.包的概念 1. 包&#xff1a; 将模块&#xff0c;代码&#xff0c;其他资料整合成一个文件夹&#xff0c;这个文件夹就叫包 2. 包分类&#xff1a; 项目包&#xff1a;主要用于编写项目和业务逻辑软件包&#xff1a;封装工具和方法进行使用 3. 包要求&#xff1a; 根目…

gprof安装使用(CMake)说明

一、安装 1、gprof默认已安装&#xff0c;可安装相关图形处理 sudo apt-get install python graphviz sudo pip install gprof2dot 注意&#xff1a;在Debian中没有安装成功&#xff0c;报Python的版本不匹配 二、使用说明 1、使用CMake管理的工程&#xff1a; 重新配置CMa…

6 种 卷积神经网络压缩方法

文章目录 前言 1、低秩近似 2、剪枝与稀疏约束 3、参数量化 4、二值化网络 &#xff08;1&#xff09;二值网络的梯度下降 &#xff08;2&#xff09;两个问题 &#xff08;3&#xff09;二值连接算法改进 &#xff08;4&#xff09;二值网络设计注意事项 5、知识蒸馏 6、浅层 …

eclipse -XX:+PrintGCDetails

eclipse -XX:PrintGCDetails

二 超级数据查看器   讲解稿   导入功能

二 超级数据查看器 讲解稿 导入功能 APP下载地址 百度手机助手 下载地址4 ​ 讲解稿全文&#xff1a; 大家好。 今天我们对 超级数据查看器的 导入信息功能 做一下详细讲解。 首先&#xff0c;我们打开 超级数据查看器。 我们这个系统要实现的是&#xff0c;快速生…

基于粒子群(PSO)的PID控制器matlab仿真

算法实现简介 利用粒子群算法对 PID 控制器的参数进行优化设计&#xff0c;其过程如图 所示。 图中&#xff0c;粒子群算法与 Simulink 模型之间连接的桥梁是粒子&#xff08;即 PID 控制器参数&#xff09;和该粒子对应的适 应值&#xff08;即控制系统的性能指标&#xff09…

sql server 恢复数据库、恢复单表数据的方法

如果不小心把某个表的数据删了&#xff0c;可以用之前的备份文件对单表进行数据恢复。 1、新建一个数据库&#xff08;全新的数据库&#xff09;&#xff0c;记得路径&#xff0c;恢复的时候要用到&#xff0c;新建完不要对数据库做什么操作。 2、用需要恢复表的数据库的备份文…

遗传算法GA求解机器人栅格地图最短路径规划,可以自定义地图及起始点(提供MATLAB代码)

一、原理介绍 遗传算法是一种基于生物进化原理的优化算法&#xff0c;常用于求解复杂问题。在机器人栅格地图最短路径规划中&#xff0c;遗传算法可以用来寻找最优路径。 遗传算法的求解过程包括以下几个步骤&#xff1a; 1. 初始化种群&#xff1a;随机生成一组初始解&…

一款开源、免费、跨平台的Redis可视化管理工具

前言 经常有小伙伴在技术群里问&#xff1a;有什么好用的Redis可视化管理工具推荐的吗&#xff1f;, 今天大姚给大家分享一款我一直在用的开源、免费&#xff08;MIT License&#xff09;、跨平台的Redis可视化管理工具&#xff1a;Another Redis Desktop Manager。 Redis介绍…

再探再报 除 0 这件事有不同

首先&#xff0c;在数学中&#xff0c;一个数除以0是没有意义的。 其次&#xff0c;在计算机中&#xff0c;对于除零&#xff0c;传统概念里是会上报一个异常。首先是CPU内部实现会报异常。最早学组成原理和汇编的时候&#xff0c;都是说CPU寄存器中有个表示除零异常的位。在L…

你应该打好你的日志,起码避免被甩锅

大家好&#xff0c;我是蓝胖子,相信大家或多或少都有这样的经历&#xff0c;当你负责的功能出现线上问题时&#xff0c;领导第一时间便是找到你询问原因&#xff0c;然而有时问题的根因或许不在你这儿&#xff0c;只是这个功能或许依赖了第三方或者内部其他部门&#xff0c;这个…

Github 2024-03-10php开源项目日报Top10

根据Github Trendings的统计,今日(2024-03-10统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量PHP项目10Blade项目1Laravel:表达力和优雅的 Web 应用程序框架 创建周期:4631 天开发语言:PHP, BladeStar数量:75969 个Fork数量:24281 次…