当前位置: 首页 > news >正文

Playcanvas后处理-辉光bloom

(一)Bloom介绍

Bloom(辉光、光晕、泛光)是一种常见的摄像机后处理(PostProcessing)效果,用于再现真实世界相机的成像伪影。这种效果会产生从图像中明亮区域边界延伸的光条纹(或羽毛),从而产生一种极其明亮的光线压倒捕捉场景的相机的错觉。

辉光简单的说法,就是有些地方足够亮,看上去是溢出到周围的区域,下面是playcanvas官方提供的辉光效果对比图

图1 未使用辉光效果

图2 使用辉光效果

(二)Bloom实现原理

bloom的实现原理很简单:就是取camera获取图像的高亮部分,进行高斯模糊,并和原图进行合并就可以实现。

1. 提取较亮区域

通过阈值提取较亮区域的像素点

varying vec2 vUv0;uniform sampler2D uBaseTexture
uniform float uBloomThreshold;float luminance(vec4 color)
{return  0.2125 * color[0] + 0.7154 * color[1] + 0.0721 * color[2]; 
}void main(void)
{vec4 color = texture2D(uBaseTexture, vUv0);// 只保留亮度超过阈值亮度的像素点float val = clamp(luminance(color) - uBloomThreshold, 0.0, 1.0);gl_FragColor = color * val;//这是playcanvas官网提供提取亮度高于某个阈值的算法,但还不知道它的原理//gl_FragColor = clamp((color - uBloomThreshold) / (1.0 - uBloomThreshold), 0.0, 1.0);
}

2. 高斯模糊

接下来,就是如何得到模糊图uBloomTexture

一般模糊图像的算法,我们可以选择常见的高斯模糊,它可以减少图像噪声、降低细节层次

高斯模糊的实现原理,这里不做多赘述,这里提供2篇文章供参考。

原理参考:2D Shader学习——高斯模糊

shader实现参考:基于线性采样的高效高斯模糊实现(译)

参考第二篇文章,我们在JavaScript中,计算我们高斯卷积核的权重和位移

var SAMPLE_COUNT = 15;//高斯曲线
function computeGaussian(n, theta) {return ((1.0 / Math.sqrt(2 * Math.PI * theta)) * Math.exp(-(n * n) / (2 * theta * theta)));
}function calculateBlurValues(sampleWeights, sampleOffsets, dx, dy, blurAmount) {// Create temporary arrays for computing our filter settings.// The first sample always has a zero offset.sampleWeights[0] = computeGaussian(0, blurAmount);sampleOffsets[0] = 0;sampleOffsets[1] = 0;// Maintain a sum of all the weighting values.var totalWeights = sampleWeights[0];// Add pairs of additional sample taps, positioned// along a line in both directions from the center.var i, len;for (i = 0, len = Math.floor(SAMPLE_COUNT / 2); i < len; i++) {// Store weights for the positive and negative taps.var weight = computeGaussian(i + 1, blurAmount);sampleWeights[i * 2] = weight;sampleWeights[i * 2 + 1] = weight;totalWeights += weight * 2;var sampleOffset = i * 2 + 1.5;sampleOffsets[i * 4] = dx * sampleOffset;sampleOffsets[i * 4 + 1] = dy * sampleOffset;sampleOffsets[i * 4 + 2] = -dx * sampleOffset;sampleOffsets[i * 4 + 3] = -dy * sampleOffset;}// Normalize the list of sample weightings, so they will always sum to one.for (i = 0, len = sampleWeights.length; i < len; i++) {sampleWeights[i] /= totalWeights;}
}

在fragment shader中,对图像进行卷积模糊(注意:这里的shader只对水平或垂直一个方向卷积

#define SAMPLE_COUNT 15varying vec2 vUv0;uniform sampler2D uBloomTexture;
uniform vec2 uBlurOffsets[15];
uniform float uBlurWeights[15];void main(void)
{vec4 color = vec4(0.0);for (int i = 0; i < SAMPLE_COUNT; i++){color += texture2D(uBloomTexture, vUv0 + uBlurOffsets[i]) * uBlurWeights[i];}gl_FragColor = color;
}    

最后,我们需要进行2次方向的滤波处理

原理具体参考文章二中,如何将高斯滤波器分为水平方向和垂直方向的滤波器的原理

// Pass 2: draw from rendertarget 1 into rendertarget 2(垂直方向)
calculateBlurValues(this.sampleWeights, this.sampleOffsets, 1.0 / this.targets[1].width, 0, this.blurAmount);
scope.resolve("uBlurWeights[0]").setValue(this.sampleWeights);
scope.resolve("uBlurOffsets[0]").setValue(this.sampleOffsets);
scope.resolve("uBloomTexture").setValue(this.targets[0].colorBuffer);
this.drawQuad(this.targets[1], this.blurShader);// Pass 3: draw from rendertarget 2 back into rendertarget 1(水平方向)
calculateBlurValues(this.sampleWeights, this.sampleOffsets, 0, 1.0 / this.targets[0].height, this.blurAmount);
scope.resolve("uBlurWeights[0]").setValue(this.sampleWeights);
scope.resolve("uBlurOffsets[0]").setValue(this.sampleOffsets);
scope.resolve("uBloomTexture").setValue(this.targets[1].colorBuffer);
this.drawQuad(this.targets[0], this.blurShader);

3. 混合原图和模糊图

那我们最后的fragment shader就可以这样实现,原图+模糊图进行混合

varying vec2 vUv0;//bloom 强度
uniform float uBloomEffectIntensity;uniform sampler2D uBaseTexture;
uniform sampler2D uBloomTexture;void main(void)
{vec4 bloom = texture2D(uBloomTexture, vUv0) * uBloomEffectIntensity;vec4 base = texture2D(uBaseTexture, vUv0);//将原图变暗,防止两图叠加后,像素溢出1base *= (1.0 - clamp(bloom, 0.0, 1.0));//合并原图和模糊图,得到最终的bloom效果gl_FragColor = base + bloom;
}

(三)在playcanvas编辑器中使用

1. 创建脚本bloom.js

// --------------- POST EFFECT DEFINITION --------------- //
var SAMPLE_COUNT = 15;function computeGaussian(n, theta) {return ((1.0 / Math.sqrt(2 * Math.PI * theta)) * Math.exp(-(n * n) / (2 * theta * theta)));
}function calculateBlurValues(sampleWeights, sampleOffsets, dx, dy, blurAmount) {// Look up how many samples our gaussian blur effect supports.// Create temporary arrays for computing our filter settings.// The first sample always has a zero offset.sampleWeights[0] = computeGaussian(0, blurAmount);sampleOffsets[0] = 0;sampleOffsets[1] = 0;// Maintain a sum of all the weighting values.var totalWeights = sampleWeights[0];// Add pairs of additional sample taps, positioned// along a line in both directions from the center.var i, len;for (i = 0, len = Math.floor(SAMPLE_COUNT / 2); i < len; i++) {// Store weights for the positive and negative taps.var weight = computeGaussian(i + 1, blurAmount);sampleWeights[i * 2] = weight;sampleWeights[i * 2 + 1] = weight;totalWeights += weight * 2;// To get the maximum amount of blurring from a limited number of// pixel shader samples, we take advantage of the bilinear filtering// hardware inside the texture fetch unit. If we position our texture// coordinates exactly halfway between two texels, the filtering unit// will average them for us, giving two samples for the price of one.// This allows us to step in units of two texels per sample, rather// than just one at a time. The 1.5 offset kicks things off by// positioning us nicely in between two texels.var sampleOffset = i * 2 + 1.5;// Store texture coordinate offsets for the positive and negative taps.sampleOffsets[i * 4] = dx * sampleOffset;sampleOffsets[i * 4 + 1] = dy * sampleOffset;sampleOffsets[i * 4 + 2] = -dx * sampleOffset;sampleOffsets[i * 4 + 3] = -dy * sampleOffset;}// Normalize the list of sample weightings, so they will always sum to one.for (i = 0, len = sampleWeights.length; i < len; i++) {sampleWeights[i] /= totalWeights;}
}/*** @class* @name BloomEffect* @classdesc Implements the BloomEffect post processing effect.* @description Creates new instance of the post effect.* @augments PostEffect* @param {GraphicsDevice} graphicsDevice - The graphics device of the application.* @property {number} bloomThreshold Only pixels brighter then this threshold will be processed. Ranges from 0 to 1.* @property {number} blurAmount Controls the amount of blurring.* @property {number} bloomIntensity The intensity of the effect.*/
function BloomEffect(graphicsDevice) {pc.PostEffect.call(this, graphicsDevice);// Shadersvar attributes = {aPosition: pc.SEMANTIC_POSITION};// Pixel shader extracts the brighter areas of an image.// This is the first step in applying a bloom postprocess.var extractFrag = ["varying vec2 vUv0;","","uniform sampler2D uBaseTexture;","uniform float uBloomThreshold;","","float luminance(vec4 color)","{","    return  0.2125 * color[0] + 0.7154 * color[1] + 0.0721 * color[2]; ","}","","void main(void)","{",// Look up the original image color."    vec4 color = texture2D(uBaseTexture, vUv0);","",// Adjust it to keep only values brighter than the specified threshold."    float val = clamp(luminance(color) - uBloomThreshold, 0.0, 1.0);","    gl_FragColor = color * val;","}"].join("\n");// Pixel shader applies a one dimensional gaussian blur filter.// This is used twice by the bloom postprocess, first to// blur horizontally, and then again to blur vertically.var gaussianBlurFrag = ["#define SAMPLE_COUNT " + SAMPLE_COUNT,"","varying vec2 vUv0;","","uniform sampler2D uBloomTexture;","uniform vec2 uBlurOffsets[" + SAMPLE_COUNT + "];","uniform float uBlurWeights[" + SAMPLE_COUNT + "];","","void main(void)","{","    vec4 color = vec4(0.0);",// Combine a number of weighted image filter taps."    for (int i = 0; i < SAMPLE_COUNT; i++)","    {","        color += texture2D(uBloomTexture, vUv0 + uBlurOffsets[i]) * uBlurWeights[i];","    }","","    gl_FragColor = color;","}"].join("\n");// Pixel shader combines the bloom image with the original// scene, using tweakable intensity levels.// This is the final step in applying a bloom postprocess.var combineFrag = ["varying vec2 vUv0;","","uniform float uBloomEffectIntensity;","uniform sampler2D uBaseTexture;","uniform sampler2D uBloomTexture;","","void main(void)","{",// Look up the bloom and original base image colors."    vec4 bloom = texture2D(uBloomTexture, vUv0) * uBloomEffectIntensity;","    vec4 base = texture2D(uBaseTexture, vUv0);","",// Darken down the base image in areas where there is a lot of bloom,// to prevent things looking excessively burned-out."    base *= (1.0 - clamp(bloom, 0.0, 1.0));","",// Combine the two images."    gl_FragColor = base + bloom;","}"].join("\n");this.extractShader = pc.createShaderFromCode(graphicsDevice, pc.PostEffect.quadVertexShader, extractFrag, 'BloomExtractShader', attributes);this.blurShader = pc.createShaderFromCode(graphicsDevice, pc.PostEffect.quadVertexShader, gaussianBlurFrag, 'BloomBlurShader', attributes);this.combineShader = pc.createShaderFromCode(graphicsDevice, pc.PostEffect.quadVertexShader, combineFrag, 'BloomCombineShader', attributes);this.targets = [];// Effect defaultsthis.bloomThreshold = 0.25;this.blurAmount = 4;this.bloomIntensity = 1.25;// Uniformsthis.sampleWeights = new Float32Array(SAMPLE_COUNT);this.sampleOffsets = new Float32Array(SAMPLE_COUNT * 2);
}BloomEffect.prototype = Object.create(pc.PostEffect.prototype);
BloomEffect.prototype.constructor = BloomEffect;BloomEffect.prototype._destroy = function () {if (this.targets) {var i;for (i = 0; i < this.targets.length; i++) {this.targets[i].destroyTextureBuffers();this.targets[i].destroy();}}this.targets.length = 0;
};BloomEffect.prototype._resize = function (target) {var width = target.colorBuffer.width;var height = target.colorBuffer.height;if (width === this.width && height === this.height)return;this.width = width;this.height = height;this._destroy();// Render targetsvar i;for (i = 0; i < 2; i++) {var colorBuffer = new pc.Texture(this.device, {name: "Bloom Texture" + i,format: pc.PIXELFORMAT_RGBA8,width: width >> 1,height: height >> 1,mipmaps: false});colorBuffer.minFilter = pc.FILTER_LINEAR;colorBuffer.magFilter = pc.FILTER_LINEAR;colorBuffer.addressU = pc.ADDRESS_CLAMP_TO_EDGE;colorBuffer.addressV = pc.ADDRESS_CLAMP_TO_EDGE;colorBuffer.name = 'pe-bloom-' + i;var bloomTarget = new pc.RenderTarget({name: "Bloom Render Target " + i,colorBuffer: colorBuffer,depth: false});this.targets.push(bloomTarget);}
};Object.assign(BloomEffect.prototype, {render: function (inputTarget, outputTarget, rect) {this._resize(inputTarget);var device = this.device;var scope = device.scope;// Pass 1: draw the scene into rendertarget 1, using a// shader that extracts only the brightest parts of the image.scope.resolve("uBloomThreshold").setValue(this.bloomThreshold);scope.resolve("uBaseTexture").setValue(inputTarget.colorBuffer);this.drawQuad(this.targets[0], this.extractShader);// Pass 2: draw from rendertarget 1 into rendertarget 2,// using a shader to apply a horizontal gaussian blur filter.calculateBlurValues(this.sampleWeights, this.sampleOffsets, 1.0 / this.targets[1].width, 0, this.blurAmount);scope.resolve("uBlurWeights[0]").setValue(this.sampleWeights);scope.resolve("uBlurOffsets[0]").setValue(this.sampleOffsets);scope.resolve("uBloomTexture").setValue(this.targets[0].colorBuffer);this.drawQuad(this.targets[1], this.blurShader);// Pass 3: draw from rendertarget 2 back into rendertarget 1,// using a shader to apply a vertical gaussian blur filter.calculateBlurValues(this.sampleWeights, this.sampleOffsets, 0, 1.0 / this.targets[0].height, this.blurAmount);scope.resolve("uBlurWeights[0]").setValue(this.sampleWeights);scope.resolve("uBlurOffsets[0]").setValue(this.sampleOffsets);scope.resolve("uBloomTexture").setValue(this.targets[1].colorBuffer);this.drawQuad(this.targets[0], this.blurShader);// Pass 4: draw both rendertarget 1 and the original scene// image back into the main backbuffer, using a shader that// combines them to produce the final bloomed result.scope.resolve("uBloomEffectIntensity").setValue(this.bloomIntensity);scope.resolve("uBloomTexture").setValue(this.targets[0].colorBuffer);scope.resolve("uBaseTexture").setValue(inputTarget.colorBuffer);this.drawQuad(outputTarget, this.combineShader, rect);}
});// ----------------- SCRIPT DEFINITION ------------------ //
var Bloom = pc.createScript('bloom');Bloom.attributes.add('bloomIntensity', {type: 'number',default: 1,min: 0,title: 'Intensity'
});Bloom.attributes.add('bloomThreshold', {type: 'number',default: 0.25,min: 0,max: 1,title: 'Threshold'
});Bloom.attributes.add('blurAmount', {type: 'number',default: 4,min: 1,'title': 'Blur amount'
});Bloom.prototype.initialize = function () {this.effect = new BloomEffect(this.app.graphicsDevice);this.effect.bloomThreshold = this.bloomThreshold;this.effect.blurAmount = this.blurAmount;this.effect.bloomIntensity = this.bloomIntensity;var queue = this.entity.camera.postEffects;queue.addEffect(this.effect);this.on('attr', function (name, value) {this.effect[name] = value;}, this);this.on('state', function (enabled) {if (enabled) {queue.addEffect(this.effect);} else {queue.removeEffect(this.effect);}});this.on('destroy', function () {queue.removeEffect(this.effect);this.effect._destroy();});
};

2. 将脚本挂载在相机

相关文章:

Playcanvas后处理-辉光bloom

&#xff08;一&#xff09;Bloom介绍 Bloom&#xff08;辉光、光晕、泛光&#xff09;是一种常见的摄像机后处理&#xff08;PostProcessing&#xff09;效果&#xff0c;用于再现真实世界相机的成像伪影。这种效果会产生从图像中明亮区域边界延伸的光条纹&#xff08;或羽毛…...

GCC 学习

GCC Resource Center for GCC Internalshttps://www.cse.iitb.ac.in/grc/这是个不错资料网站&#xff0c;有兴趣的可以了解下...

2023数维杯数学建模C题完整版本

已经完成全部版本&#xff0c;获取请查看文末下方名片 摘要 随着人工智能在多个领域的快速发展&#xff0c;其在文本生成上的应用引起了广泛关注。本研究聚焦于辨识人工智能&#xff08;AI&#xff09;生成文本的基本规则&#xff0c;并探究AI文本的检测及其与人类文本的区分…...

快速解密PPT幻灯片密码,让PPT重见天日

最简单的办法解密、找回和去除PPT幻灯片密码&#xff0c;具体步骤如下&#xff1a;1.百度搜索【密码帝官网】&#xff0c;2.点击“立即开始”在用户中心上传要解密的文件稍等片刻&#xff0c;就能找回密码。不用下载软件&#xff0c;手机电脑都可用。而且还支持Word、Excel、PD…...

十六、RabbitMQ快速入门

目录 一、在centos上下载MQ镜像 二、安装运行容器 三、登录进入MQ 1、添加一个新的用户 2、新建虚拟机 3、 为用户分配权限 四、RabbitMQ的基本概念 RabbitMQ中的几个概念: 五、常见消息模型 六、简单的消息生产与消费 1、消费者类 2、生产者类 3、基本消息队列的消…...

C#WPF用户控件及自定义控件实例

本文演示C#WPF自定义控件实例 用户控件(UserControl)和自定义控件(CustomControl)都是对UI控件的一种封装方式,目的都是实现封装后控件的重用。 只不过各自封装的实现方式和使用的场景上存在差异。 1 基于UserControl 创建 创建控件最简单一个方法就是基于UserControl …...

大模型的语言能力

NLP作为一个领域为基础模型开辟了道路。虽然这些模型在标准基准测试中占据主导地位&#xff0c;但这些模型目前获得的能力与那些将语言描述为人类交流和思维的复杂系统的能力之间存在明显的差距。针对这一点&#xff0c;我们强调语言变异的全部范围&#xff08;例如&#xff0c…...

直播岗位认知篇

一、直播岗位概述 直播岗位&#xff0c;也称为直播主播或直播运营&#xff0c;是指在互联网直播平台上进行直播活动的工作岗位。该岗位的主要职责是通过直播形式&#xff0c;向观众展示自己的才艺、分享生活、销售产品或服务&#xff0c;并引导观众互动和参与。直播主播需要具…...

后端技术知识点内容-全部内容-面试宝典-后端面试知识点

文章目录 -2 flink-1 linux of viewlinux查看占用cup最高的10个进程的命令&#xff1b; 〇、分布式锁 & 分布式事务0-1分布式锁--包含CAP理论模型概述分布式锁&#xff1a;分布式锁应该具备哪些条件&#xff1a;分布式锁的业务场景&#xff1a; 分布式锁的实现方式有&#…...

3.ubuntu20.04环境的ros搭建

ros搭建比较简单&#xff0c;主要步骤如下&#xff1a; 1.配置ros软件源&#xff1a; sudo sh -c echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list 2.配置密钥 sudo apt-key adv --keyser…...

米诺地尔行业分析:预计2029年将达到14亿美元

米诺地尔市场规模庞大&#xff0c;不仅包括消费品市场和服务行业&#xff0c;还涵盖了创新科技领域。随着经济的发展和市场需求的不断增长&#xff0c;米诺地尔市场的规模将继续扩大&#xff0c;各行各业都将面临更多机遇和挑战。 随着社会经济发展和城市化进程的推进&#xff…...

在Spring Boot中使用Thymeleaf开发Web页面

引言&#xff1a; 为啥写这篇文章呢&#xff1f;我明明就没怎么用过这个Thymeleaf进行web开发&#xff0c;用JSP也行&#xff0c;三剑客也行&#xff0c;或者Vue&#xff0c;React&#xff0c;PHP等等&#xff0c;不好吗&#xff1f; 那我为啥写这篇博客呢&#xff1f;这个写了…...

2023年亚太杯数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…...

linux高级篇基础理论五(用户安全,口令设置,JR暴力破解用户密码,NMAP端口扫描)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️不能因为人生的道路坎坷,就使自己的身躯变得弯曲;不能因为生活的历程漫长,就使求索的 脚步迟缓。 ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xff1a;云计算技…...

鸿蒙原生应用/元服务开发-AGC分发如何配置版本信息(上)

1.配置HarmonyOS应用的“发布国家或地区”。 2.设置是否为开放式测试版本。 注意&#xff1a;HarmonyOS应用开放式测试当前仅支持手机、平板、智能手表。如开发者想发布为开放式测试版本&#xff0c;选择“是”。正式发布的版本请选择“否”。 3.在“软件版本”下点击“软件包…...

探索Scrapy中间件:自定义Selenium中间件实例解析

简介 Scrapy是一个强大的Python爬虫框架&#xff0c;可用于从网站上抓取数据。本教程将指导你创建自己的Scrapy爬虫。其中&#xff0c;中间件是其重要特性之一&#xff0c;允许开发者在爬取过程中拦截和处理请求与响应&#xff0c;实现个性化的爬虫行为。 本篇博客将深入探讨…...

渗透测试--3.中间人攻击

渗透测试--3.中间人攻击 一 .中间人攻击arp欺骗DNS欺骗无线局域网漏洞利用使用 Ettercap 执行欺骗攻击arp欺骗实例1、首先查看欺骗之前靶机ip以及默认网关,2、查看kali的IP地址(192.168.76.134),MAC:000c294079903、使用Ettercap,将A主机和B主机加入到target中4、点击右上…...

nginx/html关闭网页缓存方法

【问题】 通常代理服务器默认是有缓存的&#xff0c;即用户访问网址的时候默认获取到的是缓存&#xff0c;只有刷新之后才能得到服务器端的最新文件 【解决】 以nginx为例&#xff0c;找到配置文件nginx.conf&#xff0c;找到http {}&#xff0c;在其花括号之内添加命令&…...

华为防火墙 Radius认证

实现的功能&#xff1a;本地内网用户上网时必须要进行Radius验证&#xff0c;通过后才能上网 前置工作请按这个配置&#xff1a;华为防火墙 DMZ 设置-CSDN博客 Windows 服务器安装 Radius 实现上网认证 拓扑图如下&#xff1a; 一、服务器配置 WinRadius 1、安装WinRadius …...

用spring发送http请求

在Spring中&#xff0c;你可以使用RestTemplate或WebClient来发送HTTP请求。下面分别给出使用这两个类的简单示例。 现在pom.xml中导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artif…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...