Reputation: 4245
I have two images that will be identical in dimensions.
The images are numpy arrays and I am itterating the pixels and aquiring the r
g
b
of each pixel like this:
for i in range(len(img1)):
for j in range(len(img1[0])):
pimg1 = img1[i][j]
pimg2 = img2[i][j]
r1 = pimg1[0]
r2 = pimg2[0]
g1 = pimg1[1]
g2 = pimg2[1]
b1 = pimg1[2]
b2 = pimg2[2]
I then acquire the MSE between the two pixels like:
mse = math.sqrt(((r1 - r2) ** 2) + ((g1 - g2) ** 2) + ((b1 - b2) ** 2))
The problem is this is ridiculously slow. Is there a more efficient way to do this?
I am looking to make all pixels that have a certain "thresholded" similarity, between the two images, black. And all pixels that have a larger difference the pixel of img2
.
if mse > threshold:
new_img[i][j] = pimg2
else:
new_img[i][j] = [0, 0, 0] # black pixel
I am capturing images like:
for frame in cam.camera.capture_continuous(raw, format="rgb", use_video_port=True):
img = frame.array
cv2.imwrite("image.png", img)
I am getting the images like:
dir = 'images/compare/'
bg = cv2.imread(dir+'bg.png')
img = cv2.imread(dir+'in.png')
Upvotes: 3
Views: 4546
Reputation: 221534
Simply use np.linalg.norm
on the differences -
mse = np.linalg.norm(img1-img2,axis=2)
Faster one with np.einsum
-
d = (img1-img2).astype(float)
mse = np.sqrt(np.einsum('...i,...i->...',d,d))
Runtime test -
In [46]: np.random.seed(0)
...: m,n = 1024,1024
...: img1 = np.random.randint(0,255,(m,n,3)).astype(np.uint8)
...: img2 = np.random.randint(0,255,(m,n,3)).astype(np.uint8)
In [47]: %timeit np.linalg.norm(img1-img2,axis=2)
10 loops, best of 3: 26.6 ms per loop
In [49]: %%timeit
...: d = (img1-img2).astype(float)
...: mse = np.sqrt(np.einsum('...i,...i->...',d,d))
100 loops, best of 3: 13 ms per loop
To create an output array that is set to black
for pixels that have MSE
values lesser than a certain threshold mse_thresh
and select from img2
otherwise, here are the additional codes -
mask = mse >= mse_thresh
out = np.where(mask[...,None], img2, 0)
Stitching everything together - Using einsum
to compute squared MSE
values and comparing against the squared MSE threshold for major improvement and assigning back the output into img2
-
d = (img1-img2).astype(float)
mse = np.einsum('...i,...i->...',d,d)
img2[mse < mse_thresh**2] = 0
Upvotes: 5