rtsp视频在使用unity三维融合播放后的修正

news2024/12/28 18:14:36

1 rtsp 接入

我们使用unity UE 等三维渲染引擎中使用c++编写插件来接入rtsp 视频。同时做融合的时候,和背景的三维颜色要一致,这就要使用视频融合修正技术。包括亮度,对比度,饱和度的修正。在单纯颜色上的修正可以简单使用rgb->hsv去修改,这里不做累赘说明了。

2 播放技术

使用unity 的纹理渲染来播放多路 视频,视频接入最大可达到30路,同时在untiy , UE5 中渲染。播放后有很多视频的颜色不一致,如何调整颜色成了一个问题

3 untiy 渲染过程

建立一个材质,如命名为m2
在这里插入图片描述
将m2 赋值给我们的面片,如pp
在这里插入图片描述
接下来创建一个shader,控制渲染的亮度,对比度,饱和度,分别是 Brightness, Saturation, Contrast, unity shader的基础不再啰嗦,各位可以稍稍看一下,不难。

Shader "self/BrightnessSaturationAndContrast"
{
    Properties
    {
        _MainTex ("Base(RGB", 2D) = "white" {}
        //从脚本传递更好,这里可以直接省略这些值的展示
        _Brightness ("Brightness", float) = 1
        _Saturation ("Saturation", float) = 1
        _Contrast ("Contrast", float) = 1
    }
    SubShader
    {
        Pass
        {
            //关闭深度写入
            //ZTest Always Cull Off Zwrite Off

            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            
            //properties
            sampler2D _MainTex;
            half _Brightness;
            half _Saturation;
            half _Contrast;

            struct v2f {
                float4 pos : SV_POSITION;
                half2 uv : TEXCOORD0; 
            };

            //使用了内置的appdata_img结构体作为顶点着色器的输入
            v2f vert(appdata_img  v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;
                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                //获得屏幕图像的采样
                fixed4 renderTex = tex2D(_MainTex, i.uv);

                //亮度
                fixed3 finalColor = renderTex.rgb * _Brightness;

                //饱和度
                fixed luminance = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;  //计算该像素的亮度值
                fixed3 luminanceColor = fixed3(luminance, luminance, luminance);  //创建饱和度为0的颜色
                finalColor = lerp(luminanceColor, finalColor, _Saturation);

                //contrast
                fixed3 avgColor = fixed3(0.5, 0.5, 0.5);
                finalColor = lerp(avgColor, finalColor, _Contrast);

                return fixed4(finalColor, renderTex.a);
            }
            ENDCG
        }
    }
    FallBack  Off
}

写好shader以后, 写一个脚本,调入我们的c#脚本,脚本一为控制我们的c++插件,二是可以修改,以下的插件脚本负责调入c++ 的插件,插件会在线程里面启动,获取图像,赋值给面片。插件本身可以接入实时视频,播放视频,倒放视频,支持国标gb28181和onvif协议,可以支持矫正视频,支持多组矫正参数,同时增加三个变量,改变亮度,对比度,饱和度,便于在里面实时修改观察。

//author: 钱波
using System;
using System.Text;
using System.Threading;
using System.Collections;
using UnityEngine;
using System.Runtime.InteropServices;
using UnityEngine.UI;
using System.Linq;
using System.Collections.Generic;
using Unity.VisualScripting;
using System.IO;


[StructLayout(LayoutKind.Sequential)]
public struct FRAME
{
    public int width;
    public int height;
    public int len;
    public IntPtr Frame;
    public IntPtr data;
    //public byte[] data;
    //[MarshalAs(UnmanagedType.LPArray)]
}
[StructLayout(LayoutKind.Sequential)]
public struct PARAM
{
    public double p1;
    public double p2;
    public double p3;
    public double p4;
    public double p5;
    public double p6;
    public double p7;
    public double p8;
    public double p9;
    public double c1;
    public double c2;
    public double c3;
    public double c4;
    public double c5;
}


public class rtspin : MonoBehaviour
{
    [DllImport("rtspPlugin")]
    public static extern bool rtsp_test([MarshalAs(UnmanagedType.LPStr)] string url, int isnv12);

    [DllImport("rtspPlugin")]
    public static extern bool rtsp_test_data([MarshalAs(UnmanagedType.LPStr)] string url,
        [MarshalAs(UnmanagedType.LPArray)] byte[] data, ref FRAME frame);

    [DllImport("rtspPlugin")]
    public static extern bool rtsp_test_data_nv12([MarshalAs(UnmanagedType.LPStr)] string url,
        [MarshalAs(UnmanagedType.LPArray)] byte[] data0, [MarshalAs(UnmanagedType.LPArray)] byte[] data1);

    [DllImport("rtspPlugin")]
    public static extern void rtsp_test_stop([MarshalAs(UnmanagedType.LPStr)] string url);

    [DllImport("rtspPlugin")]
    public static extern void rtsp_test_setparam([MarshalAs(UnmanagedType.LPStr)] string url, ref PARAM param);


    static string[] stringArray = {"rtsp://127.0.0.1/front.mkv" };
    static string[] stringPlanes = { "pp"};

    //Texture2D[] texture2Ds;
    int w1 = 1920;
    int h1 = 1080;
    int number = 1;


    [Range(0.0f, 3.0f)]
    public float brightness = 1.0f;

    [Range(0.0f, 3.0f)]
    public float saturation = 1.0f;

    [Range(0.0f, 3.0f)]
    public float contrast = 1.0f;
    public Material briSatConMaterial;
    class cmd
    {
        public int v_w1 = 1920;
        public int v_h1 = 1080;
        public byte[] v_data;
        public Texture2D v_texture2Ds;
        public cmd()
        {
            v_data = new byte[v_w1 * v_h1 * 3];
            v_texture2Ds = new Texture2D(v_w1, v_h1, TextureFormat.RGB24, false);//RGB24
        }
    }


    PARAM v_param;
    //byte[][] v_datas;
    Dictionary<int, cmd> hashMap_datas = new Dictionary<int, cmd>();
    //byte[][] hashMap_datas;


    void rtspThreading(string url)
    {
        Debug.Log(url);
        rtsp_test(url, 1);
    }


    void Start()
    {

        //string path = Application.dataPath + "/rtsp.txt";

        //path = path.Replace("/", "\\");
        //if (File.Exists(path))
        //{
        //    Debug.Log("FileExists");
        //    stringArray = File.ReadAllLines(path);
        //}
        //else
        //{
        //    Debug.Log("FileNotExists");
        //    File.CreateText(path);
        //}

        stringArray[0] = "rtsp://127.0.0.1/front.mkv";
        for (int i = 0; i < number; i++)
        {
            cmd c1 = new cmd();
            hashMap_datas.Add(i, c1);
        }
        v_param = new PARAM();

        //v_param.p1 = 6.5746697810243404e+002;
        //v_param.p2 = 0.0;
        //v_param.p3 = 3.1950000000000000e+002;
        //v_param.p4 = 0.0;
        //v_param.p5 = 6.5746697810243404e+002;
        //v_param.p6 = 2.3950000000000000e+002;
        //v_param.p7 = 0.0;
        //v_param.p8 = 0.0;
        //v_param.p9 = 1.0;
        //v_param.c1 = -0.5180232701824102559;
        //v_param.c2 = 0.5071524380583312119;
        //v_param.c3 = 0.0;
        //v_param.c4 = 0.0;
        //v_param.c5 = -0.5784359684793970446;

        //1281.48 0 975.5 0 1997.48 0 0 0 1 -0.6 0.4 0.1 0 -0.198
        v_param.p1 = 1281.48;
        v_param.p2 = 0.0;
        v_param.p3 = 975.5;
        v_param.p4 = 0.0;
        v_param.p5 = 1997.48;
        v_param.p6 = 0.0;
        v_param.p7 = 0.0;
        v_param.p8 = 0.0;
        v_param.p9 = 1.0;
        v_param.c1 = -0.6;
        v_param.c2 = 0.4;
        v_param.c3 = 0.1;
        v_param.c4 = 0.0;
        v_param.c5 = -0.198;


        GameObject go = GameObject.Find("pp");
        briSatConMaterial = go.GetComponent<MeshRenderer>().material;
    }
    private void OnGUI()
    {

        if (GUI.Button(new Rect(120, 10, 80, 30), "开始线程"))
        {
            Debug.Log("开始rtsp......");

            for (int i = 0; i < number; i++)
            {
                int currentIndex = i;
                Thread rtspthread1 = new Thread(() => rtspThreading(stringArray[currentIndex]));
                rtspthread1.Start();
                Thread.Sleep(1);
            }

        }

        //绘制按钮,以及按下断开连接按钮,发送断开连接请求
        if (GUI.Button(new Rect(210, 10, 80, 30), "结束线程"))
        {
            Debug.Log("结束rtsp......");
            for (int i = 0; i < number; i++)
            {
                int currentIndex = i;
                rtsp_test_stop(stringArray[currentIndex]);
            }
        }

    }


    //float delta_x, delta_y, delta_z;            //计算移动量
    //float distance = 5;
    //float ZoomSpeed = 5f;                  //拉近拉远速度
    //public bool isFar = true;
    void Update()
    {
        FRAME frame = new FRAME();
        if (briSatConMaterial != null)
        {
            briSatConMaterial.SetFloat("_Brightness", brightness);
            briSatConMaterial.SetFloat("_Saturation", saturation);
            briSatConMaterial.SetFloat("_Contrast", contrast);
        }
        for (int i = 0; i < number; i++)
        {
            if (rtsp_test_data(stringArray[i], hashMap_datas[i].v_data, ref frame))
            {
                 rtsp_test_setparam(stringArray[i], ref v_param);


                //Texture2D original = new Texture2D(w1, h1, TextureFormat.RGB24, false);
                //original.LoadRawTextureData(hashMap_datas[i].v_data);
                //FlipTexture(original, hashMap_datas[i].v_texture2Ds);
                hashMap_datas[i].v_texture2Ds.LoadRawTextureData(hashMap_datas[i].v_data);
                hashMap_datas[i].v_texture2Ds.Apply();
                GameObject go = GameObject.Find(stringPlanes[i]);
                go.GetComponent<MeshRenderer>().material.mainTexture = hashMap_datas[i].v_texture2Ds;
            }
        }
    }

    void OnDestroy()
    {
        Debug.Log("Destory, 结束rtsp......");
        for (int i = 0; i < number; i++)
        {
            int currentIndex = i;
            rtsp_test_stop(stringArray[currentIndex]);
        }
    }
}

结果

点击开始播放,rtsp线程开始播放,inspector里面可以调整三个值,可以直观地看到视频播放的亮度和对比度饱和度的改变。
在这里插入图片描述
修改一下亮度
在这里插入图片描述
同时修改三个参数的变化
在这里插入图片描述

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

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

相关文章

Android 权限申请

在Android中&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用在运行时需要动态申请权限。以下是一些步骤来动态申请权限&#xff1a; 在应用的清单文件&#xff08;AndroidManifest.xml&#xff09;中声明需要的权限。例如&#xff0c;如果应…

前端FLV视频直播解决方案

项目背景&#xff1a; 1. 后台给出一个地址&#xff0c;持续不断的推送flv视频流。 2.前端需要接收视频流&#xff0c;并寻找合适的播放插件。 一开始&#xff1a; 其实用的是xgplayer&#xff08;西瓜视频&#xff09;。 官网地址&#xff1a;西瓜播放器 使用的是直播&a…

ardupilot开发 --- 风机不停机巡检 篇

在哪里创建的siyi实例&#xff1f; 如何传递飞控的时间戳给siyi相机&#xff1f; AP_RTC_ENABLED在waf编译时配置为1&#xff1f;&#xff1f; 如何配置&#xff1f; 在lua脚本中如何获取这个时间AP::rtc().get_utc_usec(utc_usec)&#xff1f;&#xff1f;&#xff1f; inclu…

【软件问题】解决 SecoClient 提示:接收返回码超时!

解决 SecoClient 提示&#xff1a;接收返回码超时&#xff01; 1.问题描述2.问题查找3.问题解决 系统&#xff1a;Win10 1.问题描述 这段时间因为不小心得了流感&#xff0c;所以需要请病假&#xff0c;而有些工作还得做不能落下&#xff0c;所以得居家办公&#xff0c;因为我…

【深入解析spring cloud gateway】12 gateway参数调优与分析

本节主要对网关主要的一些参数做一些解释说明&#xff0c;并用压测工具测试一下网关的接口&#xff0c;通过压测来验证参数配置是否合理 一、连接池参数 参数示例 spring:application:name: gatewaycloud:gateway:# http连接设置httpclient:# 全局的响应超时时间&#xff0c…

大语言模型(LLM)与 Jupyter 连接起来了!

现在&#xff0c;大语言模型&#xff08;LLM&#xff09;与 Jupyter 连接起来了&#xff01; 这主要归功于一个名叫 Jupyter AI 的项目&#xff0c;它是官方支持的 Project Jupyter 子项目。目前该项目已经完全开源&#xff0c;其连接的模型主要来自 AI21、Anthropic、AWS、Co…

【Git】在 IDEA 中合并多个 commit 为一个

文章目录 1 未提交到远程分支1.1 需求说明1.2 reset 操作1.3 再次 push 2 已经提交到远程分支2.1 需求说明2.2 rebase 操作2.3 强制 push 分两种情况&#xff1a; 一种是本地提交还没推到远程&#xff0c;这种好处理另一种是已经提交到远程分支&#xff0c;这个略麻烦 1 未提…

【Java代码审计】RCE篇

【Java代码审计】RCE篇 1.Java中的RCE2.ProcessBuilder命令执行漏洞3.Runtime exec命令执行漏洞4.脚本引擎代码注入5.RCE的防御 1.Java中的RCE 在PHP开发语言中有system()、exec()、shell_exec()、eval()、passthru()等函数可以执行系统命令。在Java开发语言中可以执行系统命令…

如何从 Android 手机免费恢复已删除的通话记录/历史记录?

有一个有合作意向的人给我打电话&#xff0c;但我没有接听。更糟糕的是&#xff0c;我错误地将其删除&#xff0c;认为这是一个骚扰电话。那么有没有办法从 Android 手机恢复已删除的通话记录呢&#xff1f;” 塞缪尔问道。如何在 Android 上恢复已删除的通话记录&#xff1f;如…

STM32CubeMX驱动ST7789

环境 1、单片机:STM32F103C8T6 2、开发平台&#xff1a;STM32CUBEMXkeil mdk 3、屏幕&#xff1a;ST7789&#xff0c;分辨率240*240 STM32配置 1、使用硬件SPI1驱动屏幕。配置如下&#xff1a; 2、屏幕控制引脚配置&#xff1a; 注意&#xff1a;只配置了DC,RST,CS这3个控…

BearPi Std 板从入门到放弃 - 后天篇(3)(ESP8266透传点灯)

简介 电脑搭建一个TCP Server&#xff0c; ESP8266 串口设置好透传模式, 再由TCP Server发送指令控制灯的亮灭; 开灯指令&#xff1a; led_on回车 &#xff1b; 关灯指令: led_off回车 主芯片: STM32L431RCT6 LED : PC13 \ 推挽输出即可 \ 高电平点亮 串口: Usart1 / LPUART E…

html之如何设置音频和视频

文章目录 前言一、音频标签&#xff1a;audio1.audio简介2.常用属性controlsautoplayloop代码演示&#xff1a; 二、视频标签&#xff1a;video1.video2.常用的视频元素controlsautoplayloop代码演示&#xff1a; 总结视频元素总结音频元素总结 前言 html中插入音频和视频的方…

网络通信--深入理解网络和TCP / IP协议

计算机网络体系结构 TCP/IP协议族 TCP / IP 网络传输中的数据术语 网络通信中的地址和端口 window端查看IP地址和MAC地址&#xff1a;ipconfig -all MAC层地址是在数据链路层的&#xff1b;IP工作在网络层的 MAC是48个字节&#xff0c;IP是32个字节 在子网&#xff08;局域…

4 postman响应数据解析

上一篇:3 使用postman批量创建测试数据-CSDN博客 在接口测试中,从接口的响应结果中获取数据是很常用的。比如说做断言的时候,需要确保接口返回数据是符合预期的。又比如有些接口的输入参数值,需要用到前面接口运行返回的数据。下面先介绍如何解析响应数据(以json数…

轻量封装WebGPU渲染系统示例<54>- 拱形门

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/GLBMaterialTest.ts 当前示例运行效果:

vue中最重要的点,双向数据绑定是什么?

一、什么是双向绑定 我们先从单向绑定切入单向绑定非常简单&#xff0c;就是把Model绑定到View&#xff0c;当我们用JavaScript代码更新Model时&#xff0c;View就会自动更新双向绑定就很容易联想到了&#xff0c;在单向绑定的基础上&#xff0c;用户更新了View&#xff0c;Mo…

Eigen库之Quaterniond

Eigen::Quaterniond 是 Eigen C 库中用于表示四元数的类&#xff0c;四元数在计算机图形学、机器人学等领域中广泛用于表示旋转操作。 四元数是一种数学结构&#xff0c;通常用于表示和计算三维空间中的旋转。一个四元数由一个实部和三个虚部组成&#xff0c;可以写成如下形式&…

mysql主从复制(在虚拟机centos的docker下)

1.安装docker Docker安装(CentOS)简单使用-CSDN博客 2.部署2个mysql docker run --name some-mysql1 -p 33061:3306 -e MYSQL_ROOT_PASSWORD123456 -d mysql:5.7 --character-set-serverutf8mb4 --collation-serverutf8mb4_unicode_cidocker run --name some-mysql2 -p 330…

Android 13 - Media框架(23)- ACodecBufferChannel

这一节我们将了解 ACodecBufferChannel 上一节我们了解到input buffer 和 output buffer 是如何分配的了&#xff0c;allocateBuffersOnPort 方法的最后会将ACodec::BufferInfo 中的 mData 成员组织成为数组&#xff0c;最后提交给 ACodecBufferChannel 管理。这一节我们将尝试…

MySQL数据库基本操作语言:SQL

SQL 概述 SQL是一 种用于操作数据库的语言&#xff0c;SQL适用于所有关系型数据库。 MySQL、Oracle、 SQLServer是一 一个数据库软件,这些数据库软件支持标准SQL,也就是通过SQL可以使用这些软件,不过每一个数据库系统会在标准SQL的基础 上扩展自己的SQL语法。 大部分的NoSQ…