通常来说有两种方法,Two-Pass算法和Seed-Filling算法。前者是通过遍历两次图像,将图像中存在的所有联通区域找出来并标记;后者是源于计算机图形学对于某个图形进行填充,其思路是区域生长算法。想了解更具体的原理自己去搜资料吧,我懒。其实现在skimage或者opencv库都有相应的封装函数,但是一向喜欢造轮子的我喜欢手撕,最重要的,我可以根据业务需要随时进行改动源码。废话不多说,上源码,我知道这就是你们来csdn的原因。。。代码只是基本的思路实现,加速啥的自己做吧。
import cv2
import numpy as np
import sys
import matplotlib.pyplot as plt
N_hoods_4=True
N_hoods_8=False #尽可能少定义全局变量,在python里会让代码速度变慢;固定参数较多,可以考虑写成config文件导入使用;
OFFSETS_4=[[0,-1],[0,0],[1,0],[0,1]]
OFFSETS_8=[[-1,-1],[0,-1],[1,-1],
[-1,0],[0,0],[1,0],
[-1,1],[0,1],[1,1]]
def Research(img:np.array):
index_List=[]
points_List=[]
index=-1
assert(img.shape[2]==1)
h,w=img.shape
for i in range(h):
for j in range(w): #使用for循环比while要高效
pixel=img[i][j]
if pixel<0.5:
continue
if pixel in index_List:
index=index_List.index(pixel)
num=index+1
else:
index_Lenght=len(index_List)
num=index+1
index_List.append(pixel)
points_List.append([])
img[i][j]=num
points_List[index].append([i,j])
return img,points_List
def neighbor_value(img:np.array,offsets,flag=False):
assert(img.shape[2]==1)
h,w=img.shape
label_id=0
new_rows=[0,h,1] if flag==False else [h-1,-1,-1]
new_cols=[0,w,1] if flag==False else [w-1,-1,-1]
threshold=0.5
for i in range(new_rows[0],new_rows[1],new_rows[2]):
for j in range(new_cols[0],new_cols[1],new_cols[2]):
label=255
if img[i][j]<threshold:
continue
for offset in offsets:
nh_row=min(max(0,i+offset[0]),h-1)
nh_col=min(max(0,j+offset[1]),w-1)
nh_value=img[nh_row,nh_col]
if nh_value<threshold:
continue
label=nh_value if nh_value<label else label
if label==255:
label_id+=1
label=label_id
img[i][j]=label
return img
def TwoPass(img:np.array,nh_matrix):
if nh_matrix==N_hoods_4:
offsets=OFFSETS_4
elif nh_matrix==N_hoods_8:
offsets=OFFSETS_8
else:
sys.stderr.write("error in TwoPass!\n")
img=neighbor_value(img,offsets,False)
img=neighbor_value(img,offsets,True)
return img
def recursive_seed(img:np.array,row,col,offsets,Num,max_num):
assert(img.shape[2]==1)
h,w=img.shap
img[row][col]=Num
for offset in offsets:
nh_row=min(max(0,row+offset[0]),h-1)
nh_col=min(max(0,col+offset[1]),w-1)
var=img[nh_row][nh_col]
if var<max_num:
continue
img=recursive_seed(img,nh_row,nh_col,offsets,max_num)
return img
def Seed_filling(img:np.array,nh_matrix,max_num=100):
if nh_matrix==N_hoods_4:
offsets=OFFSETS_4
elif nh_matrix==N_hoods_8:
offsets=OFFSETS_8
else:
sys.stderr.write("error in Seed_filling!\n")
num=1
assert(img.shape[2]==1)
h,w=img.shap
for i in range(h):
for j in range(w):
pixel=img[i][j]
if pixel<=max_num:
continue
img=recursive_seed(img,h,w,offsets,num,max_num)
num+=1
return img
if __name__ == "__main__": #使用例子
imgPath="demo.png"
img=cv2.imread(imgPath,0)
fig, ax1 = plt.subplots(nrows=1, ncols=1, figsize=(10, 10))
ax1.imshow(img, cmap=plt.cm.gray)
ax1.axis('off')
ax1.set_title('rawdata', fontsize=20)
fig.tight_layout()
plt.show()
mode=0
if mode==0:
binary_img=TwoPass(img,OFFSETS_8)
binary_img,P=Research(binary_img)
elif mode==1:
binary_img=Seed_filling(img,OFFSETS_8)
binary_img,P=Research(binary_img)
print(binary_img," ",P)
本文介绍了两种二值图像连通域查找的方法:Two-Pass算法和Seed-Filling算法。通过Python实现,并提供了相关代码示例。利用skimage或opencv库也可完成,但作者更倾向于自定义实现以便于业务调整。
2894

被折叠的 条评论
为什么被折叠?



