在python中寻找骨架化图像的交集

2024-06-01 07:43:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个骷髅图像(如下所示)。在

Skeleton Image

我想知道线路的交叉点。我尝试了以下方法,skeleton是一个openCV图像,算法返回一个坐标列表:

def getSkeletonIntersection(skeleton):
    image = skeleton.copy();
    image = image/255;
    intersections = list();
    for y in range(1,len(image)-1):
        for x in range(1,len(image[y])-1):
            if image[y][x] == 1:
                neighbourCount = 0;
                neighbours = neighbourCoords(x,y);
                for n in neighbours:
                    if (image[n[1]][n[0]] == 1):
                        neighbourCount += 1;
                if(neighbourCount > 2):
                    print(neighbourCount,x,y);
                    intersections.append((x,y));
    return intersections;

它查找有两个以上相邻像素的白色像素的坐标。我原以为这只会回角球,但它不会-它会返回更多的分数。在

Skeleton with marked coordinates

这是它检测到的点在图像上标记的输出。这是因为它检测到下面显示的一些不是交叉点的示例。在

^{pr2}$

还有更多的例子。有没有其他方法我应该看看,以检测交叉口。感谢所有的意见和想法,谢谢。在


Tags: 方法in图像imageforlenifrange
3条回答

我最近收到一封电子邮件,要求我最终解决这个问题。它被张贴在下面,以便通知其他人。我不声称这段代码特别快或稳定-只说它对我有用!该功能还包括过滤重复项和检测到的交叉点太近,表明它们不是真正的交叉点,而是在骨架化过程中引入噪声。在

def neighbours(x,y,image):
    """Return 8-neighbours of image point P1(x,y), in a clockwise order"""
    img = image
    x_1, y_1, x1, y1 = x-1, y-1, x+1, y+1;
    return [ img[x_1][y], img[x_1][y1], img[x][y1], img[x1][y1], img[x1][y], img[x1][y_1], img[x][y_1], img[x_1][y_1] ]   


def getSkeletonIntersection(skeleton):
    """ Given a skeletonised image, it will give the coordinates of the intersections of the skeleton.

    Keyword arguments:
    skeleton -- the skeletonised image to detect the intersections of

    Returns: 
    List of 2-tuples (x,y) containing the intersection coordinates
    """
    # A biiiiiig list of valid intersections             2 3 4
    # These are in the format shown to the right         1 C 5
    #                                                    8 7 6 
    validIntersection = [[0,1,0,1,0,0,1,0],[0,0,1,0,1,0,0,1],[1,0,0,1,0,1,0,0],
                         [0,1,0,0,1,0,1,0],[0,0,1,0,0,1,0,1],[1,0,0,1,0,0,1,0],
                         [0,1,0,0,1,0,0,1],[1,0,1,0,0,1,0,0],[0,1,0,0,0,1,0,1],
                         [0,1,0,1,0,0,0,1],[0,1,0,1,0,1,0,0],[0,0,0,1,0,1,0,1],
                         [1,0,1,0,0,0,1,0],[1,0,1,0,1,0,0,0],[0,0,1,0,1,0,1,0],
                         [1,0,0,0,1,0,1,0],[1,0,0,1,1,1,0,0],[0,0,1,0,0,1,1,1],
                         [1,1,0,0,1,0,0,1],[0,1,1,1,0,0,1,0],[1,0,1,1,0,0,1,0],
                         [1,0,1,0,0,1,1,0],[1,0,1,1,0,1,1,0],[0,1,1,0,1,0,1,1],
                         [1,1,0,1,1,0,1,0],[1,1,0,0,1,0,1,0],[0,1,1,0,1,0,1,0],
                         [0,0,1,0,1,0,1,1],[1,0,0,1,1,0,1,0],[1,0,1,0,1,1,0,1],
                         [1,0,1,0,1,1,0,0],[1,0,1,0,1,0,0,1],[0,1,0,0,1,0,1,1],
                         [0,1,1,0,1,0,0,1],[1,1,0,1,0,0,1,0],[0,1,0,1,1,0,1,0],
                         [0,0,1,0,1,1,0,1],[1,0,1,0,0,1,0,1],[1,0,0,1,0,1,1,0],
                         [1,0,1,1,0,1,0,0]];
    image = skeleton.copy();
    image = image/255;
    intersections = list();
    for x in range(1,len(image)-1):
        for y in range(1,len(image[x])-1):
            # If we have a white pixel
            if image[x][y] == 1:
                neighbours = neighbours(x,y,image);
                valid = True;
                if neighbours in validIntersection:
                    intersections.append((y,x));
    # Filter intersections to make sure we don't count them twice or ones that are very close together
    for point1 in intersections:
        for point2 in intersections:
            if (((point1[0] - point2[0])**2 + (point1[1] - point2[1])**2) < 10**2) and (point1 != point2):
                intersections.remove(point2);
    # Remove duplicates
    intersections = list(set(intersections));
    return intersections;

这在github here上也可用。在

如果对给定像素,而不是计算8个邻居的总数(=具有8个连通性的邻居)的数量,而是计算彼此不是4个邻居的8个邻居的数量,这可能会有帮助

所以在你的假阳性例子中

0 0 0    1 1 0    0 1 1
1 1 1    0 1 0    1 1 0
0 0 1    0 0 1    0 0 0

对于每种情况,你有3个邻居,但每次,其中2个是4连通的。(下一个片段中标记为“2”的像素)

^{pr2}$

如果只考虑其中一个作为计数(而不是现在在代码中同时考虑这两个),则实际上只有2个新定义的“邻居”,并且考虑的点不被视为交点。 其他“真正的十字路口”仍将保留,如下所示

0 1 0    0 1 0    0 1 0
1 1 1    0 1 0    1 1 0
0 0 0    1 0 1    0 0 1

仍然有3个新定义的邻居。在

我还没有检查过你的图片是否完美,但我已经为这个问题实施了类似的东西。。。在

我不确定OpenCV的特性,但是您可以尝试使用Hit-and-Miss形态学,它描述了here。在

阅读线路连接并查看需要测试的12个模板:

enter image description here

相关问题 更多 >