このような方法は多数あり、それらは連結成分ラベリングと呼ばれます。それほど古くないものの一部を次に示します (順不同)。
- RISCアーキテクチャのための光速ラベリング、2009年
- 2パス連結成分ラベリングアルゴリズムの最適化、2009年
- 等高線追跡技術を使用した線形時間コンポーネント ラベル付けアルゴリズム、2004
2 番目の方法は、文献で「Wu のアルゴリズム」として言及されており (実際には古い論文を参照していますが、そこで提示されているアルゴリズムは同じです)、このタスクで最も高速な方法の 1 つと見なされています。フラッド フィルの使用は、これらの方法に比べて非常に遅いため、絶対に使用したくない方法の 1 つです。この Wu アルゴリズムは、パス圧縮を使用したユニオン検索データ構造に基づく 2 パス ラベル付けであり、比較的簡単に実装できます。この論文は 8 接続性を扱っているため、4 接続性 (あなたの質問の対象) を処理するためのサンプル コードを含めます。
union-find 構造のコードは論文からそのまま引用していますが、このデータ構造について読んだほぼすべてのテキストに同様のコードが見つかります。
def set_root(e, index, root):
# Set all nodes to point to a new root.
while e[index] < index:
e[index], index = root, e[index]
e[index] = root
def find_root(e, index):
# Find the root of the tree from node index.
root = index
while e[root] < root:
root = e[root]
return root
def union(e, i, j):
# Combine two trees containing node i and j.
# Return the root of the union.
root = find_root(e, i)
if i != j:
root_j = find_root(e, j)
if root > root_j:
root = root_j
set_root(e, j, root)
set_root(e, i, root)
return root
def flatten_label(e):
# Flatten the Union-Find tree and relabel the components.
label = 1
for i in xrange(1, len(e)):
if e[i] < i:
e[i] = e[e[i]]
else:
e[i] = label
label += 1
簡単にするために、配列の上部と左側にゼロが埋め込まれていると仮定します。
def scan(a, width, height): # 4-connected
l = [[0 for _ in xrange(width)] for _ in xrange(height)]
p = [0] # Parent array.
label = 1
# Assumption: 'a' has been padded with zeroes (bottom and right parts
# does not require padding).
for y in xrange(1, height):
for x in xrange(1, width):
if a[y][x] == 0:
continue
# Decision tree for 4-connectivity.
if a[y - 1][x]: # b
if a[y][x - 1]: # d
l[y][x] = union(p, l[y - 1][x], l[y][x - 1])
else:
l[y][x] = l[y - 1][x]
elif a[y][x - 1]: # d
l[y][x] = l[y][x - 1]
else:
# new label
l[y][x] = label
p.append(label)
label += 1
return l, p
したがって、最初a
にこの関数に渡す配列がありますscan
。これは最初のラベリング パスです。ラベルを解決するには、単に を呼び出しますflatten_label(p)
。次に、2 番目のラベル付けパスは簡単なものです。
for y in xrange(height):
for x in xrange(width):
l[y][x] = p[l[y][x]]
これで、4 連結コンポーネントにラベルが付けられ、max(p)
それらの数がわかります。このコードに沿って論文を読めば、問題なく理解できるはずです。構文は Python からのものです。その意味について疑問がある場合は、お気軽にお問い合わせください。