如何用Python高效精准计算三张图像间的面积差异对比?
问题描述
我有A、B、C三张图像,想要对比**(A与B的重叠面积占B的比例)和(C与B的重叠面积占B的比例)**之间的差异,目前的实现方法准确性较差,求更高效精准的Python实现方案。
当前实现代码
from PIL import Image from pycocotools import mask as coco_mask import pandas as pd, json, cv2, numpy as np, matplotlib.pyplot as plt, os A = r"/path/to/A" B = r"/path/to/B" C = r"/path/to/C" for a_path in os.listdir(A): for b_path in os.listdir(B): if b_path in a_path: a_image = Image.open(A + os.sep + a_path).convert('L') b_image = Image.open(B + os.sep + b_path).convert('L') a_array = np.array(a_image) b_array = np.array(b_image) overlap_array = np.bitwise_and(a_array, b_array) overlap_pixel_count = np.sum(overlap_array > 0) n_pixel_count = np.sum(b_array > 0) overlap_percentage = (overlap_pixel_count / n_pixel_count) * 100 print(overlap_percentage) else: pass for c_path in os.listdir(C): for b_path in os.listdir(B): if b_path in c_path: c_image = Image.open(bounding_boxes_path + os.sep + c_path).convert('L') # Convert to grayscale b_image = Image.open(segment_masks_path + os.sep + b_path).convert('L') # Convert to grayscale c_array = np.array(c_image) b_array = np.array(b_image) overlap_array = np.bitwise_and(c_array, b_array) overlap_pixel_count = np.sum(overlap_array > 0) n_pixel_count = np.sum(b_array > 0) overlap_percentage = (overlap_pixel_count / n_pixel_count) * 100 print(overlap_percentage) else: pass
图像说明
- A图:目标区域的检测框掩码图像
- B图:真实目标的分割掩码图像
- C图:另一组目标区域的检测框掩码图像
改进方案
原代码的问题
- 嵌套循环匹配文件,时间复杂度高(O(M*N)),且
b_path in a_path的匹配逻辑易出现误匹配 - 路径拼接用字符串+
os.sep,跨平台兼容性差且易出错 - 直接用
>0判断灰度图像素,若图像存在灰度过渡(非严格二值图),会导致计数不准确 - 重复代码过多,维护性差
- 存在未定义变量(
bounding_boxes_path、segment_masks_path)
优化后的实现
import os import numpy as np from PIL import Image def calculate_overlap_ratio(mask_path, target_mask_path): # 读取图像并转为灰度图 mask = np.array(Image.open(mask_path).convert('L')) target_mask = np.array(Image.open(target_mask_path).convert('L')) # 二值化处理:以127为阈值转为严格二值图(0/1),避免灰度干扰 mask_bin = (mask > 127).astype(np.uint8) target_bin = (target_mask > 127).astype(np.uint8) # 计算重叠像素数与目标掩码总像素数 overlap_pixels = np.sum(mask_bin & target_bin) target_total_pixels = np.sum(target_bin) # 避免除以0的异常 return (overlap_pixels / target_total_pixels) * 100 if target_total_pixels != 0 else 0.0 def get_file_path_map(root_dir): # 构建「文件名-文件路径」的映射字典,实现O(1)快速查找 return {os.path.basename(file): os.path.join(root_dir, file) for file in os.listdir(root_dir)} # 定义各目录路径 A_DIR = r"/path/to/A" B_DIR = r"/path/to/B" C_DIR = r"/path/to/C" # 预构建B目录的文件映射 b_file_map = get_file_path_map(B_DIR) # 计算A与B的重叠比例 print("A与B的重叠比例:") a_file_map = get_file_path_map(A_DIR) for filename, a_path in a_file_map.items(): if filename in b_file_map: ratio = calculate_overlap_ratio(a_path, b_file_map[filename]) print(f"{filename}: {ratio:.2f}%") # 计算C与B的重叠比例 print("\nC与B的重叠比例:") c_file_map = get_file_path_map(C_DIR) for filename, c_path in c_file_map.items(): if filename in b_file_map: ratio = calculate_overlap_ratio(c_path, b_file_map[filename]) print(f"{filename}: {ratio:.2f}%")
优化点说明
- 文件匹配优化:用字典构建文件名映射,匹配效率从O(M*N)降至O(1),匹配逻辑更精准
- 精准二值化:固定阈值将灰度图转为严格二值图,彻底解决灰度值干扰计数的问题
- 函数复用:将重叠比例计算逻辑封装为独立函数,减少重复代码,提升可维护性
- 路径规范:用
os.path.join处理路径,适配所有操作系统的路径分隔符 - 异常防护:增加目标掩码为空的判断,避免除以0的运行时错误
内容的提问来源于stack exchange,提问作者nikhil int
相关产品推荐
相关产品推荐

