美文网首页GPUImageGPUImageiOS Developer
GPUImage详细解析(十二)Sobel边界检测

GPUImage详细解析(十二)Sobel边界检测

作者: 落影loyinglin | 来源:发表于2017-02-12 22:36 被阅读3068次

前言

卷积运算是一个看似复杂的概念,今天来揭开这个神秘的面纱。
卷积矩阵:卷积矩阵是一个由权重数据组成的矩阵,中心像素周围像素的亮度乘以这些权重然后再相加就能得到中心像素的转化后数值。
本文对GPUImage中的Sobel边界检测滤镜进行解析。

效果

正文

GPUImage的Sobel边界检测滤镜是
GPUImageSobelEdgeDetectionFilter
GPUImageSobelEdgeDetectionFilter继承GPUImageTwoPassFilter,由两个滤镜组成,分别是黑白滤镜和边界检测滤镜。首先是把输入的图像变成亮度图,再由边界检测的滤镜转换成边界图。GPUImageSobelEdgeDetectionFilter对外的属性有三个,分别是:
texelWidth:边界检测时八方向的像素值宽度,默认是1/size.width;(1像素的宽度)
texelHeight:边界检测时八方向的像素值高度,默认是1/size.height;(1像素的高度)
edgeStrength:边界检测后,对边界的亮度增强程度,默认是1.0;(不变)
3x3矩阵中,纹理的距离宽度和高度;

边界检测的原理:一个像素为边界的表现是左右、上下的颜色差异很大,那么通过特定的卷积矩阵来运算,快速得到左右和上下方向的差异值之后,就可以通过这个值的大小来确定边界;
Sobel边界检测的卷积矩阵如下:
水平的卷积矩阵:

-1, 0, +1
-2, 0, +2
-1, 0, +1

垂直的卷积矩阵:

−1, −2, −1
 0,  0,  0
+1, +2, +1

如果左右的颜色差异值很小/大,那么通过水平卷积矩阵得到的值就会很小/大;
如果上下的颜色差异值很小/大,那么通过垂直卷积矩阵得到的值就会很小/大;
于是通过两个卷积矩阵分别得到水平差异值h和垂直差异值v后,再用sqrt(h2+v2)就可以得到边界值。

绘制的流程

  • 1、摄像机采集图像,得到YUV颜色空间的图像;
  • 2、把YUV的图像分成亮度纹理和色度纹理,并用YUV到RGBA的转 换矩阵,把两个纹理合成RGBA的图像;
  • 3、根据RGB不同的权值,把RGB颜色空间的图像,转换为亮度图;
  • 4、对每一个像素,根据八方向的像素值,用水平卷积矩阵算出水平方向的差异值h;用垂直卷积矩阵算出垂直方向的差异值v;根据sqrt(h2+v2)求出明亮程度,得到边界图;
  • 5、调整边界图的大小,显示到屏幕上。
整个流程用图来表示

流程图中的Texture#10,表示的是纹理对象10;绑定在纹理单元5是通过GPU Frame Capture查看。如下图,我们可以看到纹理单元2、3、4、5中分别绑定着纹理对象3、4、9、10,并且当前渲染的目标是纹理对象3。


遇到的问题

1、GPU Frame Debugger 无法正常工作

这个也是别人遇到过的问题点击http://www.openradar.me/28262556 可以查看。

2、无法消除的warning
System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles Reading from public effective user settings

这两个问题,其实是同一个问题:GPU Frame Capture在默认情况下会调用Metal的API,在正常的设备调试,会出现以下两行代码

Metal GPU Frame Capture Enabled
Metal API Validation Enabled

在调试demo过程中,我用的是Xcode8.1 + iOS 10.2.1;
iOS的版本高于Xcode版本
解决方案:升级Xcode或者换用低版本的iOS系统。

总结

在处理每个像素时,根据八方向求出边界值的过程与像素处理顺序无关;
这个处理的过程可以用片段着色器进行并行计算,极大地提高处理效率。

本身摄像头得到的YUV颜色空间里面就包括了亮度图,但是在本文的demo中却是经历了YUV到RGBA的转换,再由RGBA到亮度图的转换,这里是一个可优化的地方。

代码不复杂,见github

引用:《objc期刊》

相关文章

网友评论

  • 不辣先生:大佬,类似美颜相机中的那种给人像添加动态效果,比如兔子耳朵,胡子之类的,用GPUImage 可以实现吗?还是说用OpenGLes?对这块完全陌生,请指导:pray:
    不辣先生:那种动画特效的,可以给个思路吗?大佬
    落影loyinglin:@不辣先生 识别用其他 渲染用gpuimage
  • 郭_小白:你好,我在真机测试地图的时候,打印这两句话,Metal GPU Frame Capture Enabled
    Metal API Validation Enabled,然后界面卡死了。机型是iPhone5,10.3系统。用6s,6sp都不会卡死。iPhone5模拟机上测试不打印这两句话,没有出现卡死。所以想找到这两句话的根源,然后看看究竟是什么原因导致的卡死。想问下你这是什么情况下会打印的,怎么不启用这个渲染
  • Callmewenxi:大哥,为什么第二个demo以后的都跑不起来,报错,是不是要设置什么路径啊
    落影loyinglin:@iOS小小白 整个项目拉下来,公用了GPUImage的库
  • hush_2fee:你好,请教一个问题,我用GPUImage处理视频,当我添加了美颜滤镜和一个色调滤镜之后,拍摄的时候就比较卡顿,处理完的视频也只有15帧左右,这个有什么好的解决方法吗
  • shineDeveloper:你好,你写的文章都是看的是哪些资料?有没有推荐的书籍?
    落影loyinglin:@hush_2fee 如果6以上设备,不至于性能这么差。你查查是哪个地方的调用消耗太多的资源
    hush_2fee:你好,请教一个问题,我用GPUImage处理视频,当我添加了美颜滤镜和一个色调滤镜之后,拍摄的时候就比较卡顿,处理完的视频也只有15帧左右,这个有什么好的解决方法吗
    落影loyinglin:@细雨999 GPUImage看源码就行。其他的 如果有资料 会备注上去

本文标题:GPUImage详细解析(十二)Sobel边界检测

本文链接:https://www.haomeiwen.com/subject/ptlnittx.html