OpenCV 通过计算连通域面积过滤面积小的区域–Python

代码参考:https://blog.csdn.net/u014264373/article/details/119486850

通过卷积神经网络预测图像的分割结果时,会发现分割外部出现了小面积的连通域。

常识告诉我们,这么小的物体一定不是我们的分割目标,因此,我们通过后处理的方法把它过滤掉,可以提高分割准确度。

这种小面积的图形,可以使用cv2.connectedComponentsWithStats的连通域统计分析方法。

cv2.connectedComponentsWithStats

函数:connectedComponentsWithStats(image, connectivity=8, cv2.CV_32S)
功能:求得最大连通域。
输入:假如image为128x128大小的图片,有7个连通域。
返回
num_labels:连通域个数,此处为7;
labels:大小128x128,标记图,图中不同连通域使用不同的标记(当前像素是第几个轮廓),和原图宽高一致;
stats:大小7x5,每行5个数分别对应各个轮廓的x,y,width,height和面积。注意0的区域标识的是background;
centroids:大小7x2,分别对应各个轮廓的中心点。

此时可比较stats中各连通域的面积与阈值面积(此处取平均面积area_avg),保留大于阈值的面积即可。

import numpy as np
import cv2 as cv

# 加载图片
img = cv.imread('image_name.png')
# 灰度化
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 二值化
ret, thresh = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY)
# 寻找连通域
num_labels, labels, stats, centroids = cv.connectedComponentsWithStats(thresh, connectivity=8)

# 计算平均面积
areas = list()
for i in range(num_labels):
    areas.append(stats[i][-1])
    print("轮廓%d的面积:%d" % (i, stats[i][-1]))

area_avg = np.average(areas[1:-1])
print("轮廓平均面积:", area_avg)

# 筛选超过平均面积的连通域
image_filtered = np.zeros_like(img)
for (i, label) in enumerate(np.unique(labels)):
    # 如果是背景,忽略
    if label == 0:
        continue
    if stats[i][-1] > area_avg :
        image_filtered[labels == i] = 255

cv.imshow("image_filtered", image_filtered)
cv.imshow("img", img)
cv.waitKey()
cv.destroyAllWindows()




OpenCV 通过计算连通域面积过滤面积小的区域–Python_第1张图片原图共有7个连通域(包括6个前景+1个背景)
OpenCV 通过计算连通域面积过滤面积小的区域–Python_第2张图片过滤掉面积小于平均面积的连通域

产出不易,喜欢的话点个赞吧~~

你可能感兴趣的:(计算机视觉,opencv,python)