系列篇|结构光——格雷码解码方法

做者:书涵
Date:2020-03-16
来源:系列篇|结构光——格雷码解码方法
格雷码是一种特殊的二进制码,在结构光三维视觉中,经常被用于编码。比起咱们常见的二进制码,格雷码具备相邻数字的编码只有一位不一样的优势,这个优势对于解码而言十分重要,能够减小光解码的错误率。下面咱们能够看下如何对结构光用格雷码编码,并如何对编码的结构光进行解码
以5位格雷码为例,5位格雷码能够对32个像素位置进行编码,由以前的文章能够知道,咱们在计算结构光三维重建时,只须要对结构光图片的一个方向编码,以常见的列格雷码为例,如图所示是5位列格雷码编码图片集。
图中咱们对每一个像素点进行了格雷码编码,每一张图片都表明了格雷码的某一位,以图片第1列为例,其格雷码编码为00001,则前4张图片中第一列的的格雷码编码的条纹都是黑色,表明0,而最后一张图片第一列的格雷码编码是白色,表明1.
格雷码的解码很简单,只要把投影的格雷码结构光再还原回十进制数字,咱们就能知道相机中的像素点(uc,vc)对应的是投影图片的哪一列(up)了。想要获得一个好的三维重建结果,主要是对相机捕捉到的结构光进行准确的二值化操做,使得相机图片中每一个像素点都可以正确解码。
常见的二值化操做有不少,最简单的是设一个全局灰度阈值,对灰度值高于阈值的像素点置1,对灰度值低于阈值的像素点置0。 或者利用局部自适应阈值对图片进行二值化操做等·。常见的利用每一个像素点周边灰度信息的二值化操做,每每不可以知足格雷码结构光解码的二值化需求。由于使用结构光的环境每每是未知且复杂的。好比一样的结构光光强照在黑色物体表面的亮度比照射在白色物体表面的亮度要低。这意味着一样的光条纹在不一样物体上获取的灰度值不一样。因为不能提早预知环境中的物体表面信息,仅仅靠简单的利用像素点及其周周围灰度值的分布得出该像素点当前是来自结构光的亮条纹仍是暗条纹是及其不许确的。
虽然因为环境光,以及物体表面材质的缘由,一幅图像中像素的亮度(灰度值)一般是不均匀的,没法直接利用一张图片呈现的灰度信息对结构光解码,可是咱们能够利用结构光系列图片来帮助获取像素点当前是亮条纹仍是暗条纹的信息。以上图的格雷码编码为例,一个5位的格雷码编码须要投影5张结构光图片,假设有一个编码为 11011的格雷码条纹打在物体表面上,,在连续投影的5张格雷码图片中,物体表面被编码照射的位置既经历过暗条纹(编码为0)又经历过亮条纹(编码为1)。不过因为每张格雷码编码图片的光源编码不一样,并且结构光光源在物体表面上造成的漫反射不一样,当结构光编码图片不同时,即便是一样经历亮条纹照射,该位置的亮度(灰度值)也是不一样的。总的来讲,对于同一个位置,能够近似认为其被亮条纹照射到的亮度老是高于其被暗条纹照射到的亮度。那么对于一个像素点在一张图片中的二值化能够用以下方法。
首先找到像素点在系列格雷码图片中最大的灰度值,记为Imax,并找到该像素点在系列格雷码图片中最小的灰度值,记为Imin。对于每张图片,咱们能够这样计算,
In = (I-Imin)/(Imax-Imin)
其中I是该像素点在当前图片下的亮度,In能够看作是被归一化(normalize)后的灰度值,显然In的取值范围是[0,1]的。由上述公式能够看出,若是该像素点当前经历的是暗条纹,其值会接近最小的灰度值,In接近0,反之,In会接近1, 因而咱们能够设计一个阈值,好比0.5,即当In大于0.5时,咱们认为其值是偏亮的,此时像素经历的是亮条纹编码,反之,若是In小于0.5时,该像素此时经历的是暗条纹编码。值得注意的是,这个方法对于编码全为0的点,或者编码全为1的点,会有影响,由于编码全0的点和编码全1的点不会同时经历明暗变化。解决方法是避开这个编码,或者额外投图片让全部编码位置都能经历全0或者全1的过程。
上述方法的前提是近似认为被亮条纹照射到的亮度老是高于该位置被暗条纹照射到的亮度。实际上这个假设成立的前提是物体间没有漫反射,以及投影投射的光之间不会互相干扰。在一些特殊的位置,是有可能物体在经历亮条纹时其亮度值比其经历暗条纹时要暗。由于每张格雷码图片整体的光分布是不同的,如上图的第一张和最后一张,第一张光主要分布在右边半边,而最后一张条纹光很细,是明暗相间的。不同的格雷码图片的光强分布,会形成物体间漫反射的光强不同,致使其经历暗条纹时周围物体间漫反射到的光远大于结构光光源发出来的光。实际上这是有可能的,好比该像素点处于某个物体对的阴影部分,通常状况下这样的点是没有光变化的,由于结构光自己没法直射到该位置,可是由于其周边物体漫反射的光有可能致使这个位置的光强发生剧烈变化。出现该位置经历暗条纹时光强比经历亮条纹时还要强。为了解决这类特殊的点,论文[2] 给出其思路以下:
如图所示,咱们能够对每幅格雷码编码的条纹作一个逆向图,把原来编码条纹中的1的位置变为0,0的位置成1。这样咱们把每一幅编码图片变成了一对编码图. 咱们能够经过比较一对编码图中每一个像素的灰度差值来判断其值为0仍是为1。这个很容易理解,由于若是编码是亮条纹,则其逆向编码是暗条纹,则图片上编码是亮条纹的时候对应的点比编码是暗条纹(逆向)的时候对应的像素点更亮,即灰度值更高。反之亦然, 这样就能够简单地对相机图片上的结构光条纹解码了。
这个思路很简单,对大部分相机图片上的点,这样的解码效果就足够好了。可是仍然不能解决上述提到的问题。对于部分点,其经历暗条纹时仍旧可能比经历亮条纹时灰度值要更高。因而论文【2】在上述思路上,再增长了一部分想法,若是咱们能求出当前灰度值中可能的来自结构光直接光源的成分的比例,就能够帮助咱们辨别出该点是否经历暗条纹或者亮条纹。具体计算规则以下:
其中p指像素坐标,Lp+ 是像素在格雷码系列图中灰度最大值,Lp-是像素在格雷码系列图中灰度最小值。Ld能够看做是该像素点来自直接光源的灰度值,Lg能够看做来自其余光源(物体间漫反射和环境光)等的光源的灰度值。对于大部分状况,显然来自投影光的光强较强,Ld>Lg。可是对于部分点Ld<Lg, 好比处于物体阴影处的点,又好比处于周围反光物体较多点(来自周围反光太强了)。这部分点就是咱们要解决的点,经过下面的规则,能够很好的解决点的二值化问题:
对每一个像素点p和其灰度值I,有以下二值化规则 其中m是一个比较小的常数阈值,I_inv是条纹结构光的逆向图。
  • I<m 该点的二值化认为是不肯定点
  • Ld>Lg 且知足 I>I_inv 该点二值化为1
  • Ld>Lg 且知足I <I_inv 该点二值化为0
  • I<Ld 且知足I_inv>Lg 该点二值化为0
  • I>Lg 且知足I_inv<Ld 该点二值化为1
不符合以上全部条件的点为不肯定点
有了以上的二值化方法,格雷码的编码和解码都不是什么太大的问题,解码后能够根据笔者以前文章提供的三维数据计算方法获得较为准确的物体三维信息。
在文章的最后,笔者想讨论下为何格雷码编码比通常的二进制编码要好。咱们知道格雷码最大的优势是十进制相邻数字编码只相差一位。那为何这样就比普通二进制编码好呢?咱们知道,解码最容易出错的点,每每是黑白相间的边界点,相机拍摄到的黑白相间的边界点每每是一个过渡灰度,很容易致使解码错误,因此相邻的数字间位数差异越多,其黑白相间的变化越多,天然出错的几率也更大。对于这一点,其实有一个图片很直观感觉到,若是咱们对每一个像素进行格雷码编码,那么不管多少位编码,在其编码的最后一张图片上,条纹一般是很是细的,若是是普通二进制编码,其最后一张细条纹图片是每一个像素之间编码都不同,对一幅图片从左到右呈现010101…的变化,而若是用格雷码编码则会呈现0110011…的变化,明显格雷码编码其投影条纹更粗,更不容易解码出错。
本文解码方法参考论文:
[1] High-accuracy, high-speed 3D structured light imaging techniques and potential applications to intelligent robotics
[2] Robust Pixel Classification for 3D Modeling with Structured Light
相关文章
相关标签/搜索