去马赛克示例介绍
去马赛克是一种图像处理技术,用于将Bayer格式的图像数据转换为RGB格式的图像数据。去马赛克的原理是通过对Bayer格式的图像数据进行插值处理,生成RGB格式的图像数据,以便于后续的图像处理。 为了更好的展示如何使用DSP实现去马赛克的功能,本章从算法原理出发,展示了详细的去马赛克算法实现流程。
原理介绍
Bayer格式的图像数据是一种单通道的图像数据,其中每个像素点只包含一种颜色的信息, 常见的Bayer格式有RGGB、BGGR、GRBG、GBRG等。而RGB格式的图像数据是一种三通道的图像数据,其中每个像素点包含红、绿、蓝三种颜色的信息。 根据插值算法的不同,去马赛克算法可以分为最近邻插值、双线性插值、双三次插值等,在本示例中采用了一种利用色差恒定原理的自定义插值方式。 具体差值原理请参考 Demosaicing 。
DSP 实现流程
DSP的实现主要围绕着以下几点进行优化:
- 通过使用tile_manager框架,将数据分块处理,并将分块数据的搬运和计算构造pingpong流水线。
- 通过SIMD方法实现green_3x3、green_5x5插值方法。
- 使用数据分类等方法,将相同数据的计算过程进行合并,充分使用宽位寄存器的批量处理能力。
tile manager框架的使用
tile manager是cadence提供的一种算子开发框架,通过将整体数据分块处理,将数据的搬运和计算构造pingpong流水线,提高数据处理效率。 其中frame是框架中对完整输入或者输出的描述,tile是框架中对frame进行分块的描述,是框架中的计算处理单元。 算子开发中通常按照如下步骤使用:
- 创建算子参数结构体
- 实现tile分块函数,将frame数据按照顺序进行分块处理
- 实现每个tile的计算函数,完成单个tile的处理
- 通过tile manager相关接口,构造pingpong流水线,实现完整算子功能
在Demosaicing算子中,Frame结构体中包含一个输入frame和三个输出frame,Tile结构体种包含一个输入tile和三个输出tile。 这样就满足了在每个输入tile中都可以计算出对应的三个RGB tile的目的。 具体参数结构体实现如下:
下一步要实现的是tile的分块函数,按照一定逻辑将frame数据分成逐个处理的块。在Demosaicing算子中,输入输出的每个像素的位置映射是一对一的,位置也不会发生变化。 例如,Raw图片中的G21点,在RGB图片中的每个通道中坐标也是(2,1)。因此,输入tile的坐标和设置和输出一致。 在Demosaicing计算中,Raw图片的边界值计算需要使用的数据超出了原图大小,因此需要填充边界值。 在上文描述的插值算法中,最多使用的是5x5的范围,因此,输入的边界值大小设置为2,输出的边界值大小设置为0。
具体实现如下:
第三步要实现的是每个tile的计算函数,是算子的核心处理逻辑,对应源码中的demosaic_kernel函数。
最后,调用框架相关接口,实现多个tile的流水线处理,对应源码中的demosaic_rggb_comp函数。 代码核心如下:
实现插值算法green_3x3、green_5x5
在上文对插值算法的分析中,可以提取出核心的插值逻辑 green_3x3 和 green_5x5。通过SIMD优化,实现代码如下:
其中,函数的输入参数为计算插值所需要的不同位置的数组,每个元素计算所需的值根据数组下标一一对应。
主体计算逻辑合并和SIMD优化
根据分析,在计算插值过程中,可以将奇数和偶数位置的数据分开处理,比如偶数行元素为RG,可以通过奇偶性将R和G分开进行计算,最后再将计算结果合并。 在插值计算中,每个位置的计算最多涉及到周围5x5的内核大小,因此定义5x6的混合内核如下:
算子的处理按照DSP中int16的最大处理长度进行,因此第一层循环按照宽度,步长为1024/16 = 64,第二层循环按照高度进行,步长为1。 可以看出,在内层的处理逻辑中,混合内核的前4行数据可以复用,可以节省重复的计算逻辑,减少耗时。 流程大致如下:
- 读取数据,并按照奇偶位置将数据进行拆分。
- 将拆分后的数据进行判断,执行不同的去马赛克逻辑。
- 计算结果按照奇偶位置进行合并,并保存到输出数据中。
- 将插值内核中的数据进行更新,充分利用本次计算结果,进行下一轮循环。
第一步,读取数据,并按照奇偶位置将数据进行拆分。DSP实现中将读取数据并按照奇偶分开的过程封装为了LOAD_AND_SELECT_ODD_EVEN_WITH_OFFSET宏函数, 该函数的功能为读取最多64*3=192个数据,并按照奇偶位置拆分,将拆分后的数据按照混合内核的位置进行选择,保存到对应的寄存器中。 其定义及使用代码如下:
第二步,将拆分后的数据进行判断,执行不同的去马赛克逻辑。在计算插值过程中,相同颜色的计算逻辑是一致的,因此将相同颜色的计算逻辑合并。 在具体实现中,行的奇偶判断取y起始坐标加y偏移坐标的最后一位,即(y+ys)%2。列的奇偶判断取x偏移的最后一位,即(x+xs)%2。因为列的处理步长一定是偶数, 所以x偏移不会影响奇偶性。具体实现代码如下:
第三步,将计算结果按照奇偶位置进行合并,并保存到输出数据中。主要实现方法为通过双选操作,将数据合并。 还需要注意的是,在处理结果之前,要将结果限制到合法的输出范围。具体实现代码如下:
第四步,将插值内核中的数据进行更新,充分利用本次计算结果,进行下一轮循环。在内层循环中,很多参数是可以复用的, 5x6的混合内核每次循环向下移动一行,因此只需要更新最后一行的数据,寄存器数组、green_3x3的临时结果都可以使用旧值。具体实现代码如下:
至此,整个Demosaicing算法的实现流程已经完成。此示例仅供参考,在实际应用场景中,可以根据此示例进行修改和优化,或许可以进一步提升算子效果和性能。
