使用BFS连接组件标签

时间:2014-11-19 00:03:33

标签: python algorithm python-2.7 computer-vision graph-theory

我正在使用BFS算法解决连通分量标记算法。原始图像im将被标记为图像。

当blob很小时,此代码可以正常工作。但是,当我将起点更改为具有大blob时,代码要么达到最大递归深度,要么具有分段错误。如何避免这些问题?

import cv2
import numpy as np
from collections import deque
import sys
import copy

sys.setrecursionlimit(10000000)

def bfs(queue, im, out, label):
    if len(queue) > 0:
        pixel = queue.pop()
        print pixel
        out[pixel] = label

        M, N = im.shape
        for n in neighbors(pixel, M, N):
            if out[n] == 0 and im[n] == im[pixel]:
                queue.append(n)
        out = bfs(queue, im, out, label)
    return out

def neighbors(pixel, M, N):
    if pixel[0] == M - 1 and pixel[1] == N - 1:
        return [(M-2, N-1), (M-1, N-2)]
    elif pixel == (0,0):
        return [(0,1),(1,0)]
    elif pixel == (M - 1, 0):
        return [(M-1, 1), (M-2, 0)]
    elif pixel == (0, N - 1):
        return [(1, N-1), (0, N-2)]
    elif pixel[0] == 0:
        return [(1,pixel[1]), (0, pixel[1]-1), (0 ,pixel[1] + 1)]
    elif pixel[1] == 0:
        return [(pixel[0], 1), (pixel[0]-1, 0), (pixel[0] + 1, 0)]
    elif pixel[0] == M - 1:
        return [(pixel[0], pixel[1] + 1), (pixel[0] - 1, pixel[1]), (pixel[0], pixel[1] - 1)]
    elif pixel[1] == N - 1:
        return [(pixel[0] + 1, pixel[1]), (pixel[0], pixel[1] - 1), (pixel[0] - 1, pixel[1])]
    else: 
        return [(pixel[0] + 1, pixel[1]), (pixel[0], pixel[1] + 1),\
                (pixel[0] - 1, pixel[1]), (pixel[0], pixel[1] - 1)]


im = cv2.imread('33039.png', cv2.IMREAD_GRAYSCALE)
out = np.zeros(im.shape)

queue = deque()
queue.append((10,10))
out = bfs(queue, im, out, 1)

2 个答案:

答案 0 :(得分:1)

BFS可以很容易地以迭代方式实现。以下是CPP中的一个示例:

void
bfs(const vector< vector<int> > &g)
{
        // visit self, then neighbors, store neighbors using stack.
        vector<bool> visited(g.size(), false);
        vector<int> s;
        Queue Q;
        Q.enqueue(6);
        while (Q.size() > 0)
        {
                int t = Q.dequeue();
                if (!visited[t])
                {
                        cout << "visit node: " << t << endl;
                        visited[t] = true;
                        for (int i = 0; i < g[t].size(); ++i)
                        {
                                if (!visited[g[t][i]])
                                {
                                        Q.enqueue(g[t][i]);
                                }
                        }
                }
        }        
}

答案 1 :(得分:0)

就python解决方案而言,我经常使用这种非递归解决方案:

def bfs(graph,start):
    # Breadth-first search to find pixels connected
    # graph is array with some pixels true and others false
    # start is x, y
    if not graph[start[0]][start[1]]:
        return
    visited = []
    w, h = len(graph)-1, len(graph[0])-1
    queue = [start]
    while queue:
        x, y = queue.pop(0)
        neighbors = []
        if x<w:
            neighbors.append((x+1,y))
        if x>0:
            neighbors.append((x-1,y))
        if y<h:
            neighbors.append((x,y+1))
        if y>0:
            neighbors.append((x,y-1))   
        for n in neighbors:
            if n not in visited and graph[n[0]][n[1]]:
                visited.append(n)
                queue.append(n)
    return visited

我为过去的项目编写的这个版本使用2-d python数组作为输入,并探索True或One的相邻像素。为了在上下文中看到它,我为this编写了它。