在图像处理和计算机视觉中,计算对象面积的常见方法有两种:使用四邻域标记算法和使用轮廓计算。每种方法在不同情况下有各自的优缺点。
-
四邻域标记算法:
- 优点 :
- 简单易实现。
- 能够处理带有孔洞的复杂区域(只要孔洞不影响连通性判断)。
- 缺点 :
- 对于边缘不清晰或有噪声的图像,可能会导致面积计算误差。
- 依赖于图像分辨率和阈值选择的精度。
- 优点 :
-
轮廓计算:
- 优点 :
- 通常更精确,因为它直接使用对象的边缘来计算面积。
- 适合处理边界清晰的对象。
- 可以在亚像素级别计算面积,提供更高精度。
- 缺点 :
- 计算复杂度相对较高,特别是在图像边缘检测和轮廓提取步骤。
- 对于有噪声的图像,边缘检测可能会失败或产生错误的轮廓。
- 优点 :
更准确的选择
通常情况下,使用轮廓计算面积更为准确,特别是在以下情况下:
- 图像边缘清晰。
- 需要高精度的面积计算。
- 可以处理复杂形状和多种连通区域。
分别代码:
1 轮廓
python
# 获取连通域的边界和标签 # 查看各个轮廓
contours, _ = cv2.findContours(gray_frame_seg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 筛选出面积较小的轮廓
option_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > area_threshold]
logging.info(f'count: {len(contours)}, option contours: {len(option_contours)}')
# 初始化要计算的参数
num_contours = len(option_contours)
areas = np.zeros(num_contours)
2 四邻域标记算法
python
def calculate_perimeter():
"""计算连通区域的周长"""
contours, _ = cv2.findContours(region.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
perimeter = 0
for contour in contours:
perimeter += cv2.arcLength(contour, True)
return perimeter
# 找到连通区域并计算每个区域的面积和周长
labeled_array, num_features = label(gray_frame_seg)
print(f'labeled_array, num_features:{labeled_array, num_features}')
areas1 = []
perimeters1 = []
# 遍历每个连通区域
for region_slice in find_objects(labeled_array):
region = labeled_array[region_slice]
area = np.sum(region > 0)
perimeter = calculate_perimeter()
areas1.append(area)
perimeters1.append(perimeter)
print(f'sort areas, len:{len(areas1)}:\n{sorted(areas1)}')
return areas1, perimeters1