Opencv 4-邻域连通域标记

seg.png进行4-邻域连通域标记吧。

连通域标记(Connected Component Labeling)是将邻接的像素打上相同的标记的作业。

也就是说:

黒 黒 黒 黒
黒 白 白 黒
黒 白 黒 黒
黒 黒 黒 黒

将相邻的白色像素打上相同的标记。

像这样的像素组成的被标记的块被称为连通区域(Connected Component)。

在这里我们为4邻域的像素打上标记。另,在这里我们使用一种被称为Lookup Table的东西。

Lookup Table是这样的:

Source Distination
1 1
2 2
3 1

一开始被打上1标签的像素(即Source=1的像素)最终被分配到的标签为1(Distination=1);一开始被打上3标签的像素(即Source =3的像素)最终被分配的的标签也为1(Distination=1)。

算法如下:

  1. 从左上角开始进行光栅扫描。

  2. 如果当前遍历到的像素i(x,y)是黑像素的什么也不干。如果是白像素,考察该像素的上方像素i(x,y-1)和左边像素i(x-1,y),如果两个的取值都为0,将该像素分配一个新的标签。

    在这里我们用数字做标签,即1,2。

  3. 如果两个像素中有一个不为0(也就是说已经分配了标签),将上方和左边的像素分配的标签中数值较小的那一个(0除外)分配给当前遍历到的像素i(x,y)。在这里,将上方像素和左边像素的标签写入Lookup TableSource,将当前遍历的像素i(x,y)分配的标签写入Distination

  4. 最后,对照Lookup Table,对像素分配的标签由Source变为Distination

像这样的话,邻接像素就可以打上同样的标签了。因为这里是做4-邻域连通域标记,所以我们只用考察上方像素和左边像素。

python实现:

import cv2
import numpy as np
import matplotlib.pyplot as plt

# Read image
img = cv2.imread("seg.png").astype(np.float32)
H, W, C = img.shape

label = np.zeros((H, W), dtype=np.int)
label[img[..., 0]>0] = 1

LUT = [0 for _ in range(H*W)]

n = 1

for y in range(H):
    for x in range(W):
        if label[y, x] == 0:
            continue
        c3 = label[max(y-1,0), x]
        c5 = label[y, max(x-1,0)]
        if c3 < 2 and c5 < 2:
            n += 1
            label[y, x] = n
        else:
            _vs = [c3, c5]
            vs = [a for a in _vs if a > 1]
            v = min(vs)
            label[y, x] = v

            minv = v
            for _v in vs:
                if LUT[_v] != 0:
                    minv = min(minv, LUT[_v])
            for _v in vs:
                LUT[_v] = minv

count = 1

for l in range(2, n+1):
    flag = True
    for i in range(n+1):
        if LUT[i] == l:
            if flag:
                count += 1
                flag = False
            LUT[i] = count

COLORS = [[0, 0, 255], [0, 255, 0], [255, 0, 0], [255, 255, 0]]
out = np.zeros((H, W, C), dtype=np.uint8)

for i, lut in enumerate(LUT[2:]):
    out[label == (i+2)] = COLORS[lut-2]

# Save result
cv2.imwrite("out.png", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

输入(seg.png):

Opencv 4-邻域连通域标记

输出:

Opencv 4-邻域连通域标记

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程