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

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里面可以调整三个值,可以直观地看到视频播放的亮度和对比度饱和度的改变。
在这里插入图片描述
修改一下亮度
在这里插入图片描述
同时修改三个参数的变化
在这里插入图片描述

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

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

相关文章

逻辑回归(LR,Logistic Regression)算法 简介

逻辑回归&#xff08;LR&#xff0c;Logistic Regression&#xff09;算法 当线性回归的预测结果&#xff0c;由于受到个别极端数值的影响而不准的时候, 可以用逻辑回归来解决. 逻辑回归模型的输出只能在 0 到 1 之间&#xff0c;也就是表达一个事件会发生的概率&#xff0c;…

从0开始学Git指令

从0开始学Git指令 因为网上的git文章优劣难评&#xff0c;大部分没有实操展示&#xff0c;所以打算自己从头整理一份完整的git实战教程&#xff0c;希望对大家能够起到帮助&#xff01; 初始化一个Git仓库&#xff0c;使用git init命令。 添加文件到Git仓库&#xff0c;分两步…

Vue.js 教程

Vue.js&#xff08;读音 /vjuː/, 类似于 view&#xff09; 是一套构建用户界面的渐进式框架。 Vue 只关注视图层&#xff0c; 采用自底向上增量开发的设计。 Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 阅读本教程前&#xff0c;您需要了解的…

万德高科携手航天科技AIRIOT打造智慧能碳管理平台, 助力碳达峰碳中和

“十四五”时期&#xff0c;我国生态文明建设进入了以降碳为重点战略方向、推动减污降碳协同增效、促进经济社会发展全面绿色转型、实现生态环境质量改善由量变到质变的关键时期。“实施数字化赋能行动”&#xff0c;聚焦能源管理、节能降碳、低碳能力等典型场景&#xff0c;推…

node实现简单的数据爬虫

前言 我使用的是墨迹天气的页面&#xff0c;因为这个使用的链接简单 页面结构简单并且大都是文字形式 第一步 打开墨迹天气网址 随便点开一个页面 点击F12或者鼠标右键点击检查 查看页面的信息 分析页面内容 使用文字所在的class和标签来定位 编写代码 配置express环境 …

EasyExcel 导出文件的格式化

阿里开源的这个库&#xff0c;让 Excel 导出不再复杂&#xff08;既要能写&#xff0c;还要写的好看&#xff09; 之前聊了 EasyExcel 的内容导出&#xff0c;本文主要说一下导出文件的格式化&#xff0c;格式化包括工作表/单元格样式和内容格式化。毕竟&#xff0c;有时候还是…

Opencv入门五 (显示图片灰度值)

源码如下&#xff1a; #include <opencv2/opencv.hpp> int main(int argc, char** argv) { cv::Mat img_rgb, img_gry, img_cny; cv::namedWindow("Example Gray",cv::WINDOW_AUTOSIZE); cv::namedWindow("Example Canny", cv::WINDOW_…

ruoyi若依前后端分离版部署centos7服务器(全)

目录 VMware虚拟机 centos7 安装环境如下 一、msql 5.7 二、nginx1.23.3 三、java8 四、redis 3.2.1 五、部署若依前端 六、部署若依后端 前言 虚拟机的桥接与nat模式 : 重点 重点&#xff01;&#xff01;&#xff01; 无线不可以用桥接模式 &#xff0c;而你用了nat模式会…

苹果cms模板MXone V10.7魔改版源码/ 苹果cms主题源码/苹果cmsv10模板MXone自适应模板/全开源无授权无加密

源码简介&#xff1a; 苹果cms模板MXone V10.7魔改版源码、苹果cms主题源码&#xff0c;作为苹果cmsv10模板MXone自适应模板&#xff0c;它是全开源无授权无加密。二开优化修复开源版影视网站源码。 MXone自适应模板&#xff0c;苹果cms v10开源无授权无加密电影网站模板。原…

Html / CSS刷题笔记

WebKit是一个开源的浏览器引擎&#xff0c;它最初是由苹果公司开发的&#xff0c;并且被广泛用于Safari浏览器和其他基于WebKit的浏览器&#xff0c;比如Google Chrome的早期版本。它也是构建许多移动设备浏览器的基础。WebKit的主要功能是解析HTML和CSS&#xff0c;并将其渲染…

SQL---Zeppeline前驱记录与后驱记录查询

内容导航 类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统…

前后端实现解析用户请求ip地址

前言 在我的软件系统中,如果希望安全系数高一些的话,往往会有用户登陆行为表来记录用户登陆行为,保障用户账号安全,比如记录登陆地址,每次登陆时候读取数据最近几次登陆地点,进行账号安全验证 假如以下是我的用户登陆行为表 实现获取用户登陆地址的方法有很多种,比如通过前端整…

听GPT 讲Rust源代码--src/tools(18)

File: rust/src/tools/rust-analyzer/crates/ide-ssr/src/from_comment.rs 在Rust源代码中的from_comment.rs文件位于Rust分析器&#xff08;rust-analyzer&#xff09;工具的ide-ssr库中&#xff0c;它的作用是将注释转换为Rust代码。 具体来说&#xff0c;该文件实现了从注…

机器学习 | 概率图模型

见微知著&#xff0c;睹始知终。 见到细微的苗头就能预知事物的发展方向&#xff0c;能透过微小的现象看到事物的本质&#xff0c;推断结论或者结果。 概率模型为机器学习打开了一扇新的大门&#xff0c;将学习的任务转变为计算变量的概率分布。 实际情况中&#xff0c;各个变量…

java easyexcel上传和下载数据

安装依赖 easyexcel官方文档 <!--通过注解的方式导出excel--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.1</version></dependency>注意踩坑&#xff1a;easyexcel会…

Linux服务器 部署飞书信息发送服务

项目介绍&#xff1a; 飞书信息发送服务是指将飞书信息发送服务部署到一个Linux服务器上。飞书是一款企业级的即时通讯和协作工具&#xff0c;支持发送消息给飞书的功能。通过部署飞书信息发送服务&#xff0c;可以方便内网发送信息给外网飞书。 项目代码结构展示&#xff1a; …

51单片机(STC8)-- 串口配置及串口重定向(printf)

文章目录 STC8串口概述串口寄存器配置串口1控制寄存器SCON串口1数据寄存器SBUF串口1模式 1工作方式串口1波特率计算方式 串口注意事项串口1通信demo串口重定向 STC8串口概述 由下图可知STC8H3K64S4带有4个4个串行通信接口&#xff0c;芯片名后两位S所带的数字即代表这款芯片带…

用户管理第2节课--idea 2023.2 后端--实现基本数据库操作(操作user表) -- 自动生成

一、插件 Settings... 1.1 File -- Settings 1.2 Settings -- Plugins 1.2.1 搜索框&#xff0c;也可以直接搜索 1.3 Plugins -- 【输入 & 搜索】mybatis 1.3.1 插件不同功能介绍 1.3.2 翻译如下 1.4 选中 Update&#xff0c;更新下 1.4.1 更新中 1.4.2 Restart IDE 1…

华为全屋wifi6蜂鸟套装标准

华为政企42 华为政企 目录 上一篇华为安防监控摄像头下一篇华为企业级无线路由器

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个控…