LSPW / utils /eval.py
fanduluhf's picture
Upload 4 files
f460dc5 verified
import numpy as np
from scipy.optimize import linear_sum_assignment
def temporal_iou(pred_span, gt_span):
"""
Calculate 1D Intersection over Union (IoU) between two temporal spans.
Args:
pred_span (tuple/list): Predicted temporal span (start, end)
gt_span (tuple/list): Ground truth temporal span (start, end)
Returns:
float: IoU score between 0 and 1
"""
pred_start, pred_end = pred_span
gt_start, gt_end = gt_span
# Ensure valid spans
if pred_end < pred_start or gt_end < gt_start:
raise ValueError("End time cannot be before start time")
# Calculate intersection
intersection_start = max(pred_start, gt_start)
intersection_end = min(pred_end, gt_end)
if intersection_end <= intersection_start:
return 0.0
intersection = intersection_end - intersection_start
# Calculate union
pred_duration = pred_end - pred_start
gt_duration = gt_end - gt_start
union = pred_duration + gt_duration - intersection
# Calculate IoU
iou = intersection / union
return float(iou)
def match_temporal_iou(preds, gts):
"""
Find optimal matching between predicted and ground truth temporal spans using Hungarian algorithm.
Args:
preds (list): List of predicted temporal spans, each span is [start, end]
gts (list): List of ground truth temporal spans, each span is [start, end]
Returns:
tuple: (matched_indices, total_iou)
- matched_indices: List of (pred_idx, gt_idx) pairs
- total_iou: Sum of IoUs for the matched pairs
"""
if not preds or not gts:
return [], 0.0
# Calculate cost matrix (negative IoU since Hungarian algorithm minimizes cost)
cost_matrix = np.zeros((len(preds), len(gts)))
for i, pred in enumerate(preds):
for j, gt in enumerate(gts):
cost_matrix[i, j] = -temporal_iou(pred, gt) # Negative since we want to maximize IoU
# Apply Hungarian algorithm
pred_indices, gt_indices = linear_sum_assignment(cost_matrix)
# Get matched pairs and total IoU
matched_pairs = list(zip(pred_indices, gt_indices))
total_iou = -cost_matrix[pred_indices, gt_indices].sum() # Convert back to positive
avg_iou = total_iou / len(gts)
return matched_pairs, avg_iou
'''
# Example usage:
if __name__ == "__main__":
# Example predictions and ground truths
predictions = [[10, 20], [25, 35], [40, 50], [50, 55]]
ground_truths = [[15, 25], [30, 40], [45, 55]]
# Find optimal matching
matches, avg_iou = match_temporal_iou(predictions, ground_truths)
print("Matched pairs (pred_idx, gt_idx):", matches)
print("Avg IoU:", avg_iou)
# Print individual IoUs for matched pairs
print("\nIndividual IoUs:")
for pred_idx, gt_idx in matches:
iou = temporal_iou(predictions[pred_idx], ground_truths[gt_idx])
print(f"Pred {pred_idx} - GT {gt_idx}: {iou:.3f}")
'''
def find_difference_range(s1, s2):
# Ignore first and last chars by slicing [1:-1]
s1_mid = s1[1:-1]
s2_mid = s2[1:-1]
n = len(s1_mid)
if n != len(s2_mid):
return None # Strings of different lengths
# Find start of difference
start = 0
while start < n and s1_mid[start] == s2_mid[start]:
start += 1
# Find end of difference (going backwards)
end = n - 1
while end >= start and s1_mid[end] == s2_mid[end]:
end -= 1
# Adjust indices to account for ignored first character
return [start + 1, end + 1] if start <= end else None
'''
# Test with your example
s1 = "GIBJBIGCHEHCGIBFAD-"
s2 = "GIBJBIGCHED----FADG"
result = find_difference_range(s1, s2)
print(f"Different substrings: '{s1[result[0]:result[1]+1]}' and '{s2[result[0]:result[1]+1]}'")
'''
def get_overlapping_substring(s1, s2, best_offset, max_matches):
len1 = len(s1)
len2 = len(s2)
start_index_s1 = -1
start_index_s2 = -1
for i in range(len1):
j = i - best_offset
if 0 <= j < len2 and s1[i] == s2[j]:
start_index_s1 = i
start_index_s2 = j
break # Find the first index of match
if start_index_s1 != -1:
return s1[start_index_s1 : start_index_s1 + max_matches]
else:
return ""
'''
string1 = 'JBHKHBJGCEID'
string2 = 'BJGCEIDIALFKCGJ'
best_offset, max_matches = align_strings(string1, string2)
overlapping_part = get_overlapping_substring(string1, string2, best_offset, max_matches)
print("String 1:", string1)
print("String 2:", string2)
print("\nOverlapping part:", overlapping_part)
'''
def find_difference_range(s1, s2):
# Ignore first and last chars by slicing [1:-1]
s1_mid = s1[1:-1]
s2_mid = s2[1:-1]
n = len(s1_mid)
if n != len(s2_mid):
return None # Strings of different lengths
# Find start of difference
start = 0
while start < n and s1_mid[start] == s2_mid[start]:
start += 1
# Find end of difference (going backwards)
end = n - 1
while end >= start and s1_mid[end] == s2_mid[end]:
end -= 1
# Adjust indices to account for ignored first character
return [start + 1, end + 1] if start <= end else None
'''
# Test with your example
s1 = "GIBJBIGCHEHCGIBFAD-"
s2 = "GIBJBIGCHED----FADG"
result = find_difference_range(s1, s2)
print(f"Different substrings: '{s1[result[0]:result[1]+1]}' and '{s2[result[0]:result[1]+1]}'")
print(f"Range index: {result}")
'''