[英]How to calculate mean and standard deviation of a set of images
我想知道我要計算給定RGB
圖像數據集的mean
和std
。
例如,對於imagenet ,我們有imagenet_stats: ([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]
。
我試過了:
rgb_values = [np.mean(Image.open(img).getdata(), axis=0)/255 for img in imgs_path]
np.mean(rgb_values, axis=0)
np.std(rgb_values, axis=0)
我不確定我得到的值是否正確。
哪個可能是更好的實現?
第一個解決方案迭代圖像。 它比第二種解決方案慢得多,並且它使用相同數量的 memory因為它首先加載然后將所有圖像存儲在列表中。 所以它比第二種解決方案更糟糕,除非你改變你的圖像的加載方式——從光盤上一張一張地加載和處理它們。
第二種方案需要同時保存memory中的所有圖像。 它要快得多,因為它是完全矢量化的。
對於每個通道: R , G , B ,這里是如何計算所有圖像中所有像素的mean
s 和std
差:
每個圖像具有相同數量的像素。
如果不是這種情況 - 使用第二種解決方案(如下)。
images_rgb = [np.array(Image.open(img).getdata()) / 255. for img in imgs_path]
# Each image_rgb is of shape (n, 3),
# where n is the number of pixels in each image,
# and 3 are the channels: R, G, B.
means = []
for image_rgb in images_rgb:
means.append(np.mean(image_rgb, axis=0))
mu_rgb = np.mean(means, axis=0) # mu_rgb.shape == (3,)
variances = []
for image_rgb in images_rgb:
var = np.mean((image_rgb - mu_rgb) ** 2, axis=0)
variances.append(var)
std_rgb = np.sqrt(np.mean(variances, axis=0)) # std_rgb.shape == (3,)
...如果像這樣計算,並且如果一次使用所有像素計算, mean
和std
將相同:
假設每個圖像有n
像素(值為vals_i
),並且有m
個圖像。
然后有(n*m)
像素。
所有real_mean
中所有像素的vals_i
為:
total_sum = sum(vals_1) + sum(vals_2) + ... + sum(vals_m)
real_mean = total_sum / (n*m)
分別添加每個圖像的平均值:
sum_of_means = sum(vals_1) / m + sum(vals_2) / m + ... + sum(vals_m) / m
= (sum(vals_1) + sum(vals_2) + ... + sum(vals_m)) / m
現在, real_mean
和sum_of_means
之間的關系是什么? - 如你看到的,
real_mean = sum_of_means / n
類似地,使用標准偏差的公式,所有real_std
中所有像素的vals_i
為:
sum_of_square_diffs = sum(vals_1 - real_mean) ** 2
+ sum(vals_2 - real_mean) ** 2
+ ...
+ sum(vals_m - real_mean) ** 2
real_std = sqrt( total_sum / (n*m) )
如果從另一個角度看這個方程,你會發現real_std
基本上是m
個圖像中n
值的平均方差的平均值。
實際mean
和std
:
rng = np.random.default_rng(0)
vals = rng.integers(1, 100, size=100) # data
mu = np.mean(vals)
print(mu)
print(np.std(vals))
50.93 # real mean
28.048976808432776 # real standard deviation
將其與逐圖像方法進行比較:
n_images = 10
means = []
for subset in np.split(vals, n_images):
means.append(np.mean(subset))
new_mu = np.mean(means)
variances = []
for subset in np.split(vals, n_images):
var = np.mean((subset - mu) ** 2)
variances.append(var)
print(new_mu)
print(np.sqrt(np.mean(variances)))
50.92999999999999 # calculated mean
28.048976808432784 # calculated standard deviation
一次使用所有圖像的所有像素。
rgb_values = np.concatenate(
[Image.open(img).getdata() for img in imgs_path],
axis=0
) / 255.
# rgb_values.shape == (n, 3),
# where n is the total number of pixels in all images,
# and 3 are the 3 channels: R, G, B.
# Each value is in the interval [0; 1]
mu_rgb = np.mean(rgb_values, axis=0) # mu_rgb.shape == (3,)
std_rgb = np.std(rgb_values, axis=0) # std_rgb.shape == (3,)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.