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 OffCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"//propertiessampler2D _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);//contrastfixed3 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.198v_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.rhkb.cn/news/222730.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NXP iMX8MM 通过 TFTP和 NFS 启动示例

By Toradex秦海 1). 简介 嵌入式 Linux 设备开发调试时候为了方便部署各种配置和修改常用的一种方法就是通过网络启动&#xff0c;具体就是将 Linux Kernel&#xff08;以及 Device tree/Device Tree overlays) 从开发主机的 TFTP 服务加载&#xff0c; Linux rootfs 通过开发…

听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;该文件实现了从注…

【即插即用篇】YOLOv8改进实战 | 引入 Involution(内卷),用于视觉识别的新一代神经网络!涨点神器!

YOLOv8专栏导航:点击此处跳转 前言 YOLOv8 是由 YOLOv5 的发布者 Ultralytics 发布的最新版本的 YOLO。它可用于对象检测、分割、分类任务以及大型数据集的学习,并且可以在包括 CPU 和 GPU 在内的各种硬件上执行。 YOLOv8是一种尖端的、最先进的 (SOTA) 模型,它建立在以前成…

Centos7在安装Graylog时新安装MongoDB报错端口不监听服务不启动无法运行启动失败

由于虚拟机服务器上需要安装Graylog需要安装MongoDB&#xff0c;尝试官网下载安装包&#xff0c;和yum安装均无法正常启动&#xff0c;折腾了好几天&#xff0c;重装了十几次&#xff0c;网上搜索了很多很多资料&#xff0c;均无法正常运行&#xff0c;百度上搜索各种文档&…

华为端口隔离简单使用方法同vlan下控制个别电脑不给互通

必须得用access接口&#xff0c;hybrid口不行 dhcp enable interface Vlanif1 ip address 192.168.1.1 255.255.255.0 dhcp select interface interface MEth0/0/1 interface GigabitEthernet0/0/1 port link-type access port-isolate enable group 1 interface GigabitEther…

Node.js-模块化(二)

1. 模块化的基本概念 1.1 什么是模块化 模块化是指解决一个复杂问题时&#xff0c;自顶向下逐层将系统拆分成若干模块的过程。对于整个系统来说&#xff0c;模块是可组合、分解和更换的单元。 1.2 编程领域中的模块化 编程领域中的模块化&#xff0c;就是遵守固定的规则&…

Python之Django项目的功能配置

1.创建Django项目 进入项目管理目录&#xff0c;比如&#xff1a;D盘 执行命令&#xff1a;diango-admin startproject demo1 创建项目 如果提示diango命令不存在&#xff0c;搜索diango-admin程序的位置&#xff0c;然后加入到环境变量path中。 进入项目&#xff0c;cd demo…

嵌入式开发网络配置——windows连热点,开发板和电脑网线直连

目录 电脑 WiFi 上网&#xff0c;开发板和电脑直连 使用场景 设置VMware虚拟机的网络配置 Ubuntu设置——版本18.04 ​编辑 windows设置 开发板设置 原因&#xff1a;虚拟机Linux移植可执行程序到开发板失败 最后发现虚拟机的Linuxping不通开发板 下面是我的解决方法 …

微软的word文档中内置背景音乐步骤(打开自动播放)

目录 一、前言 二、操作步骤 一、前言 有时候需要在word文档里面打开的时候就自动播放音乐或者音频&#xff0c;那么可以用微软的word来按照操作步骤去这样完成。 如果没有微软office的&#xff0c;可以下载这个是2021专业版的。因为office只能免费使用一段时间&#xff0c…

猜数字游戏 C语言xdoj490

问题描述 猜数字游戏是令游戏机随机产生一个 100 以内的正整数&#xff0c;用户输入一个数对其进行猜测&#xff0c;需要你编写程序自动对其与随机产生的被猜数进行比较&#xff0c;并提示大了&#xff08;“Too big”&#xff09;&#xff0c;还是小了&#xff08;“Too smal…

Java小案例-Sentinel的实现原理

前言 Sentinel是阿里开源的一款面向分布式、多语言异构化服务架构的流量治理组件。 主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 核心概念 要想理解一个新的技…

vue3引入使用高德地图,不显示地图问题

将全局引入的mockjs去除&#xff0c;就可以了。

Springboot+vue的装饰工程管理系统(有报告),Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的装饰工程管理系统&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的装饰工程管理系统&#xff0c;采用M&#xff08…

【uniapp】uniapp中本地存储sqlite数据库保姆级使用教程(附完整代码和注释)

数据库请求接口封装 uniapp中提供了plus.sqlite接口&#xff0c;在这里我们对常用的数据库请求操作进行了二次封装 这里的dbName、dbPath、recordsTable 可以根据你的需求自己命名 module.exports {/** * type {String} 数据库名称*/dbName: salary,/*** 数据库地址* type {…

.Net Core webapi RestFul 统一接口数据返回格式

在RestFul风格盛行的年代&#xff0c;大部分接口都需要一套统一的数据返回格式&#xff0c;那么我们怎么才能保证使用统一的json数据格式返回呢&#xff0c;下面给大家简单介绍一下&#xff1a; 假如我们需要接口统一返回一下数据格式&#xff1a; {"statusCode": …

任天堂,steam游戏机通过type-c给VR投屏与PD快速充电的方案 三type-c口投屏转接器

游戏手柄这个概念&#xff0c;最早要追溯到二十年前玩FC游戏的时候&#xff0c;那时候超级玛丽成为了许多人童年里难忘的回忆&#xff0c;虽然长大了才知道超级玛丽是翻译错误&#xff0c;应该是任天堂的超级马里奥&#xff0c;不过这并不影响大家对他的喜爱。 当时FC家用机手柄…

【Xcode】解决Unable to process request - PLA Update available

出现场景 IOS更新app时&#xff0c;使用Xcode上传新版本的包时&#xff0c;提示无法上传。 Unable to process request -PLA update available you currently dont have access to this membership resource. To resolve this issue ,agree to the latest program license a…

PHP数组定义和输出

数组就是一组数据的集合&#xff0c;把一系列数据组织起来&#xff0c;形成一个可操作的整体。 PHP中的数组与Java的数组不一样&#xff0c;需要有key&#xff08;键&#xff09;和value&#xff08;值&#xff09;&#xff0c;相当于Java中数组和键值对的结合。 数组的定义 …

7ADC模数转换器

一.模数转换原理 ADC模拟-数字转换器可以将引脚上连续变化的模拟电压转换成内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁。另外一种是DAC既是与前面相反&#xff0c;如PWM波&#xff0c;由于PWM电路简单且没有额外的功率损耗&#xff0c;更适用于惯性系统的…

基于博弈树的开源五子棋AI教程[4 静态棋盘评估]

引子 静态棋盘的评估是棋力的一个很重要的体现&#xff0c;一个优秀的基于博弈树搜索的AI往往有上千行工作量&#xff0c;本文没有做深入讨论&#xff0c;仅仅写了个引子用来抛砖引玉。 评估一般从两个角度入手&#xff0c;一个是子力&#xff0c;另一个是局势。 1 评估维度 …