广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >基于Unity实现2D边缘检测
  • 182
分享到

基于Unity实现2D边缘检测

2024-04-02 19:04:59 182人浏览 安东尼
摘要

目录一、ShaderLab1.Alpha值边缘检测2.卷积边缘检测二、ShaderGraph一、ShaderLab 1.Alpha值边缘检测 根据图片的Alpha值边缘判定,向内扩

一、ShaderLab

1.Alpha值边缘检测

根据图片的Alpha值边缘判定,向内扩一段距离做边缘,颜色设置未描边颜色;

片元着色阶段,向上下左右四个方向做检测,有一个点的透明度为0,判定为边缘;

Shader "2DOutline"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
		_LineWidth("Width",Range(0,0.4)) = 1.0
		_LineColor("LineColor",color) = (1,1,1,1)
		_Intensity("Intensity",Range(1,10)) = 1.0
	}

	SubShader
	{
		Tags { "RenderType" = "Opaque" "Queue" = "Transparent"}
		Blend SrcAlpha OneMinusSrcAlpha
		
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITioN;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed _LineWidth;
			float4 _LineColor;
			fixed _Intensity;

			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				// 采样周围4个点
				float2 up_uv = i.uv + float2(0, 1) * _LineWidth * 1 / 10 * _MainTex_ST.xy;
				float2 down_uv = i.uv + float2(0,-1) * _LineWidth * 1 / 10 * _MainTex_ST.xy;
				float2 left_uv = i.uv + float2(-1,0) * _LineWidth * 1 / 10 * _MainTex_ST.xy;
				float2 right_uv = i.uv + float2(1,0) * _LineWidth * 1 / 10 * _MainTex_ST.xy;
				// 如果有一个点透明度为0 说明是边缘
				float w = tex2D(_MainTex,up_uv).a * tex2D(_MainTex,down_uv).a * tex2D(_MainTex,left_uv).a * tex2D(_MainTex,right_uv).a;

				if (w == 0) {
					col.rgb = lerp(_LineColor * _Intensity, col.rgb, w);
				}

				return col;
			}
		ENDCG
		} 
	}
}

如果图片内容恰好铺满整张图,没有alpha值,方法不适用;下图底部边缘消失了;

2.卷积边缘检测

在屏幕后处理阶段,使用卷积做边缘检测;

卷积:根据像素周围八个方向的像素的计算出新的像素值;

边缘检测卷积算子,都包含水平和竖直两个方向的卷积核;

梯度公式:G = sqrt(Gx*Gx + Gy*Gy);

考虑性能问题,使用:G = |Gx|+|Gy|;

顶点着色器计算卷积纹理采样坐标,减少计算量(片元数量更多);

片元着色阶段Sobel卷积计算,插值获得片元像素颜色;

Sobel计算结果和梯度Gradient比较,大于梯度和EdgeColor做插值;

屏幕后效调用OnRenderImage接口;

Shader "EdgeDetection" 
{
	Properties{
		_MainTex("Base (RGB)", 2D) = "white" {}
		_EdgeColor("Edge Color", Color) = (0, 0, 0, 1)		
        //卷积梯度
		_Gradient("Gradient",float) =0.0
	}
	SubShader{
		Pass 
		{
			ZTest Always Cull Off ZWrite Off

			CGPROGRAM

			#include "UnityCG.cginc"

			#pragma vertex vert  
			#pragma fragment frag

			sampler2D _MainTex;
			uniform half4 _MainTex_TexelSize;
			//fixed _EdgeOnly;
			fixed4 _EdgeColor;
			//fixed4 _BackgroundColor;
			fixed _Gradient;

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

			v2f vert(appdata_img v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);

				half2 uv = v.texcoord;

				o.uv[0] = uv + _MainTex_TexelSize.xy * half2(-1, -1);
				o.uv[1] = uv + _MainTex_TexelSize.xy * half2(0, -1);
				o.uv[2] = uv + _MainTex_TexelSize.xy * half2(1, -1);
				o.uv[3] = uv + _MainTex_TexelSize.xy * half2(-1, 0);
				o.uv[4] = uv + _MainTex_TexelSize.xy * half2(0, 0);
				o.uv[5] = uv + _MainTex_TexelSize.xy * half2(1, 0);
				o.uv[6] = uv + _MainTex_TexelSize.xy * half2(-1, 1);
				o.uv[7] = uv + _MainTex_TexelSize.xy * half2(0, 1);
				o.uv[8] = uv + _MainTex_TexelSize.xy * half2(1, 1);

				return o;
			}

			fixed luminance(fixed4 color) {
				return  0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
			}

			half Sobel(v2f i) {
				const half Gx[9] = {    -1,  0,  1,
										-2,  0,  2,
										-1,  0,  1};
				const half Gy[9] = {   -1, -2, -1,
										0,  0,  0,
										1,  2,  1};

				half texColor;
				half edgeX = 0;
				half edgeY = 0;
				for (int it = 0; it < 9; it++) {
					texColor = luminance(tex2D(_MainTex, i.uv[it]));
					edgeX += texColor * Gx[it];
					edgeY += texColor * Gy[it];
				}

				half edge = 1 - abs(edgeX) - abs(edgeY);

				return edge;
			}

			fixed4 frag(v2f i) : SV_Target {
				half edge = Sobel(i);

				fixed4 col = tex2D(_MainTex, i.uv[4]);

				if(edge> _Gradient)
					col = lerp(_EdgeColor, tex2D(_MainTex, i.uv[4]), edge);				
				
				return col;
			}

			ENDCG
		}
	}
	FallBack Off
}

二、ShaderGraph

抓取图片缓冲,上下左右四个方位平移,乘以描边颜色;

四张图合并,减去原图范围的像素,只剩边缘;

最后将原图和边缘合并(可插值使边缘柔和);

升级项目到URP,修改projectsetting-graphic-pielinesettings;

导入ShaderGraph包,开始拖拖拽拽,真的香,效果好,速度快,思路清晰;

到此这篇关于基于Unity实现2D边缘检测的文章就介绍到这了,更多相关Unity边缘检测内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 基于Unity实现2D边缘检测

本文链接: https://www.lsjlt.com/news/145612.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 基于Unity实现2D边缘检测
    目录一、ShaderLab1.Alpha值边缘检测2.卷积边缘检测二、ShaderGraph一、ShaderLab 1.Alpha值边缘检测 根据图片的Alpha值边缘判定,向内扩...
    99+
    2022-11-13
  • 基于Unity怎么实现2D边缘检测
    今天小编给大家分享一下基于Unity怎么实现2D边缘检测的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、ShaderLab...
    99+
    2023-06-30
  • Python OpenCV实现边缘检测
    本文实例为大家分享了Python OpenCV实现边缘检测的具体代码,供大家参考,具体内容如下 1. Sobel 算子检测 Sobel 算子是高斯平滑和微分运算的组合,抗噪能力很强,用途也很多,尤其是效率要求高但对细...
    99+
    2022-06-02
    python OpenCV 边缘检测
  • python实现图像边缘检测
    本文实例为大家分享了python实现图像边缘检测的具体代码,供大家参考,具体内容如下 任务描述 背景 边缘检测是数字图像处理领域的一个常用技术,被广泛应用于图像特征提取、目标识别、计...
    99+
    2022-11-11
  • Matlab实现图像边缘检测
    为了在一幅图像 f 的(x,y)位置寻找边缘的强度和方向,所选择的工具就是梯度,梯度使用向量来表示: 该向量指出了图像 f 在位置(x,y)处的最大变化率的方向,梯度向量的大小表示...
    99+
    2022-11-12
  • Python实现Opencv cv2.Canny()边缘检测
    目录1. 效果图2. 源码补充:OpenCV-Python 中 Canny() 参数这篇博客将介绍Canny边缘检测的概念,并利用cv2.Canny()实现边缘检测; Ca...
    99+
    2022-11-12
  • OpenCV中Canny边缘检测的实现
    目录1. Canny 边缘检测理论1.1、高斯滤波1.2、Sobel算子计算梯度和方向1.3、非极大值抑制(定位准确的边缘同时可缩小边缘线宽)1.4、双阈值检测2. OpenCV 之...
    99+
    2022-11-12
  • Python+OpenCV实现边缘检测与角点检测详解
    目录一、边缘检测1.1、读取图像1.2、图像转换成灰度图像1.3、Sobel算子1.4、Canny算子1.5、显示正常中文的标签1.6、边缘检测结果二、角点检测2.1、读取图像2.2...
    99+
    2023-02-03
    Python OpenCV边缘检测 Python OpenCV角点检测 Python OpenCV 检测
  • OpenCV实现Sobel边缘检测的示例
    目录一、Sobel算法1、算法概述2、主要函数二、C++代码三、python代码四、结果展示五、相关链接一、Sobel算法 1、算法概述 Sobel边缘检测算法比较简单,实际应用中效...
    99+
    2022-11-13
    OpenCV Sobel边缘检测 OpenCV 边缘检测
  • 使用OpenCV怎么实现Canny边缘检测
    今天就跟大家聊聊有关使用OpenCV怎么实现Canny边缘检测,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. Canny 边缘检测理论Canny 是一种常用的边缘检测算法. 其是...
    99+
    2023-06-20
  • python实现ROA算子边缘检测算法
    python实现ROA算子边缘检测算法的具体代码,供大家参考,具体内容如下 代码 import numpy as np import cv2 as cv def ROA(im...
    99+
    2022-11-12
  • Android+OpenCv4实现边缘检测及轮廓绘制出图像最大边缘
    实现步骤: 图像灰度化 边缘检测 根据Canny检测得出来的Mat寻找轮廓 算出最大轮廓周长or面积 根据获取到的最大轮廓下标进行轮廓绘制 ...
    99+
    2022-11-12
  • Python中怎么实现Opencv cv2.Canny()边缘检测
    这期内容当中小编将会给大家带来有关Python中怎么实现Opencv cv2.Canny()边缘检测,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1. 效果图原始图 VS Canny检测效果图如下:2. ...
    99+
    2023-06-20
  • Python OpenCV Canny边缘检测算法如何实现
    本文小编为大家详细介绍“Python OpenCV Canny边缘检测算法如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python OpenCV Canny边缘检测算法如何实现”文章能帮助...
    99+
    2023-07-02
  • Android+OpenCv4如何实现边缘检测及轮廓绘制出图像最大边缘
    这篇文章将为大家详细讲解有关Android+OpenCv4如何实现边缘检测及轮廓绘制出图像最大边缘,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。实现步骤:图像灰度化边缘检测根据Canny检测得出来的Mat...
    99+
    2023-06-15
  • Python+OpenCV图像边缘检测四种实现方法
    目录1.Sobel算子2.Schaar算子(更能体现细节)3.Laplacian算子(基于零穿越的,二阶导数的0值点)4.Canny边缘检测(被认为是最优的边缘检测算法)总结 im...
    99+
    2022-11-12
  • C语言实现BMP图像边缘检测处理
    本文实例为大家分享了C语言实现BMP图像边缘检测处理的具体代码,供大家参考,具体内容如下 以Sobel算子为例,其余模板算子卷积代码部分同Sobel算子。如:高斯算子、拉普拉斯算子等...
    99+
    2022-11-12
  • Python利用OpenCV和skimage实现图像边缘检测
    目录一、简介二、opencv 实践三、skimage 实践一、简介 提取图片的边缘信息是底层数字图像处理的基本任务之一。边缘信息对进一步提取高层语义信息有很大的影响。大部分边缘检测算...
    99+
    2022-12-28
    Python OpenCV 图像边缘检测 Python skimage图像边缘检测 Python图像边缘检测
  • Python中图像边缘检测算法如何实现
    这篇“Python中图像边缘检测算法如何实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python中图像边缘检测算法如何...
    99+
    2023-06-30
  • 基于C#如何实现多边形冲突检测
    这篇文章主要为大家展示了“基于C#如何实现多边形冲突检测”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“基于C#如何实现多边形冲突检测”这篇文章吧。前言之前在项目上碰到了一个多边形冲突检测的问题,...
    99+
    2023-06-20
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作