Skip to content

Commit

Permalink
🐞 fix(Smeasure中的质心计算): 原始实现在输入过大时会溢出
Browse files Browse the repository at this point in the history
原本直接基于np.sum()的实现在输入尺寸过大的时候会出现数值溢出。现在基于np.argwhere()的实现方式则避免了这一问题。

关于质心计算的更多细节可见文档:https://www.yuque.com/lart/blog/gpbigm
  • Loading branch information
lartpang committed Aug 22, 2022
1 parent 4aa253a commit b733575
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 31 deletions.
54 changes: 31 additions & 23 deletions examples/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
# @GitHub : https://github.com/lartpang

import os
import sys
from pprint import pprint

import cv2
from tqdm import tqdm

# pip install pysodmetrics
sys.path.append("..")
from py_sod_metrics import MAE, Emeasure, Fmeasure, Smeasure, WeightedFmeasure

FM = Fmeasure()
Expand All @@ -21,7 +22,8 @@
mask_root = os.path.join(data_root, "masks")
pred_root = os.path.join(data_root, "preds")
mask_name_list = sorted(os.listdir(mask_root))
for mask_name in tqdm(mask_name_list, total=len(mask_name_list)):
for i, mask_name in enumerate(mask_name_list):
print(f"[{i}] Processing {mask_name}...")
mask_path = os.path.join(mask_root, mask_name)
pred_path = os.path.join(pred_root, mask_name)
mask = cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE)
Expand Down Expand Up @@ -50,24 +52,30 @@
"maxFm": fm["curve"].max(),
}

print(results)
# 'Smeasure': 0.9029763868504661,
# 'wFmeasure': 0.5579812753638986,
# 'MAE': 0.03705558476661653,
# 'adpEm': 0.9408760066970631,
# 'meanEm': 0.9566258293508715,
# 'maxEm': 0.966954482892271,
# 'adpFm': 0.5816750824038355,
# 'meanFm': 0.577051059518767,
# 'maxFm': 0.5886784581120638
default_results = {
"v1_2_3": {
"Smeasure": 0.9029763868504661,
"wFmeasure": 0.5579812753638986,
"MAE": 0.03705558476661653,
"adpEm": 0.9408760066970631,
"meanEm": 0.9566258293508715,
"maxEm": 0.966954482892271,
"adpFm": 0.5816750824038355,
"meanFm": 0.577051059518767,
"maxFm": 0.5886784581120638,
},
"v1_3_0": {
"Smeasure": 0.9029761578759272,
"wFmeasure": 0.5579812753638986,
"MAE": 0.03705558476661653,
"adpEm": 0.9408760066970617,
"meanEm": 0.9566258293508704,
"maxEm": 0.9669544828922699,
"adpFm": 0.5816750824038355,
"meanFm": 0.577051059518767,
"maxFm": 0.5886784581120638,
},
}

# version 1.2.3
# 'Smeasure': 0.9029763868504661,
# 'wFmeasure': 0.5579812753638986,
# 'MAE': 0.03705558476661653,
# 'adpEm': 0.9408760066970631,
# 'meanEm': 0.9566258293508715,
# 'maxEm': 0.966954482892271,
# 'adpFm': 0.5816750824038355,
# 'meanFm': 0.577051059518767,
# 'maxFm': 0.5886784581120638
pprint(results)
pprint({k: default_value - results[k] for k, default_value in default_results["v1_3_0"].items()})
12 changes: 5 additions & 7 deletions py_sod_metrics/sod_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,19 +266,17 @@ def centroid(self, matrix: np.ndarray) -> tuple:
so there is no need to use the redundant addition operation when dividing the region later,
because the sequence generated by ``1:X`` in matlab will contain ``X``.
:param matrix: a data array
:param matrix: a bool data array
:return: the centroid coordinate
"""
h, w = matrix.shape
if matrix.sum() == 0:
area_object = np.count_nonzero(matrix)
if area_object == 0:
x = np.round(w / 2)
y = np.round(h / 2)
else:
area_object = np.sum(matrix)
row_ids = np.arange(h)
col_ids = np.arange(w)
x = np.round(np.sum(np.sum(matrix, axis=0) * col_ids) / area_object)
y = np.round(np.sum(np.sum(matrix, axis=1) * row_ids) / area_object)
# More details can be found at: https://www.yuque.com/lart/blog/gpbigm
y, x = np.argwhere(matrix).mean(axis=0).round()
return int(x) + 1, int(y) + 1

def divide_with_xy(self, pred: np.ndarray, gt: np.ndarray, x: int, y: int) -> dict:
Expand Down
2 changes: 1 addition & 1 deletion version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.3.0
1.3.1

0 comments on commit b733575

Please sign in to comment.