话不多说,cv2下的连通区域函数:cv2.connectedComponentsWithStats 网上大部分都是C++教程
这里使用连通区域函数筛选出3个最大区域,然后顺手利用得到的二值化图像做腐蚀-膨胀去除毛边
注意传入的image必须是灰度图
import cv2
import numpy as np
from collections import Counter
def postprocess(self, img):
# 先搞成灰度图
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_ = np.array(img.copy(), dtype=np.int8)
connectivity = 4
# 连通组件
num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(img_, connectivity, cv2.CV_8U)
# labels就是由连通区域编号组成的mask 尺寸与原图对应
labels = np.array(labels, dtype=np.float)
# 统计各个连通区域的元素个数并排序,这里我希望得到的图像只包括三个及以下区域,于是most_common(3)
maxnum = Counter(labels.flatten()).most_common(3)
maxnum = sorted([x[0] for x in maxnum])
# 制作一个包括背景和最大n个连通区域组成的Mask
background = np.zeros_like(labels)
if len(maxnum) == 1:
pass
elif len(maxnum) == 2:
background[labels == maxnum[1]] = 1
else:
background[labels == maxnum[1]] = 1
background[labels == maxnum[2]] = 1
# img[background == 0] = 0 就可以得到筛选连通区域之后的图像
# 接下来使用腐蚀-膨胀去除连通区域的毛边
K_SIZE = 10
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (K_SIZE, K_SIZE))
background = cv2.morphologyEx(background, cv2.MORPH_OPEN, kernel)
background = cv2.morphologyEx(background, cv2.MORPH_CLOSE, kernel)
img[background == 0] = 0
# 返回灰度图
return img