图像分割:如何表征检测区域的分散程度?
表征二值掩码中目标区域分散度的可行方案
你完全可以通过计算空间分布相关的量化指标,区分目标区域的集中/分散程度,以下是几种实用的实现方式:
1. 质心坐标标准差
计算所有目标轮廓质心的x、y坐标标准差,数值越大代表目标在对应轴上的分布越分散。
实现代码:
import cv2 import imutils import numpy as np # 你已有的轮廓提取代码 cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) centroids = [] for c in cnts: # 计算轮廓质心 M = cv2.moments(c) if M["m00"] != 0: cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) centroids.append((cX, cY)) if centroids: centroids = np.array(centroids) # 计算x、y坐标的标准差 std_x = np.std(centroids[:, 0]) std_y = np.std(centroids[:, 1]) # 取二者均值作为综合分散度指标 dispersion_std = (std_x + std_y) / 2 print(f"质心标准差分散度: {dispersion_std}") else: print("无目标轮廓")
2. 最小外接矩形占比
计算包裹所有目标轮廓的最小外接矩形面积,再除以所有目标区域的总面积。比值越小,说明目标分布越分散(分散目标需要更大的外接框包裹,占比偏低,可取倒数调整指标方向)。
实现代码:
# 基于已有的cnts和areas列表 total_target_area = np.sum(areas) if total_target_area == 0: print("无目标区域") else: # 获取所有轮廓的边界点 all_points = [] for c in cnts: all_points.extend(c.reshape(-1, 2)) all_points = np.array(all_points) # 计算最小外接矩形 rect = cv2.minAreaRect(all_points) rect_area = rect[1][0] * rect[1][1] # 计算占比并调整指标方向 dispersion_rect_ratio = rect_area / total_target_area print(f"外接矩形占比分度: {dispersion_rect_ratio}")
3. 平均最近邻距离
计算每个轮廓质心到其他所有质心的最近距离,取平均值。数值越大,代表目标之间的间隔越大,分布越分散。
实现代码:
if len(centroids) < 2: print("轮廓数量不足,无法计算最近邻距离") else: min_distances = [] for i in range(len(centroids)): # 计算当前质心到其他所有质心的距离 distances = np.sqrt(np.sum((centroids - centroids[i])**2, axis=1)) # 排除自身距离(0),取最小距离 min_dist = np.min(distances[distances != 0]) min_distances.append(min_dist) avg_min_distance = np.mean(min_distances) print(f"平均最近邻距离分散度: {avg_min_distance}")
指标选择建议
- 若目标数量差异不大,质心标准差和平均最近邻距离的区分度较好;
- 若目标数量差异明显,外接矩形占比更稳定,不受轮廓数量影响;
- 可同时计算多个指标,综合判断分散程度。
内容的提问来源于stack exchange,提问作者TritZ
相关产品推荐
相关产品推荐

