Anime4K算法
写在前面:Anime4K算法已经出来两年了,在去年经历一次大更新后,现在的Anime4K-V3已经和原来有了很大不同。一个是V3版本里的算法已经结合了CNN(事实上在很早之前作者就说要结合机器学习算法,在性能和时间上寻求一个tradeoff),不过只给出了卷积权重没给训练流程。另一个是V3版本目前是只有用GLSL写的(说穿了就是我读不懂),而且也不像之前,连个论文的preprint也没有(可能是实在吵不动懒得发了?)。所以接下来讲的是最原始版本的Anime4K,这个版本也就是作者所说没有任何机器学习/深度学习方法的版本,对应的代码是github里V1.0里的java代码。
github地址:https://github.com/bloc97/Anime4K/tree/v1.0-RC
作者对二次元图像的假设认为,高质量的二次元图像有大量大面积的平坦区域(一整个区域的颜色都一样或者变化很小),这一点不同于三次元图像,因此这是一个针对于二次元图像的超分算法,不能拿来用在三次元上。
首先先介绍一下论文的理念。作者通过对比观察同一分辨率下的模糊和清晰图像,认为清晰的图像具有较细(指在图像中占据的区域小)的边缘(其实在这里说的是梯度),而模糊图像的边缘较粗。下图是一个具体的展示。
由于论文是预印版,没有详细的描述算法的实现过程,因此要从代码中进行解读。参考其代码,可以发现整个算法的核心有两个步骤:deblur和grad_refine。
首先,算法先要从原始图像中计算一张亮度图用于后面的处理。不同于普通的Y通道,这里的亮度图是按照 ( b + 3 ∗ g + 2 ∗ r ) / 6 (b+3*g+2*r)/6 (b+3∗g+2∗r)/6计算出来的,bgr分别是原始图像中的三通道。
condition
接着要做deblur操作,而deblur的操作要做一组很有趣的判断,而且这组判断在之后的grad_refine里也要用到。具体看下图,共有八种,可以看做是第一种不停旋转得到其他七种,中心就是当前要计算处像素的位置。
每次判断,都是判断绿色中最小的数是否比红色中最大的数要大,如果绿色中最小的数大就是true,反之就是true(后面的grad_refine也是这组判断)。
deblur
好了,知道判断是什么了,就可以说明deblur的步骤了。对图像中任意一点(x,y),在它的亮度图中进行上述8次判断,如果某次判断中为false,那么按下面计算:
m e a n b = ( r e d 1 b + r e d 2 b + r e d 3 b ) / 3 mean_b=(red_{1b}+red_{2b}+red_{3b})/3 meanb=(red1b+red2b+red3b)/3
m e a n g = ( r e d 1 g + r e d 2 g + r e d 3 g ) / 3 mean_g=(red_{1g}+red_{2g}+red_{3g})/3 meang=(red1g+red2g+red3g)/3
m e a n r = ( r e d 1 r + r e d 2 r + r e d 3 r ) / 3 mean_r=(red_{1r}+red_{2r}+red_{3r})/3 meanr=(red1r+red2r+