如何在数学上定义嘈杂的轮廓?

时间:2019-01-10 22:58:11

标签: python algorithm opencv math image-processing

看下面的图片:

enter image description here

如您所见,某些区域非常嘈杂(边缘呈锯齿状,变化很多)

我想从图像中消除这些区域,但是要做到这一点,我需要能够确定这种“噪声”的含义。

我曾经考虑过要测量连续轮廓点的角度变化,并以此来确定是否有噪声,但是我不确定这是一种鲁棒的噪声区域检测。

有人对如何数学定义这些区域有建议吗?

3 个答案:

答案 0 :(得分:3)

我试图通过分析其曲率值来定义嘈杂的轮廓。 以下是实施细节:

1. Threshold the gray scale image using fixed threshold value of 250 to retrieve the white edges

2.Extract the contours in the threshold image

3.Calculate the curvature values along each contour

4.From the curvature data we can observer that the noisy contour's curvature values has higher variance value, therefore we can classify such
noisy contours using certain threshold value.

以下是上述步骤的Python实现。  在这里,我使用了here

定义的笛卡尔坐标系的曲率估计方程
#function to calculate the curvature values along a given contour and classify noisy contour
def contourCurvature(contourspt):
    #curvature value estimation using symmetric derivation
    # at points (i-step), i, (i+step)
    step = 5
    s1 = 2*step
    s2 = np.power(s1, 2)
    if len(contourspt) < s1:
        return False

    kp = []
    l = len(contourspt)
    ct = 0
    for i in range(l):
        p = i - step
        pp = i - s1
        if p < 0:
            p += l
            pp += l
        elif pp < 0:
            pp += l
        n = (i + step) % l
        nn = (i + s1) % l

        posPrev = contourspt[p][0]
        posPrevP = contourspt[pp][0]
        posCurr = contourspt[i][0]
        posNext = contourspt[n][0]
        posNextN = contourspt[nn][0]
        #first order derivative at point i w.r.t. x and y
        f1stderX = (posNext[0] - posPrev[0])/s1
        f1stderY = (posNext[1] - posPrev[1])/s1
        # second order derivative at point i w.r.t. x and y
        f2ndderX = (posNextN[0] - 2*posCurr[0] + posPrevP[0])/s2
        f2ndderY = (posNextN[1] - 2*posCurr[1] + posPrevP[1])/s2

        if f1stderX != 0 or f1stderY != 0:
            a = f2ndderX*f1stderY - f2ndderY*f1stderX
            b = np.power(np.power(f1stderX,2) + np.power(f1stderY,2), 3/2)
            curvature2D = float("{0:.5f}".format(a/b))

            #Check if contour contains any regular section of more than 
            # 20 percent of the contour length
            if np.abs(curvature2D) < 0.005:
                ct += 1
                if ct > l*0.2:
                    return True
            else:
                ct = 0
            if np.abs(curvature2D) < 0.0001 or np.abs(curvature2D) > 5: 
                curvature2D = 0 #local noise suppression
            #store the curvature values in a list
            kp.append(np.abs(curvature2D))

    # check the variance of curvatures values along the contour
    var = np.var(kp, ddof=1)
    if var < 0.01:
        print('Variance: ',var)
        return True
    return False


def main():
    gray = cv2.imread('D:/cnt.png', 0)
    #threshold the image using 250 as threhold value
    ret,th1 = cv2.threshold(gray,250,255,cv2.THRESH_BINARY)
    img1,contours,hierarchy = cv2.findContours(th1, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    img = cv2.cvtColor(gray, cv2.COLOR_GRAY2RGB)
    #iterate through each contour
    for cnt in contours:
        if(len(cnt)>50): #neglect the small contours as noise
            flag = contourCurvature(cnt)
            if(flag):
                cv2.drawContours(img,[cnt],0,(0,0,255),3)

    cv2.imshow('Final image', img)
    cv2.waitKey(0)

if __name__ == "__main__":
    main()

这是仅显示非噪波(真实)轮廓的输出图像。 enter image description here

尽管最终的输出图像缺少一些真实的轮廓,但是在此欢迎任何其他改进此算法的想法。

答案 1 :(得分:1)

您可以尝试以下方法:

  1. 将图像矩阵拆分为完全可迭代的比例。

  2. 对于每个迭代空间,将白色像素拟合为该空间中的线性回归。

  3. 存储每个部分的线性模型中的RSME(均方根误差)。

  4. 计算所有迭代截面的标准偏差。

  5. 选择描述可容忍“噪声”阈值的标准偏差。

您需要尝试使用不同的“迭代大小”来找到最佳的噪声描述符。

如果要比较图片之间的相对噪声水平,则使用卷积机学习设计可以最好地解决此问题。

答案 2 :(得分:1)

您首先可以使用道格拉斯-皮克(Douglas-Peucker)用多边形曲线近似每个轮廓(或其一部分),以便最大误差在全局范围内,然后考虑

  1. 将近似值的周长与原始曲线的周长进行比较
  2. 计算原始曲线上每个点到近似多边形曲线的距离,然后计算该数据集的标准偏差。

或者您可以采用相同轮廓的粗略近似和多边形近似,并按近似近似值的每个长度计算精细近似中的段数。