Compare multiple images based on pixel values

Viewed 1759

Hi I am trying to compare a set of images where I want to produce a final image with maximum pixels from each individual image. Say I have 3 images (converted to 10x10 matrix) in which I know the pixel values of each block> Now I want to compare these values block by block and produce a final separate image with maximum block values from each image.

To do so I have changed the image dimensions(250x250) such that each block is a square of 25x25

I even tried comparing two images and taking the maximum pixels from both the images and displaying them

image = cv2.resize(im,(250,250))
hs,ws,c= image.shape
print(hs, ws,c)
hs = round(h/10)
ws = round(w/10)
resized = cv2.resize(image, (ws,hs), interpolation = cv2.INTER_AREA)
cv2.imshow("Resized image", resized)
cv2.waitKey(0)
cv2.destroyAllWindows()

print(list(resized))
#comparing two images
data = np.maximum.reduce([resized,resized1])
from matplotlib import pyplot as plt
plt.imshow(data, interpolation='nearest')
plt.show()

So these are two images and the tiled image is the result of the block #comparing two images. Now using these two images I want to produce a final image similar to the original photos not the tiled version but the final photo should have pixels from both original photos(maximum from each). I hope it clears the question

2 Answers

For better visualization purposes, I skip the whole resizing part you got earlier, and stick to resized (250 x 250) images.

My approach is the following: Store all your resized images in some NumPy array with dimensions (width x height x numberOfChannels x numberOfImages), and then use NumPy's max along axis=3, such that you get a final image (width x height x numberOfChannels) with maximum BGR values (or grayscale, if desired) over all images.

Here's some exemplary code:

import cv2
import numpy as np

# Set up empty images array
width, height, nChannels, nImages = (250, 250, 3, 3)
images = np.zeros((width, height, nChannels, nImages), np.uint8)

# Read and resize exemplary input images
images[:, :, :, 0] = cv2.resize(cv2.imread('WeQow.png'), (width, height))
images[:, :, :, 1] = cv2.resize(cv2.imread('gIHOd.png'), (width, height))
images[:, :, :, 2] = cv2.resize(cv2.imread('lAdfO.jpg'), (width, height))

# Generate maximum image along last axis, i.e. the images.
# For each BGR value you get the maximum over all images.
image = images.max(axis=3)

# Show images
cv2.imshow('image0', images[:, :, :, 0])
cv2.imshow('image1', images[:, :, :, 1])
cv2.imshow('image2', images[:, :, :, 2])
cv2.imshow('image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

These are the three input images:

Input 1

Input 2

Input 3

The final output image then looks like this:

Output

Hope that helps!

You can try using block_reduce function with block size (no_of_images, channels, block_height, block_width).

skimage.measure.block_reduce(np.asarray([image1, image2, image3,...]), (no_of_images, channels, 1, 1), np.max)

If your input images are in RGB scale and you want per-channel max value (output also RGB image) among images just replace channels value with 1 or if you want max value across channels among the images then use 3 as channels value that will generate a gray scale image.

Related