Reputation: 45
My goal is to take the average of 200+ images, and then find the standard deviation of said average. Ask the user for a threshold and then compare the threshold to the standard deviation. If the threshold is < the standard deviation for that particular pixel, change it to red [255,0,0]. My issue lies with taking the standard deviation of a pixel. Any help would be appreciated.
allimg = []
avg_img=[]
path = glob.glob('podatlamar/*.jpg')
for x in path:
img = Image.open(x)
img = np.float32(img)
allimg.append(img)
avg_img = np.average(allimg, axis=0)
std = [0,0,0]
for img in allimg :
std += (img-avg_img) ** 2
std = np.sqrt(std / (len(allimg) - 1))
now:
for i in range(0, len(std)): #i is row
for j in range(0, len(std[i])): #j is column
if(std[i][j] > float(threshold)).any :
avg_img[i][j] = [255.0, 0.0, 0.0]
avg_img = np.clip(avg_img, 0, 255)
etc...
and the result is all pixels are made red
and here is the for loop debugging in action
[The avg_img being changed to 255,0,0
Snippet of what std looks like
[[0.19792126 0.05137325 0.03966657]
[0.09997863 0.06348856 0.07472634]
[0.0367469 0.18667144 0.21834356]
...
[0.02421235 0.02454335 0.14083997]
[0.02319027 0.02351524 0.13969136]
[0.02285284 0.02317629 0.13930877]]
[[0.03304812 0.06428259 0.04262938]
[0.0978733 0.02841616 0.04049174]
[0.09566899 0.02877731 0.0357872 ]
...
[0.08500231 0.03502595 0.12032651]
[0.08347222 0.03630779 0.1217759 ]
[0.08385488 0.03598539 0.12141356]]
Upvotes: 1
Views: 4025
Reputation: 207445
As you have not provided any input data, I used the individual frames of this animation as my 18 input frames to average across:
I extracted them using ImageMagick:
magick animation.gif -coalesce frame-%02d.jpg
The code I came up with looks like this:
#!/usr/bin/env python3
import glob
import numpy as np
from PIL import Image
# Generate list of image names
names = glob.glob('frame-*.jpg')
# Load all images into list
images = []
for filename in names:
im = Image.open(filename)
images.append(np.array(im))
# Generate average image, where each pixel is the average of that pixel position across all images
average = np.mean(images, axis=0)
Image.fromarray(average.astype(np.uint8)).save('tmp-average.png') # DEBUG
# Generate stdev image, where each pixel is the stdev of that pixel position across all images
stdev = np.std(images, axis=0)
Image.fromarray(stdev.astype(np.uint8)).save('tmp-stdev.png') # DEBUG
threshold = 80
average[np.any(stdev>threshold, axis=2)] = [255,0,0]
Image.fromarray(average.astype(np.uint8)).save(f'result.png')
And the result is this:
Just for fun, I made a little animation of the effect of setting the threshold differently:
Upvotes: 3