I have six photographs. I changed them into block structure. Consider an image of size 200x200. 1. I converted into blocks of 10x10 so now I have 400 blocks in total each of siz
So, here's my approach to your problem. I rewrote parts of your code to get rid of all the lists, and solely working on NumPy arrays. Therefore, I store all images in a 4D array, and store all calculated "block means" in a 3D array. Finally, I use the found image_number
array to generate some kind of "index array" by using OpenCV's resize method with INTER_AREA interpolation flag ("resampling using pixel area relation"). In doing so, the generation of your final image can be done very easily using NumPy's boolean array indexing.
Let's have a look at the following code:
import cv2
import numpy as np
# Read images in one single 4D array; resize to [200, 200]
nImages = 3
images = np.zeros((200, 200, 3, nImages), np.uint8)
images[:, :, :, 0] = cv2.resize(cv2.imread('U2Gmz.png', cv2.IMREAD_COLOR), (200, 200))
images[:, :, :, 1] = cv2.resize(cv2.imread('OZxf3.png', cv2.IMREAD_COLOR), (200, 200))
images[:, :, :, 2] = cv2.resize(cv2.imread('aISEB.png', cv2.IMREAD_COLOR), (200, 200))
# Calculate block means and store in one single 3D array
means = np.zeros((20, 20, nImages), np.uint8)
for im in range(nImages):
arr = np.split(images[:, :, :, im], 20)
arr = np.array([np.split(x, 20, 1) for x in arr])
means[:, :, im] = np.reshape([arr[i][j].mean() for i in range(20) for j in range(20)], (20, 20))
# Determine block mean maximum over all images
result = np.max(means, axis=2)
# Determine index of block mean maximum over all images
image_number = np.argmax(means, axis=2)
print(image_number)
# Resize index array with "resampling using pixel area relation" to final image size
image_number_idx = cv2.resize(np.uint8(image_number), (200, 200), interpolation=cv2.INTER_AREA)
# Generate final image by boolean array indexing
final = np.zeros((200, 200, 3), np.uint8)
for im in range(nImages):
idx = image_number_idx == im
final[idx, :] = images[idx, :, im]
# Show images
cv2.imshow('image1', images[:, :, :, 0])
cv2.imshow('image2', images[:, :, :, 1])
cv2.imshow('image3', images[:, :, :, 2])
cv2.imshow('final', final)
cv2.waitKey(0)
cv2.destroyAllWindows()
These are the used images:
The image_number
output gives this:
[[0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0]
[1 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0]
[1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0]
[0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1]
[0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 0]
[0 0 0 0 0 0 0 2 1 1 1 2 0 0 0 0 0 1 0 0]
[0 0 0 0 0 0 0 2 1 0 0 2 2 2 0 0 0 1 1 0]
[0 0 0 0 0 2 2 2 1 0 2 2 2 2 0 0 0 1 1 0]
[0 0 0 0 0 2 2 2 0 0 0 0 2 2 2 0 0 0 0 0]
[0 0 0 0 2 2 2 2 0 0 0 0 2 2 2 2 0 0 0 0]
[0 0 0 0 2 0 2 2 0 0 0 0 2 0 0 0 0 0 0 0]
[1 1 0 0 0 2 2 0 0 2 2 0 0 2 0 0 0 0 0 0]
[1 1 0 0 2 2 2 0 2 2 2 2 1 2 2 2 2 0 2 1]
[1 0 0 0 0 2 2 2 2 0 2 2 2 2 2 2 0 1 1 1]
[1 1 1 0 0 2 2 2 1 1 1 2 2 2 2 0 0 1 1 0]
[1 1 1 1 1 1 1 1 1 1 1 2 0 0 1 0 0 0 0 0]
[1 1 1 1 1 1 0 1 1 1 1 1 0 2 0 0 0 0 0 0]
[1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
[1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0]
[0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1]]
And, the final image looks like this:
I hope, I understood your question correctly, and this is what you wanted to achieve.
My assumption is, that all input images have the same image dimensions, (200, 200)
here. Otherwise, I couldn't think of a way to manage potentially varying block sizes, if just the "grid", (20, 20)
here, is fixed.
Hope that helps!
EDIT: To read all jpg
files from the given folder, you might use:
files = glob.glob('resized/*.jpg')
# Read images in one single 4D array; resize to [200, 200]
nImages = len(files)
images = np.zeros((200, 200, 3, nImages), np.uint8)
for im in range(nImages):
images[:, :, :, im] = cv2.resize(cv2.imread(files[im], cv2.IMREAD_COLOR), (200, 200))
I consider you wonder to know how to merge two or more images. In python, when you load an image using opencv, it is stored in numpy arrays. So it is easy using numpy. Below is an example to merge two images. Firstly, load two images:
import cv2
import numpy as np
img1 = cv2.imread('pic1.png')
img2 = cv2.imread('pic2.png')
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
the two images are like:
Then to merge those two imgs:
# get the height and width of those pictures
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]
# define the height and width of the merged pictures
h, w = max(h1, h2), w1 + w2
img = np.zeros((h, w, 3), np.uint8)
# paste each img to the right place
img[0:h1, 0:w1] = img1
img[0:h2, w1:] = img2
cv2.imshow('img', img)
cv2.waitKey(0)
the result would be like: