|
|
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 |
|
|
|
|
|
|
|
|
if pred_end < pred_start or gt_end < gt_start: |
|
|
raise ValueError("End time cannot be before start time") |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
pred_duration = pred_end - pred_start |
|
|
gt_duration = gt_end - gt_start |
|
|
union = pred_duration + gt_duration - intersection |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
pred_indices, gt_indices = linear_sum_assignment(cost_matrix) |
|
|
|
|
|
|
|
|
matched_pairs = list(zip(pred_indices, gt_indices)) |
|
|
total_iou = -cost_matrix[pred_indices, gt_indices].sum() |
|
|
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): |
|
|
|
|
|
s1_mid = s1[1:-1] |
|
|
s2_mid = s2[1:-1] |
|
|
|
|
|
n = len(s1_mid) |
|
|
if n != len(s2_mid): |
|
|
return None |
|
|
|
|
|
|
|
|
start = 0 |
|
|
while start < n and s1_mid[start] == s2_mid[start]: |
|
|
start += 1 |
|
|
|
|
|
|
|
|
end = n - 1 |
|
|
while end >= start and s1_mid[end] == s2_mid[end]: |
|
|
end -= 1 |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
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): |
|
|
|
|
|
s1_mid = s1[1:-1] |
|
|
s2_mid = s2[1:-1] |
|
|
|
|
|
n = len(s1_mid) |
|
|
if n != len(s2_mid): |
|
|
return None |
|
|
|
|
|
|
|
|
start = 0 |
|
|
while start < n and s1_mid[start] == s2_mid[start]: |
|
|
start += 1 |
|
|
|
|
|
|
|
|
end = n - 1 |
|
|
while end >= start and s1_mid[end] == s2_mid[end]: |
|
|
end -= 1 |
|
|
|
|
|
|
|
|
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}") |
|
|
''' |