python模仿remove_small_objects()函数保留图片中连通域最大的区域
skimage包的morphology子模块中,提供了一个remove_small_objects()
函数,可以通过自己设定的连通域面积阈值有效去掉图片中的噪点,但是在具体使用过程中会发现:这个函数使用起来还有诸多的不便,好在这个函数的源代码并不长,在在skimage包的小优化(1):模仿remove_small_objects()函数去除图片边缘不感兴趣区域
中,我就是通过模仿remove_small_objects()
的源代码,实现了判断连通域与中心坐标的位置远近来去除图片边缘大面积噪声。很好地解决了去掉图片边缘不感兴趣区域的问题。
但是最近在使用过程中,我有发现了另外一个问题:在使用remove_small_objects()
函数的时候,必须要指定一个连通域的面积阈值(这个函数的具体使用方法见:scikit-image(skimage)包的用法详解),而很多时候我们根本不知道这个阈值到底要设为多少。而有时候,我们如果已经知道图片中只有那块连通域面积最大的区域是我们想要的,那么,只需要保留这块区域,其他的都当作噪点删掉即可,没必要非要确定一个面积阈值。
具体实现如下:
##输入:一张二值图像,无须指定面积阈值,
##输出:会返回保留了面积最大的连通域的图像
def save_max_objects(img):
labels = measure.label(img) # 返回打上标签的img数组
jj = measure.regionprops(labels) # 找出连通域的各种属性。 注意,这里jj找出的连通域不包括背景连通域
# is_del = False
if len(jj) == 1:
out = img
# is_del = False
else:
# 通过与质心之间的距离进行判断
num = labels.max() #连通域的个数
del_array = np.array([0] * (num + 1))#生成一个与连通域个数相同的空数组来记录需要删除的区域(从0开始,所以个数要加1)
for k in range(num):#TODO:这里如果遇到全黑的图像的话会报错
if k == 0:
initial_area = jj[0].area
save_index = 1 # 初始保留第一个连通域
else:
k_area = jj[k].area # 将元组转换成array
if initial_area < k_area:
initial_area = k_area
save_index = k + 1
del_array[save_index] = 1
del_mask = del_array[labels]
out = img * del_mask
# is_del = True
return out