Total Denoising理解

最近读到了2019年的ICCV的关于点云无监督去噪的文章,分享一下自己的理解。

二维与三维噪音
对于二维图像来说,像素位置都是固定的,知识像素值会发生偏移,而对于三维点云图像来说,点的位置噪音是会改变位置,造成一个无序状态。如图2在这里插入图片描述
图2右面的干净点原本是均匀分布在表面的,受到噪音的影响,点不仅会在domain上改变,也会在range上改变。实际上这里是对比二维图像来说的,实际上的三维点云噪音是在三维空间的位置偏移。这种噪音论文叫做total noise
二维与三维去噪
对于二维图像,domain是规则的,即像素的位置不会改变,因此去噪的有监督学习过程一般是:
在这里插入图片描述
其中,噪音值y是符合分布p(z|xi)的,也就是说在干净点xi的影响下,z的取值可能。

对于二维无监督的学习过程:

使用到了成对的图像
本文参考了Noise2Noise,对同一张图片,在不同的均值为0的噪音影响下的y1和y2进行学习,最后得到的学习结果更加偏向于干净图像。
不成对的图像
而对于只是用单独一张图像的去噪,例如Noise2Void,是使用了去除自己的像素点,通过邻域进行学习的方法进行恢复的无监督学习。

对于三维点云有监督的学习:
例如POINTCLEANNET等三维点云的去噪网络,是直接将点坐标作为输入,对点进行去噪的。实现的方法是尽可能的将点恢复到取样表面,因此学习方法一般是:在这里插入图片描述
三维点云无监督学习:
首先,作者首先考虑了是否能够按照Noise2Noise的方法进行去噪,但是有两个困难。首先是很难获得成对的具有不同噪音的点云图,其次是这种方法需要知道两张图点的对应编号,这几乎是不太现实的。因此作者参考了不成对的无监督去噪,提出的total denoise。
但是对于不成对的无监督去噪面临着一些问题,首先是因为点云是无结构分布的,我们并不知道噪音点y是对应哪个真实点x的噪音结果,这对于无监督的学习方法来说,我们仅仅能从周围点中学习出来一条拟合的线/面p(z|S),但是还是无法去确定y对应的干净点的位置,因为y可能是这一条曲线上任何一个位置的噪音结果。而且,因为无监督学习并不会知道真正干净点的位置,因此,是无法真正的将噪音与真实值区分开,所以,确定点y对应干净点在曲线上的位置基本上是不可能实现的。那么作者就引进了一个先验。
在这里插入图片描述
这里的q(z|y)表示的是在给定一个点y,点z是y的干净点的概率。Wd的目的是将d进行归一化,W=1/αr,r是点y的取样半径,5%的模型对角线长度,α是一个比例系数。那么去优化这样一个loss:
在这里插入图片描述
再回头看一下这个先验q(z|y),它由两部分组成,一部分是之前提到的p(z|S),是从周围点中学习来的一个多模,第二部分是一个高斯分布,很明显是以0为均值,干净点z到y的距离为输入值的高斯分布。那么随着距离的增大,分布值就会减小。以此式作为先验,且作为概率值,很明显是倾向于离y点近的点的。那么问题就是如果z点满足这个先验,自然选取概率值最大的点即可,但是如何得到这个值呢,因为p(z|S)是个不可知的分布,那么在实验过程中,作者使用了拒绝采样,首先在以y为中心,r为半径的区域内随机选择点q,如果k(q-y)>ξ,其中ξ是在区间(0,1)内的随机平均取值,那么点q的集合作为Q进行训练。每个点q的选择都是关于分布q的一个内部期望值。关于颜色的问题就是单纯的在q的选择上不选择其他颜色的点,这样可以显示出尖锐的角。
那么在选择出q的集合之后该怎么办呢,在这里插入图片描述
这是作者给出的算法图,其中Q是q的集合,L0范式的表示为在这里插入图片描述
很让人疑惑的是,具体的操作细节,在损失函数上,q很明显表现得是一个预测点,那么取样得时候很明显范围内不只是一个点,那么最后的q点怎么确定,是通过计算每个q点的损失函数,还是通过先验直接确定q点,很可惜论文中并没有对此进行详细描述,而且代码比较麻烦,用到的MCCNN许多函数,很难读懂,所以这个问题一直比较困扰,见更新。贴出相关代码:

def create_loss(positions, predictedPostions, regPoints, lOrderLoss, 
    global_step, totalNumSteps, patchRadius, regTerm, regLambda):

    # Create the main loss.
    diffPos = (positions-predictedPostions)
    diffPos = tf.abs(diffPos)

    if lOrderLoss == 0:
        exponent = 2.0*(1.0 - (tf.to_float(global_step) \
            *tf.constant(1.0/float(totalNumSteps))))
        exponent = tf.maximum(exponent, 1e-8)
        diffPos = diffPos + tf.constant(1e-8)
        regScale = tf.pow(patchRadius, exponent)/(patchRadius*patchRadius)
    elif lOrderLoss == 1:
        exponent = tf.constant(1.0)
        regScale = patchRadius/(patchRadius*patchRadius)
    elif lOrderLoss == 2:
        exponent = tf.constant(2.0)
        regScale = 1.0

    diffPos = tf.pow(diffPos, exponent)

    loss_axes = tf.reduce_sum(diffPos, axis=1)
    loss = tf.reduce_mean(loss_axes)

    # Create the regularization term to avoid clulstering.
    if regTerm:
        regLoss = tf.reduce_mean(tf.reduce_sum(tf.square(regPoints-predictedPostions), axis=1))*regScale
    else:
        regLoss = 0.0

    return loss*(1.0-regLambda)+regLoss*regLambda

再最后看这一篇文章,作者提出了一个先验模型,为什么会提出这样一个模型呢,是因为只是单纯的学习局部特征,会得出一个多种模式,无法确定一个点的确切位置。在提出先验的情况下,不仅改变了点的采样模式,而且把点固定到了一个最近的位置。并且提出了关于颜色的改进。
更:
在读到DMR denoising的时候,恰好文章作者也使用了Total denoising的损失函数,趁机搞懂了是如何使用的。首先通过KNN寻找到原噪音点的K个近邻,并且通过距离计算这个点是干净点的概率,即高斯分布公式。然后再对所有的概率进行伯努利采样,剩下的点作为预测点的目标点,取距离的均值。这里面有个难点,就是如何确定噪音点所对应的预测点。以局部输入为例子,假设我们输入了以噪音点i为中心,r为半径的点云,放入网络中去学习,来预测噪音点i的干净点位置。很自然我们可以获得i的K近邻,但是DMR却使用了emd来给预测点和噪音点进行配对,我认为是作者使用了流形重建,删除了一半的点,然后再重新生成导致了无法判断映射点,因此只能这么做。
那么我们反观本文的代码,

neighPredPts, _, _, startIndexsPred, packedNeighsPred = model.create_neighborhood(mPointHierarchyPred, 
            mPointHierarchyIn, patchRadius, relRad=False)
        knnIndexs = find_knn(neighPredPts, predPts, startIndexsPred, packedNeighsPred, -1)
        knnIndexsReshaped = tf.reshape(knnIndexs, [-1])
        regPredPoints = tf.gather(neighPredPts, knnIndexsReshaped)

        mPointHierarchyColor = mPointHierarchyIn
        if args.priorFeatSpace:
            mPointHierarchyColor = model.create_point_hierarchy_output(inPts, inBatchIds, inFeaturesColor, 1, relRad=False)

        neighPts, neighFeatures, _, startIndexs, packedNeighs = model.create_neighborhood(mPointHierarchyColor, 
            mPointHierarchyColor, patchRadius, relRad=False)
        randIndexs = random_neighbors(neighPts, neighFeatures, inPts, mPointHierarchyColor.features_[0], inBatchIds, 
            startIndexs, packedNeighs, mPointHierarchyColor.aabbMin_, mPointHierarchyColor.aabbMax_, args.prior, 
            patchRadius*args.scalePrior, 1, False, args.priorFeatSpace)
        randIndexsReshaped = tf.reshape(randIndexs, [-1])
        regressPredPoints =  tf.gather(neighPts, randIndexsReshaped)
        
        diffLoss = create_loss(regressPredPoints, predPts, regPredPoints, args.lossOrder, epoch_step, \
            args.numTrainingSteps, patchRadius, args.regTerm, args.regNoisyLambda)

在调用random_neighbors函数之后,得到的idx是先验概率大于平均取样的序号,如下代码:

 float prob = 0.0;
                if(pdf ==1){
                    prob = exp(-(distance*distance)*1.5625)*0.705236979; //Gaussian: STD=0.5657
                }else if(pdf == 2){
                    prob = pow(max(1.0f-distance, 0.0f), 4.0f)*(1.0f+4.0f*distance); //Wendland C2
                }else if(pdf == 3){
                    prob = 1.0f/sqrt(1.0f+pow(distance*5.0f, 2.0f)); //Inverse multiquadric with E=5.0
                }

                if(curand_uniform(&localState) < prob){
                    selectedIndex = currIndex;
                }
                lastIndex = currIndex;
                counter++;
            }
            if(selectedIndex < 0){
                selectedIndex=lastIndex;
                if(lastIndex < 0){
                    selectedIndex = 0;
                }
            }
        }
        pPtsIndices[currentSampleIndex] = selectedIndex;
    }

也就是说和DMR denoising一样,都是采样了概率较大的点,取平均值的方法计算loss,那么这样做的好处是什么呢?回想Noise2Void这篇文章,作者使用了盲点网络,根据邻居信息来获取盲点的值,那么这篇文章为什么不采用相同的方法,而是假设了一个先验模型呢?
回读文章,在实验结果上我们可以看到,在这里插入图片描述
在没有先验模型下,去噪差距还是比较明显的,那么加入这个模型,对去噪的影响是什么呢?如果没有这个先验,那么对预测点起作用的点将会是整个局部的所有点,但是加入了这个先验之后,能够影响预测点的点少了,并且,很关键的一点是加入了一定的随机性。那么令人感兴趣的是,是随机性对最后效果起到的作用更大,还是因为作用域变小导致的拟合信息更加精确呢?
换句话讲,如果因为作用域变小导致的更加精确,那么我们换个思路,给每个点加上一个注意力机制会怎么样?那如果是因为随机性的作用更加巨大,那么我们随机丢弃一些点又会怎么样呢?那二者相结合,最后结果又会如何呢?
先验模型明显偏向于离噪音点较近的点,而真实点中与噪音点i相邻的点可能会相距较远,因此在一次去噪后,噪音点可能会靠近物体表面,但是不太可能一步到位,因此这也是论文中提出多次迭代的原因。那么如果找到一个先验模型,能够考虑到这种情况,效果一定会更加完善。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值