OpenCV—python连通域标记

OpenCV—python连通域标记
⽂章⽬录
连通域
图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域,连通域分析是指在图像中寻出彼此互相独⽴的连通域并将其标记出来。提取图像中不同的连通域是图像处理中较为常⽤的⽅法,在⽬标检测等领域对感兴趣区域分割与识别。⼀般情况下,⼀个连通域内只包含⼀个像素值,因此为了防⽌像素值波动对提取不同连通域的影响,连通域分析常处理的是⼆值化后的图像。
在了解图像连通域分析⽅法之前,⾸先需要了解图像邻域的概念。图像中两个像素相邻有两种定义⽅式,分别是4-邻域和8-邻域。
OpenCV-python⾃带了连通域函数,如下:以下的标记⽅法只为了解原理。钢管扩口机
参数详解:
image:待标记不同连通域的单通道图像,数据类型必须为CV_8U。
labels:标记不同连通域后的输出图像,与输⼊图像具有相同的尺⼨。
connectivity:标记连通域时使⽤的邻域种类,4表⽰4-邻域,8表⽰8-邻域。
ltype:输出图像的数据类型,⽬前⽀持CV_32S和CV_16U两种数据类型。
ccltype:标记连通域时使⽤的算法类型标志,可以选择的参数下表中给出。
标志参数简记作⽤
CCL_WU08-邻域使⽤SAUF算法,4-邻域⽤SAUF算法
CCL_DEFAULT-18-邻域使⽤BBDT算法,4-邻域⽤SAUF算法
CCL_GRANA18-邻域使⽤BBDT算法,4-邻域⽤SAUF算法
4-邻域连通域标记
Lookup Table:
Source Distination地下室排水沟
11
22
桔梗去皮机31
⼀开始被打上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,4等。
3. 如果两个像素中有⼀个不为0(也就是说已经分配了标签),将上⽅和左边的像素分配的标签中数值较⼩的那⼀个(0除外)分配给当
前遍历到的像素i(x,y)。在这⾥,将上⽅像素和左边像素的标签写⼊Lookup Table的Source,将当前遍历的像素i(x,y)分配的标签写⼊Distination。
4. 最后,对照Lookup Table,对像素分配的标签由Source变为Distination。
像这样的话,邻接像素就可以打上同样的标签了。因为这⾥是做4-4−邻域连通域标记,所以我们只⽤考察上⽅像素和左边像素。
import numpy as np
def four_cc_label(img):
height, width, channel = img.shape
label = np.zeros((height, width), dtype=np.int32)
LUT = np.zeros(height * width,dtype=np.uint8)
COLORS = np.array([[0,0,255],[0,255,0],[255,0,0],
[255,255,0],[255,0,255],[0,255,255],
[125,0,255],[0,255,125],[255,0,125],
[255,255,125],[255,125,255],[0,125,255]],dtype=np.uint8)    out = np.zeros((height, width, channel), dtype=np.uint8)
label[img[:,:,0]>0]=1
n =1
for y in range(height):
for x in range(width):
if label[y, x]==0:
continue
c3 = label[max(y -1,0), x]
c5 = label[y,max(x -1,0)]
if c3 <2and 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
for index, lut in enumerate(LUT[2:]):
out[label ==(index +2)]= COLORS[lut -2]
return out
if __name__ =='__main__':
img = cv2.imread("123.png")
out = four_cc_label(img)
cv2.imwrite("out1234.png", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
8-邻域连通域标记
要进⾏8-8−邻域连通域标记,我们需要考察4个像素:左上 i(x-1,y-1),正上i(x, y-1),正左i(x-1,y),左下i(x+1,y-1)或者右上。
import numpy as np
def four_cc_label(img):
height, width, channel = img.shape
label = np.zeros((height, width), dtype=np.int32)
LUT = np.zeros(height * width,dtype=np.uint8)
COLORS = np.array([[0,0,255],[0,255,0],[255,0,0],
[255,255,0],[255,0,255],[0,255,255]],dtype=np.uint8)    out = np.zeros((height, width, channel), dtype=np.uint8)
label[img[:,:,0]>0]=1
n =1
for y in range(height):
for x in range(width):
销子材料if label[y, x]==0:
continue
c2 = label[max(y -1,0),min(x +1, width -1)]
c3 = label[max(y -1,0), x]
c4 = label[max(y -1,0),max(x -1,0)]
c5 = label[y,max(x -1,0)]
if c3 <2and c5 <2and c2 <2and c4 <2:
n +=1
label[y, x]= n
else:
_vs =[c3, c5, c2, c4]
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
for i, lut in enumerate(LUT[2:]):
out[label ==(i +2)]= COLORS[lut -2]
return out
if __name__ =='__main__':
img = cv2.imread("123.png")
out = four_cc_label(img)
cv2.imwrite("out456.png", out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()

本文发布于:2024-09-21 16:25:08,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/145000.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:像素   图像   邻域   标签   分配   参数   算法   感兴趣
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议