现把D到O的大部分滤镜用vulkan的ComputeShader实现了,列举其中一些有点特殊的说明.

GaussianBlurPosition 指定区域高斯模糊

没有按照GPUImage里的方式实现,按照类似GaussianSelectiveBlur方式实现,一张高斯模糊图,一张原图,二图进行混合,这种实现方式更灵活(模糊半径等参数),并且并不会降低性能(单独的高斯模糊更容易优化).

SphereRefraction 环境映射

环境映射技术漫谈

和GlassSphere一样,主要就是球形坐标系与UV坐标系的转化,刚开始完成后,我测试效果,发现圈外在闪烁,后面发现没把圈外置0,其中withinSphere表示圈外圈内.

Halftone 半色调效果,类似新闻打印

这个类继承PixellateFilter(马赛克),顺便也把这个实现了,他们参数一样,实现主要是把一小快矩形范围的UV统一成一个,然后处理.

HighPass 高通滤波,检测图像像素变动

实现这个类,首先要实现LowPass,这个滤境有点特殊,需要保存上一桢的传入图像,然后比较当前桢与上一桢.

我设定运行图使用的有向无环图,中间可以根据需求自动排除不可用节点并自动链接下层,所以不能有回环线,从一层保存一桢然后再拿回来使用,这样构成回环,所以我定义VkSaveFrameLayer层为bInput = true,当作输入层,告诉外面不需要自动连接别层输入,在相应接口手动指定别的层需要保存的纹理.

最开始我直接调用vkCmdCopyImage,发现在Nsight显示占用0.3ms-0.7ms左右的时间,从逻辑上来说,应该不可能啊,这个copy应该比最简单的运算层占去的时间要更少才对,于是我测试了二种方案,对应参数bUserPipe,表示用不用管线,用管线控制到0.2ms内,用vkCmdCopyImage在0.3ms以上,以后找下资料看看是什么问题.

LowPass有二个输入,然后就是第一输入节点是上层,第二个输入节点是SaveFrameLayer,在LowPass运行前,SaveFrameLayer提供输入,在LowPass后(混合前后桢,可以去掉类似摩尔纹的东东),把结果又保存在SaveFrameLayer里.

HighPass就是比较与LowPass的差异,可用来显示变化大的像素.

相应源码,有兴趣可以自己查看VkLowPassLayer

Histogram 直方图

GPUImage通过回读到CPU然后计算,这种方式直接放弃,查看相应opencv cuda模块类似实现.

线程组定成256个,然后使用数值对应索引位置+1,结果就是索引上的数值表示对应值的个数.

有二种方式,保存到临时buffer,二是用原子集合(int/uint),这里因为int满足,使用原子集合.

保存到临时buffer,我在开始四通道时使用类似reduce2分二段,不用原子操作的方式,但是效果并不好,一是第一次把16*16块的方式转换成对应的一个个直方图,模块并没的缩小,导致第二块把这一个直方图通过for加在一起需要循环1920/16x1080/16(假设是1080P的图),这个会花费超过2ms,这种方式就pass掉,我直接使用原子操作导出四个图然后再结合都比这个快.

可以看到,在这之前,要先vkCmdClearColorImage结果,几乎不消费时间,我也是这样理解的,但是为什么vkCmdCopyImage会导致那么大的时间等待了?

时间差不多在0.2ms左右,不过随机的亮度图,亮度比较分散,后面使用只有0,1的二种图看看会不会影响这个时间.

一通道在0.18ms左右,四通道在0.52ms+0.01ms,比0.18*4快些.

直方图的显示可以使用VkAlphaShow2Layer显示,没有用GPUImage里的显示方式,其对应输出分别为256x1x(R32UI/RGBA32UI)纹理,自己用glsl显示各种需求应该更方便.要输出到CPU的话,直接接一个VkOutputLayer也方便.

iOSBlur 一种特定模糊实现

把原来的几个已经实现的层downSampling/saturation/gaussian blur/luminance range/upSampling组合一下输出效果就是.

Kuwahara 实现类似油画风格效果

kuwahara filter 实现

在GPUImage上最开始就说了,只适合静止图像,因为很耗性能.原理比较简单,查找当前像素周边四个方向区域方差最小的区域.

因其算法特点,卷积分离没有使用,只使用了局部共享显存优化,在PC 2070N卡1080P下,半径5需要3.3ms,半径10需要9.7ms.

测试手机Redmi 10X Pro 用半径3在720P下非常流畅,可以满足30fps运行.

PC平台Vulkan运算层时间记录里可以看到,3x3时使用局部共享显存并不一定会占优,但是只要核大于3x3,使用局部共享显存的方案就一定会提速,核越大提速越多.

Kuwahara3x3因为算法特性,需要4x4x4,与8x8相当,就算专门去掉重复的那几行,也要读取49个数据,相当于7x7,所以下面专门优化的Kuwahara3x3就没用了.

Laplacian 使用拉普拉斯算子查找边缘

比较常见,一个像素与一个特定3x3矩阵的结果,单独拿出来说,是因为在ubo中,直接使用mat3/mat4,在CPU中使用类似的的Mat3x3,Mat4x4对齐会有问题,并且我在Nsight查看到对应的UBO里放着正确的mat3对应数据,但是结果就是不对.最不容易出错的方法就是在ubo中全使用单个float+std140表示类似vec3/vec4/mat3/mat4结构,在CPU端就不需要特殊处理结构,和ubo一样顺序就行,这样最不容易出现CPU-GPU中的UBO对齐问题.

Lookup 颜色查找表

这个在前面Vulkan移植GpuImage(三)从A到C的滤镜已经说过,但是感觉由用户自己来接一个输入层不太方便,因此修改逻辑,内置一个输入层,提供loadLookUp方法,由用户提供三通道/四通道512x512x(3/4)的lookup图像数据就行.

下面的MissEtikate导入lookup_miss_etikate图像数据就行,本框架现没有读各种图像格式的模块与第三方库.

Median 中值滤波

中值滤波原理及其C++实现与CUDA优化

开始和Kuwahara一样,使用局部共享显存来优化,在结合上面文章里的直方图方式,但是结果并不好,详细情况可以看PC平台Vulkan运算层时间记录记录.

总的来说,优化了个寂寞,还是移植了GPUImage里的3x3的实现,虽然核大会导致排序也是指数增长,但是这次优化明显不成功,只能说是暂时可用大于3核的情况,后续找找更多的资料试试改进.

看了下相关opencv cuda里的median里的写法,在前面会声明一个图像元素*256的buffer?嗯,这个buffer是为了替换里面单个线程uint hist[256]?在CS里,一个线程声明大堆栈数据会导致性能问题吗?先暂停,opencv cuda这个算法写的太麻烦了,后面有时间研究.

MotionBlur 运动模糊

在没看GPUImage实现前,我还在想HighPass就有点运动模糊的味道,但是其在GPUImage实现里,就是简单的给定一个方向,然后由这个方向模糊,并没有前后桢的叠加比较,因其实现简单,所以也移植了.

MotionDetector 运动检测

这个倒是和HighPass很像,区别在于最后会聚合统计给CPU输出,这个确实有必要,所以在本MotionDetector实现中,集成一个VkOutputLayer,并转化输出数据与GPUImage类似,可以看到运动的大小统计.

class VkMotionDetectorLayer : public VkLayer, public MotionDetectorLayer {
AOCE_LAYER_QUERYINTERFACE(VkMotionDetectorLayer)
private:
std::unique_ptr<VkLowPassLayer> lowLayer = nullptr;
std::unique_ptr<VkReduceLayer> avageLayer = nullptr;
std::unique_ptr<VkOutputLayer> outLayer = nullptr; public:
VkMotionDetectorLayer();
virtual ~VkMotionDetectorLayer(); private:
void onImageProcessHandle(uint8_t* data, ImageFormat imageFormat,
int32_t outIndex); protected:
virtual void onUpdateParamet() override;
virtual void onInitGraph() override;
virtual void onInitNode() override;
}; VkMotionDetectorLayer::VkMotionDetectorLayer(/* args */) {
glslPath = "glsl/motionDetector.comp.spv";
inCount = 2; lowLayer = std::make_unique<VkLowPassLayer>();
avageLayer = std::make_unique<VkReduceLayer>(ReduceOperate::sum);
outLayer = std::make_unique<VkOutputLayer>(); paramet = 0.5f;
lowLayer->updateParamet(paramet);
outLayer->setImageProcessHandle(std::bind(
&VkMotionDetectorLayer::onImageProcessHandle, this, _1, _2, _3));
} void VkMotionDetectorLayer::onImageProcessHandle(uint8_t* data,
ImageFormat imageFormat,
int32_t outIndex) {
if (onMotionEvent) {
vec4 motion = {};
memcpy(&motion, data, sizeof(vec2));
onMotionEvent(motion);
}
} VkMotionDetectorLayer::~VkMotionDetectorLayer() {} void VkMotionDetectorLayer::onUpdateParamet() {
lowLayer->updateParamet(paramet);
} void VkMotionDetectorLayer::onInitGraph() {
VkLayer::onInitGraph();
pipeGraph->addNode(lowLayer->getLayer());
pipeGraph->addNode(avageLayer.get())->addNode(outLayer->getLayer());
} void VkMotionDetectorLayer::onInitNode() {
lowLayer->addLine(this, 0, 1);
this->addLine(avageLayer.get());
setStartNode(this, 0);
setStartNode(lowLayer.get());
}

顺便还通过CPU的输出,查到了一个reduce2.comp里divup误写导致的低级错误.

NobleCornerDetection Noble角点检测

这个GPUImage中,实现方式和HarrisCornerDetection几乎一样,就是角点的选择计算方式有点不同,会导致比HarrisCornerDetection多检测很多角点出来.

Opening 开运算,先侵蚀后膨胀

和Closing一样,由侵蚀与膨胀组合,专门提供一个类GroupLayer,本身不提供任何计算,只组合别的运算层.

中间没有移植的滤镜统计

  1. FASTCornerDetection,其GPUImage里并没有实现,只是写个声明.

  2. JFAVoronoi,看到其中需要CPU定循环多次GPU运行,其中UV与颜色对应相关代码暂时不理解,先放着,后期找更多资料确定移植方法.

  3. LanczosResampling,GPUImage的实现好像和其原理差别有点大,应该是特化实现,暂不移植.

  4. LineGenerator这个现在还没想到如何能在GPGPU中高效画多条线,普通的渲染管线方式倒是方便实现,后面查找资料确定移植方法.

  5. MosaicFilter没找到具体显示效果,看到显示效果应该就可以马上移植了.

  6. 直方图的显示,现框架实现的VkHistogramLayer里会输出分别为256x1x(R32UI/RGBA32UI)纹理,自己根据你的需求去写相应glsl显示更合适.

其中从D到O的处理,有一部分因为前面实现别的层时,有一些已经实现过,也不在本文里说明,现在GPUImager移植进度大约有60%,相应的效果可以在vulkanextratest,win端修改Win32.cpp,android修改Android.cpp查看对应平台效果,等所有效果移植完成后会写配套专门的UI界面查看.

Vulkan移植GpuImage(四)从D到O的滤镜的更多相关文章

  1. Vulkan移植GpuImage(三)从A到C的滤镜

    前面移植了几个比较复杂的效果后,算是确认了复杂滤镜不会对框架造成比较大的改动,开始从头移植,现已把A到C的所有滤镜用vulkan的ComputeShader实现了,讲一些其中实现的过程. Averag ...

  2. Vulkan移植GPUImage(五)从P到Z的滤镜

    现aoce_vulkan_extra把GPUImage里从P到Z的大部分滤镜用vulkan的ComputeShader实现了,也就是最后一部分的移植,整个过程相对前面来说比较简单,大部分我都是直接复制 ...

  3. Vulkan移植GPUImage的安卓Demo展示

    演示Android apk下载 需要Android 8以上. 先看效果图,大约一百多种滤镜,有超过一半的滤镜有参数设置,其参数调整界面使用反射自动生成与绑定. 如下每种选择一些进行展示. 视觉效果 图 ...

  4. Vulkan移植GpuImage(一)高斯模糊与自适应阈值

    自适应阈值效果图 demo 这几天抽空看了下GpuImage的filter,移植了高斯模糊与自适应阈值的vulkan compute shader实现,一个是基本的图像处理,一个是组合基础图像处理聚合 ...

  5. Vulkan移植GpuImage(二)Harris角点检测与导向滤波

    Harris角点检测 UI还是用的上次扣像的,只有前后置可以用,别的没有效果,只看实现就好. 相应源码 在实现之前,我先重新整理编译glsl的生成工具,如Harris角点检测中间计算过程需要针对rgb ...

  6. u-boot移植(四)---修改前工作:代码流程分析3---代码重定位

    一.重定位 1.以前版本的重定位 2.新版本 我们的程序不只涉及一个变量和函数,我们若想访问程序里面的地址,则必须使用SDRAM处的新地址,即我们的程序里面的变量和函数必须修改地址.我们要修改地址,则 ...

  7. 基于tiny4412的Linux内核移植 -- DM9621NP网卡驱动移植(四)

    作者信息 作者: 彭东林 邮箱:pengdonglin137@163.com QQ:405728433 平台简介 开发板:tiny4412ADK + S700 + 4GB Flash 要移植的内核版本 ...

  8. U-Boot在FL2440上移植(四)----支持网卡DM9000和烧写yaffs文件系统

    <一>支持网卡芯片DM9000 在driver下,有网卡驱动DM9000x.c 和 DM9000x.h DM9000接在BANK4,位宽16 在include/configs/TX2440 ...

  9. 从0移植uboot (四) _点亮调试LED

    这一节主要讨论1个问题:点灯.点灯是实际开发中,特别是裸板开发中常见的调试手段,相当于主机开发中漫天飞舞的printf/printk.为了追踪程序的现场执行情况,很多时候我们都使用点一个灯的方法来进行 ...

随机推荐

  1. wxWidgets源码分析(4) - 消息处理过程

    目录 消息处理过程 消息如何到达wxWidgets Win32消息与wxWidgets消息的转换 菜单消息处理 消息处理链(基于wxEvtHandler) 消息处理链(基于wxWindow) 总结 消 ...

  2. JDK的下载、安装与配置

    一.JDK的下载 1.JDK下载地址:https://www.oracle.com/cn/java/technologies/javase-downloads.html 2.登录Oralce官网:ht ...

  3. 剑指 Offer 33. 二叉搜索树的后序遍历序列 + 根据二叉树的后序遍历序列判断对应的二叉树是否存在

    剑指 Offer 33. 二叉搜索树的后序遍历序列 Offer_33 题目详情 题解分析 本题需要注意的是,这是基于一颗二叉排序树的题目,根据排序二叉树的定义,中序遍历序列就是数据从小到大的排序序列. ...

  4. 剑指 Offer 25. 合并两个排序的链表

    剑指 Offer 25. 合并两个排序的链表 Offer 25 该问题的原型就是多项式的合并. 实现较简单,没有特殊需要注意的问题. package com.walegarrett.offer; /* ...

  5. POJ-2516(最小费用最大流+MCMF算法)

    Minimum Cost POJ-2516 题意就是有n个商家,有m个供货商,然后有k种商品,题目求的是满足商家的最小花费供货方式. 对于每个种类的商品k,建立一个超级源点和一个超级汇点.每个商家和源 ...

  6. MVC模式从Controller返回内容协商格式(Json或者Xml)

    WebAPI默认的返回格式Json,但是MVC是View,如果在MVC的控制器中,想要返回Json格式该怎么操作呢 在MVC的控制器中返回json数据只需要然会JsonResult而不是ActionR ...

  7. 【MaixPy3文档】写好 Python 代码!

    本文是给有一点 Python 基础但还想进一步深入的同学,有经验的开发者建议跳过. 前言 上文讲述了如何认识开源项目和一些编程方法的介绍,这节主要来说说 Python 代码怎么写的一些演化过程和可以如 ...

  8. jdk8的安装与环境搭建

    jdk8的安装与环境搭建 jdk8下载网址:https://www.oracle.com/cn/java/technologies/javase/javase-jdk8-downloads.html ...

  9. 解决 Ant Design Modal 中的 Select 选项框不能显示的问题

    antd 的 select 在 modal 里不能显示候选框 代码示例 <a-modal> <a-select> <!-- options --> </a-s ...

  10. springboot注解之@Import @Conditional @ImportResource @ConfigurationProperties @EnableConfigurationProperties

    1.包结构 2.主程序类 1 @SpringBootApplication(scanBasePackages={"com.atguigu"}) 2 public class Mai ...