我正在使用示例图像序列测试背景减法算法。我想知道如何在给定基本事实的情况下评估背景减法算法结果的准确性?
我现在唯一想到的想法是获取结果图像与其对应的地面实况图像之间的差异并计算差异/total_white_pixels_of(ground_truth)。
干杯!
编辑:亲爱的,我所说的地面实况图像是指前景为白色斑点,背景为黑色像素的二进制图像。这是输入图像及其基本事实的示例:
我正在使用示例图像序列测试背景减法算法。我想知道如何在给定基本事实的情况下评估背景减法算法结果的准确性?
我现在唯一想到的想法是获取结果图像与其对应的地面实况图像之间的差异并计算差异/total_white_pixels_of(ground_truth)。
干杯!
编辑:亲爱的,我所说的地面实况图像是指前景为白色斑点,背景为黑色像素的二进制图像。这是输入图像及其基本事实的示例:
一种方法是创建一个简单的信噪比估计,使用像素强度和地面实况图像作为掩码。这是我在 Python 中的意思的一个例子:
import numpy as np
# Sample data
# Indices [0, 1, 2, 6] are background, [3, 4, 5] are object
original = np.array([1, 2, 2, 5, 6, 8, 2])
truth = np.array([0, 0, 0, 1, 1, 1, 0])
back_mask = 1 - truth
result = np.array([0, 1, 0, 4, 5, 7, 1]) # Result of background subtraction
def non_masked_mean(input_array, mask):
"""mean of non-masked elements in the array"""
return np.ma.masked_array(input_array, mask).mean()
def snr(input_array, back_mask):
"""ratio of non-masked to masked mean intensities"""
with np.errstate(all='ignore'):
snr = non_masked_mean(input_array, back_mask) / non_masked_mean(input_array, (1-back_mask))
return 0 if np.isnan(snr) else snr
snr_before = snr(original, back_mask) # (mean of objects / mean of background), before
snr_after = snr(result, back_mask) # (mean of objects / mean of background), after
snr_ratio = snr_after / snr_before
if snr_after == np.inf:
print "Perfect SNR in result! Either great or suspect..."
elif snr_after == 0:
print "Image was flattened :("
else:
print "SNR changed by a multiple of %.2f" % (snr_ratio)
这样做的问题是,您通过偏爱严厉的背景减法获得了完美的分数。即使对象只有 1 个像素幸存,此 SNR 也将是无限的。另一种方法是分别考虑背景和信号,并对两者的结果进行加权。然后,您可以决定是否更重要的是展平背景,还是保留原件。
def non_masked_mean_ratio(input_array, result_array, mask):
"""ratio of two array means, with the same mask"""
return non_masked_mean(result_array, mask) / non_masked_mean(input_array, mask)
signal_ratio = non_masked_mean_ratio(original, result, back_mask) # (mean of objects after) / (mean of objects before)
background_ratio = non_masked_mean_ratio(original, result, truth) # (mean of background after) / (mean of background before)
weight = 0.5 # Higher weight favours preservation of objects
score = (weight*signal_ratio) + ((1-weight) * (1-background_ratio))
这为分数提供了大约 0-1 的良好预期范围,其中 1 是理想的结果。但它并不完美,因为您可以通过增加对象的强度来增强它。
如果您期望二进制结果,您可以使用类似的策略,除了使用非零像素数而不是平均值:
def nonzero_count_ratio(result_array, ideal_array):
"""ratio of actual number of non-zero pixels vs ideal non-zero pixels"""
return float(np.count_nonzero(result_array*ideal_array)) / np.count_nonzero(ideal_array)
true_obj_ratio = nonzero_count_ratio(result, truth) # Number of correct object pixels vs number of potential correct
false_back_ratio = nonzero_count_ratio(result, back_mask) # Number of false background pixels vs number of potential false
weight = 0.5
score = (weight*true_obj_ratio) + ((1-weight) * (1-false_back_ratio))