opencv提取骨架细化python

发布时间 2023-08-30 13:17:38作者: cn_gzb

来自于这里:基于OpenCV实现二值图细化,骨骼化并求出端点和交叉点_晴堂的博客-CSDN博客

我用python实现,并且改进了一下,看到回复发出来

    def LineMid(binary):
        binary[binary == 255] = 1
        skeleton0 = morphology.skeletonize(binary, method="lee")  # 细化提取骨架
        skeleton = skeleton0.astype(np.uint8) * 255
        intMat = skeleton0.astype(int)
        return skeleton, intMat

    def getPoints(thinSrc, raudis=4, thresholdMax=6, thresholdMin=4):
        height, width = thinSrc.shape[0], thinSrc.shape[1]
        tmp = thinSrc.copy()
        points = []
        for i in prange(height):
            for j in prange(width):
                if (tmp[i][j]) == 0:
                    continue
                count = 0
                for k in range(i - raudis, i + raudis + 1):
                    for l in range(j - raudis, j + raudis + 1):
                        if k < 0 or l < 0 or k > height - 1 or l > width - 1:
                            continue
                        elif tmp[k][l] == 255:
                            count += 1
                if count > thresholdMax:
                    point = (j, i)
                    points.append(point)
        return points

    def SplitImg(binary, points):
        Mat = binary.copy()
        if points:
            for poin in points:
                cv2.circle(Mat, (poin[0], poin[1]), 15, (0, 0, 0), -1)  # 将交点抹除,这里以圆的方式拆除交点
        splitmat = Mat.copy()
        conts, hierarchy = cv2.findContours(Mat, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)  # 区域分块操作
        for j in range(len(conts)):   # 拆除交点后进行预支判定,小于阈值的就不要
            area = cv2.contourArea(conts[j])
            if area < 100:
                cv2.fillPoly(Mat, [conts[j]], 0)
        return Mat, splitmat
binary = Mat.copy()
skeleton, intMat = LineMid(binary)
points = getPoints(skeleton, raudis=1, thresholdMax=3, thresholdMin=4)  # 找存在分支的交点
sigMat, SplitMat = SplitImg(Mat, points)  # 根据交点拆解区域,去除交点区域