第一篇工作SLASH的幕后故事
本文主要介绍一下九月刚中的一篇NDSS的文章的幕后故事和个人感想。想了一下还是不让AI来污染我的博客了,对于博客这一块咱还是坚持手敲保持活人感吧。但是感觉现在用AI太多,导致自己脑子里的语料库已经被AI污染了…未来AI一定会把人类的自然语言的分布给整体带偏的。
SLASH: Scratch-induced Lens Adversarial Streak Hijacking
一晃已经博三了,总算是把第一个工作做完了给发出去了,也算是结算第一个里程碑了,就结果来说,起码还是中了个安全四大,虽然慢了点,但是结果还是不错的,中了就好。
说实话第一个工作的时间线拖得非常长,前后做了一年半两年才做完,这的确是我和导师都没想到的。通常来说,正常进度下一般是一年出至少一篇工作,别管中不中,但一般来说你得先一年给一篇工作结题,然后再到处去尝试投稿,从顶会往下面投,全部投一圈,看哪儿能中。之所以拖这么久,除了一开始探索阶段走了很多弯路以外,课题本身也属于是强调“在真实世界中部署的adversarial attack”的,这个属性就注定了这是一个实验极其麻烦、不能通过在虚拟环境中开多个实例来并行化的事情…“人”本身也是省不了的,人没在采数据,就没有新的数据产生,甚至我们采集数据的时候还得看天吃饭,天气不好还采不了,太折磨了。
我不准备花大篇幅讲paper本身,因为paper都是公开的,你可以直接去项目主页看,我更想讲的是一些paper成型的幕后的故事之类的,毕竟是个人博客,咱别搞得那么学术。
我们的这篇工作用一句话概括就是:如何在相机镜头上划一道/多道划痕,来导致其背后连接的系统的感知层的模型无法正确地推断物体的深度。记住这个一句话概括,因为接下来要等很久才又回到这句话,大部分都是在讲我是如何绕弯子的/呲牙。

这个课题是一开始来的时候导师看我们都没啥想法,就直接塞给我的,毕竟我之前做adversarial attack之类的比较多,然后我对渲染、图形学之类的也懂点皮毛,那么我也就欣然接受了呗。一开始的课题并非像现在这么明确,一开始我从导师那里接收到的prompt就是“我们能不能通过在镜头上做点什么手脚来搞点adversarial attack出来”,核心理由是导师觉得physical adversarial attack是各大会议在AI/ML安全这一块很喜欢收的方向,所以导师觉得做这个方向能中的概率应该挺大的(现在回头看,这个判断的确是对的,那么好中的代价是什么呢?笑う)。
一开始想象的是,咱能不能搞个凹凸不平但平滑连续的玻璃片,放在镜头前面来造成adversarial attack(比如让YOLO之类的目标检测或者让ResNet之类的分类模型预测错误),那么等于说attack surface就是这个凹凸不平的玻璃片的一个2D的高度场(可以看见一开始做的东西和最后得到的东西根本不是同一个东西)。于是在导师的推荐下,我就开始用mitsuba做了,这是一个differentiable的path tracing的引擎,当时导师主要是觉得说这玩意儿自带对渲染结果的梯度之类的,应该会对优化有帮助。但我当时做了个很傻逼的事儿就是我直接用了大多数渲染引擎默认会使用的针孔相机(没办法,它真是默认),而我们要做的东西又刚好是放在镜头前面的一块玻璃,这种失焦的情况下的光学现象针孔相机和透镜相机是完全不能等价的,导致浪费了好些时间去优化和设计一个完全不可能在真实相机下有用的东西。
后来反应过来、发现这个事情之后,立刻换成了薄透镜相机,虽然薄透镜相机相比起现在动辄好几个或者十几个镜片的相机来说建模有点太理想化了,但是好在即使是多透镜相机也是能找到一个等效的薄透镜位置/等效的焦距的,因此光学模型上起码还是比针孔相机的小孔成像要正确多了。但问题也又来了,经常拍照的朋友都知道,如果相机镜头前面放点啥距离很近的东西,那么出来的基本上就是一个非常非常糊的一坨,如果放一个非常凹凸不平的玻璃,那么会直接搞乱原本的光路,导致成像本身都出现很大的问题。更重要的是path tracing对失焦物体渲染的效率问题,以及直接在距离镜头很近的地方全部糊上一片玻璃的这个做法本身,当物体距离镜头非常近的时候,path tracing渲染的效率是极低的,默认的针对path tracing的各种加速trick根本不是为我们这种非常奇怪的场景设计的,虽然也有少量paper研究过如何加速path tracing对于失焦物体的渲染之类的,但是对我们来说,要去深入改造一个differentiable path tracing的引擎的工作量还是太大了,臣妾做不到。
于是吧,我们换了些平台,说能不能找一些比如Zemax之类的镜头用的光学仿真软件,我们想象的是它本身应该是足够精准的,而且还自带色散之类的path tracing里面很难做到的东西,但很显然的问题就是拿不到梯度,只能做zero order optimization,而且Zemax我捣鼓了半天感觉也很难用,没给API接口,有很多东西还是黑盒的,找厂家要了一个镜头的Zemax的文件,这个文件居然只能看到几条示例的光线的方向,你甚至都看不到里面的光路是怎样的,甚至还不能把它当成一个黑盒函数用,喂给它任意输入之类的…于是Zemax之类的专门做镜头调校的软件也被排除了。
后来去恶补了一些光学的知识后(显然这些东西后来可以说基本上没怎么用上),知道了我们目前的思路其实就是想要优化一个PSF(Point spread function,光学系统对点光源的响应),使得在这个PSF下拍出来的东西能够造成adversarial attack。也试了例如通过优化Zernike多项式(可以理解成描述镜片起伏的一个函数之类的)来控制镜头的PSF,但不管怎么优化,PSF变化引入的这种轻微的扰动本身太小了,作为adversarial attack的扰动根本不够看,等于说是在图像空间中,变化频率不够高,振幅也不够大,根本打不动模型,然后要制造一个有特定起伏的光学级别的玻璃的话也很困难,以我们的条件也根本不可能造得出来,因此这个“搞个凹凸不平但平滑连续的玻璃片来进行adversarial attack”的方案后来就基本上被完全放弃了。
这属于是完全的低谷期了,等于说之前设想的思路完全是错的,但不得不说的是,捣鼓mitsuba之类的path tracing的代码、自己写点custom的BRDF、BTDF函数之类的还是很有意思的,太享受了,这块就属于是自己纯瘾大了。
后来我们去参考了一些相机的艺术化/风格化的滤镜设计(比如PrismLensFX)之后,我们发现了一个之前没发现的华点,就是我们似乎在之前的attack中从来没考虑过极亮光源,之前我们考虑的场景总是完全漫反射的场景,但其实也有很多场景下是有很多specular highlight或者明亮点光源的,例如夜间的路灯灯泡、光滑表面的局部反光的高光之类的,经常拍照的朋友都知道,当你把特定形状(例如五角星)的洞放在镜头前,然后去拍摄夜景,在失焦的情况下,就会看到画面中的光源的光晕都变成了五角星,这其实就是通过一个遮罩让镜头的PSF改变了,这个可优化的维度看起来就很诱人了,等于说我们可以优化的是一个2D的遮罩的形状,那么可优化参数的维度其实是比较够的,但是核心的问题也很明显,这玩意儿只有在失焦的情况下才会出现,但实际的相机在工作的时候并不会故意保持失焦状态,因此这个方案显然也在这里卡住了。
最后我们终于是想起了还有星光镜这么个东西,经常摄影的朋友应该都知道,星光镜其实基本上可以理解成是一个上面有很多沟槽/划痕的平板镜片,装上去之后,在拍摄明亮点光源的时候,就能出一条或多条亮线。这个方案唯一的问题就是可优化的维度很低,虽然这条亮线本身的亮度通常是足够的,但总共就只有一根线给我调整角度、位置、长度之类的,因此攻击的能力/强度会比较一般,但好在它还是能打得动一些depth相关的感知层,比如一些深度估计模型和一些3D的物体检测模型,因此好歹还是做了一批实验然后终于给它收尾结题了。至此,我们终于兜兜转转一大圈,做了很多无用功之后,把这个和星光镜一个原理、在镜头上划几道划痕的新attack给它做完了。

这个攻击本身还是比较有意思的,在相机镜头前面做攻击本身就是一个很难做的事情,同类型攻击的论文数量就很少,因此能再给这种攻击方式添加一种新的攻击手段的确会让人觉得很有趣,大多数reviewer估计都没太见过,因此感觉还是比较有novelty的。整个工作虽然耗时比较久,但是只要能攒下一些之后还能继续复用的经验和数据,那么就是值得的,之后如果继续做类似的工作的话,速度应该就快很多了,毕竟该踩的坑都踩完了,现在的确也在准备快速做一篇跟进的新的工作出来,新的一篇跟进工作会更有趣而且更强力的捏。