You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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图:另一组目标区域的检测框掩码图像
改进方案

原代码的问题

  1. 嵌套循环匹配文件,时间复杂度高(O(M*N)),且b_path in a_path的匹配逻辑易出现误匹配
  2. 路径拼接用字符串+os.sep,跨平台兼容性差且易出错
  3. 直接用>0判断灰度图像素,若图像存在灰度过渡(非严格二值图),会导致计数不准确
  4. 重复代码过多,维护性差
  5. 存在未定义变量(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}%")

优化点说明

  1. 文件匹配优化:用字典构建文件名映射,匹配效率从O(M*N)降至O(1),匹配逻辑更精准
  2. 精准二值化:固定阈值将灰度图转为严格二值图,彻底解决灰度值干扰计数的问题
  3. 函数复用:将重叠比例计算逻辑封装为独立函数,减少重复代码,提升可维护性
  4. 路径规范:用os.path.join处理路径,适配所有操作系统的路径分隔符
  5. 异常防护:增加目标掩码为空的判断,避免除以0的运行时错误

内容的提问来源于stack exchange,提问作者nikhil int

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 10:05:59