Unity边缘检测的数学原理和shader实现

最近一直研究基于灰度的边缘检测,搜索了好多博客文章,发现没有对Sobel算子解释的非常清晰明了的,对于我这种数学控,细节控,实在是无法忍受,所以索性自己查阅数学资料,研究一番,花了一周时间终于搞清楚了所有的困惑,分享给大家。这篇文章非常长,分成3个部分:实现原理,代码部分,数学部分,大家可以根据需要查看,如果能从头到尾啃完,相信一定有巨大收获!由于我不想把所有数学公式再打一遍了,所以直接上图了,请谅解

目录

1.实现原理

1-1.边缘检测的原理

1-2.像素的梯度

1-3.思路总结

 1-4.像素的梯度

 1-5. 曼哈顿距离(Manhattan Distance )

2.Shader实现

2-1.思路

 2-2.C#部分

2-3.Shader部分

3.数学部分

a.导数定义

 b.线性近似

c.两个变量时的近似

d.两个变量的链式求导

 e.方向导数

 f.梯度(Gradient)

 g.梯度的坐标系变换

 4.参考文献


1.实现原理

1-1.边缘检测的原理

图像由像素点组成的,在像素点的灰度变化剧烈的地方就可以被当作是边缘.

a.比较灰度

       像素点一般来说可以有三种颜色表示,RGB,单独比较任何以中颜色,都不能表达图像某区域的变化.所以要比较灰度.

b.单像素点的最大变化值

每个像素点的灰度变化,是和周围像素点比较的结果,而且这个比较是有方向的某个方向也许变化不大,另一个方向变化或许很大必须选取变化最大的一个方向的数值,这个数值才有资格代表这个像素点的变化率. 从数学角度来说,灰度在某个方向的变化率,其实就是灰度在某个方向上的方向导数那么哪个方向的方向导数最大呢,是梯度的方向(注意,梯度是个向量),并且这个最大方向导数的绝对值,也就是最大的变化率的绝对值,等于梯度的模.

c.选出边缘

每个像素点的最大变化率都求出后,我们可以根据自己设定的阈值,进行筛选,得到最终的边缘.或者是按照这个变化率绝对值的大小,按照比例绘制粗细不同,颜色深浅不同的边缘轮廓.

1-2.像素的梯度

具体的梯度公式和方向导数的推导证明请参考最后的“数学部分”,此处我们直接开始讨论像素的梯度计算.

也就是要求出像素的梯度,并且还要求出梯度的模,也就是该像素灰度的最大变化率.

梯度:

梯度的模:

 之所以要约等于x,y两个分量绝对值的和,是因为计算平方和,再计算开方是个不小的成本.

最后问题归结为计算x,y方向的偏导数.

1-3.思路总结

 1-4.像素的梯度

如果是连续的函数,那么通过xy的偏导数计算得到的梯度向量就是个准确的数值.但是现实情况是,在图像中灰度的变化并不是连续的函数,而是离散的. 为了让得到的灰度变化梯度更加准确,不仅要计算x,y方向的偏导数(方向导数)得到梯度,同时可以再选择两个正交的方向计算方向导数(参考数学部分g),得到梯度,这两个梯度求平均值,进而得到更准确的梯度.

图中每个格子代表一个像素点,上面的字母表示该像素点的灰度数值. e像素为中心,可粗略分成8个方向. 如果要更细致的划分方向,需要扩展邻近像素数量,计算成本将会大大提高.   值得关注的是梯度的相对大小,而不是绝对大小,所以我们这里也没有严格使用单位向量.

参考“数学部分”公式f-4,  

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值