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))