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.hqwc.cn/news/292796.html

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

相关文章

JavaScript读写15693 ICod2 卡源码

本示例使用设备 &#xff1a; https://item.taobao.com/item.htm?spma1z10.5-c-s.w4002-21818769070.11.23eb789efg450Y&id615391857885 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-t…

无头 SEO:技术实施的 8 个基本步骤

确保您的内容在无头 CMS 环境中大放异彩。按照我们的 8 个步骤进行一流的无头 SEO。 无头内容管理系统 &#xff08;CMS&#xff09; 正在兴起&#xff0c;迅速被宜家、耐克和国家地理等大品牌采用。 那里有很多选择&#xff0c;而且更有可能的是&#xff0c;作为 SEO 专业人士…

宝塔+Let‘s Encrypt给网站安装免费SSL证书

文件验证老是不通过&#xff0c;遂选择DNS验证&#xff1a; DNS验证也不过&#xff0c;发现腾讯云DNS解析的时候填写不能填宝塔页面给的完整的“解析域名”内容&#xff0c;只需填前面一部分就行了&#xff1a; ref: https://cloud.tencent.com/document/product/302/54454

非隔离恒压ACDC稳压智能电源模块芯片推荐:SM7015

非隔离恒压ACDC稳压智能电源模块芯片是一种用于将交流&#xff08;AC&#xff09;电源转换为直流&#xff08;DC&#xff09;电源的集成电路。这种芯片具有恒压输出功能&#xff0c;能够保持输出电压的稳定&#xff0c;适用于各种需要直流电源的应用场景。 非隔离电源模块通常…

SQL 多字段条件查询

SQL 多字段条件查询 一个数据库表&#xff0c;几十个字段&#xff0c;查找任意字段里包含北京的记录&#xff0c;在 mysql 里这句 sql 应该是这样&#xff1a; SELECT * FROM table WHERE concat(field1,field2,field3……fieldn) like ‘% 北京 %’ 反正是少不了将几十个字…

Angular 进阶之五: Signals到底用不用?

Angular 在V16的时候推出了Signals&#xff0c;在17正式作为主打功能之一强烈推荐&#xff0c;看过了各种博主的各种科普文章也没说明白&#xff0c;到底这东西值不值得用&#xff1f;毕竟项目大了&#xff0c;重构代码也不是闹着玩儿的。各种科普文章主要在说两点&#xff1a;…

Docker可视化界面【Portainer】安装

Portainer是一个可视化的容器镜像的图形管理工具&#xff0c;利用Portainer可以轻松构建&#xff0c;管理和维护Docker环境。 而且完全免费&#xff0c;基于容器化的安装方式&#xff0c;方便高效部署。 一、拉取镜像 docker pull portainer/portainer 二、运行portainer容…

如何将采购时间从几天缩短为几小时?

从事采购工作时&#xff0c;采购需要多长时间是面临的常见挑战之一。 采购是供应链中的一个环节&#xff0c;大家都不想看到整个流程被拖慢&#xff0c;但很多时候&#xff0c;事情往往向超出控制范围的方向发展。不过&#xff0c;企业可以通过多种方式简化采购和管理整个采购…

Redis实现日榜|直播间榜单|排行榜|Redis实现日榜01

前言 直播间贡献榜是一种常见的直播平台功能&#xff0c;用于展示观众在直播过程中的贡献情况。它可以根据观众的互动行为和贡献值进行排名&#xff0c;并实时更新&#xff0c;以鼓励观众积极参与直播活动。 在直播间贡献榜中&#xff0c;每个观众都有一个对应的贡献值&#…

华为鸿蒙4.0来袭:带你从0开始上手鸿蒙开发!

今天我们来聊一聊鸿蒙。 鸿蒙是什么呢&#xff1f;它是华为自家打造的一个操作系统。就好比苹果有iOS&#xff0c;谷歌有Android&#xff0c;华为也想有一个属于自己的系统&#xff0c;这就是鸿蒙。 那鸿蒙有什么特色呢&#xff1f;首先&#xff0c;它采用了微内核设计。微内…

软件测试:最强面试题整理出炉附答案,一点点小总结,建议收藏

一、Web自动化测试 1.Selenium中hidden或者是display &#xff1d; none的元素是否可以定位到&#xff1f; 不能,可以写JavaScript将标签中的hidden先改为0&#xff0c;再定位元素 2.Selenium中如何保证操作元素的成功率&#xff1f;也就是说如何保证我点击的元素一定是可以点…

云渲染Blender怎么用 Blender云渲染设置教程

作为一个免费且开源的三维创作套件&#xff0c;Blender为独立艺术家和小规模的创意团队提供了一个功能丰富的平台&#xff0c;涵盖了从建模、雕刻到动力学模拟、动画和高级渲染的全套工作流程。随着其支持的特效和视觉质量的不断提升&#xff0c;Blender项目的渲染耗时也显著增…