-3

I have a Numpy Array type image which I would like to split into 9 (3 x 3) even tiles which I can iterate over. How can I do this?

Here is my code so far to generate the numpy.ndarray but I haven't managed to split it:

The numpy image array to split is th1

import cv2
import numpy as np

# Only for the threshold display
from matplotlib import pyplot as plt

# The Image to be used
image = 'six.png'

# Finding the average greyscale value
image_bgr = cv2.imread(image, cv2.IMREAD_COLOR)

# Calculate the mean of each channel
channels = cv2.mean(image_bgr)
# Type Float
thresh = channels[0]/2
#print (thresh)

# Displaying the threshold value
img = cv2.imread(image,0)
img = cv2.medianBlur(img,5)

# If below then black else white 
ret,th1 = cv2.threshold(img,thresh,255,cv2.THRESH_BINARY)


titles = ['Original Image', 'Global Thresholding']
images = [img, th1, ret]

for i in range(2):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])

# Shows single image on its' own
plt.imshow(images[1], 'gray')
plt.xticks([]),plt.yticks([])

Here is the image (six.png):

edited image named six.png

David
  • 139
  • 1
  • 1
  • 12
Aiyush
  • 170
  • 13

2 Answers2

2

What I would do is create a list or a 2-dimensional array in which I'd save the "tiles" of the full image. The tiles would be copied using the code below:

height, width, dim = img.shape
image_tile = img[0:height/3, 0:width/3]

It creates a new ndarray image_tile that contains the part of the full image array that's inside of the coordinates. In this case it is the top left tile.

The whole example with a for loop would look something like this:

image_tile = []
for i in range(0,3):
    for j in range(0,3):
        image_tile.append(img[i * height/3:(i+1) * height/3, j * width/3:(j+1) * width/3])

I hope this helps and good luck!

  • Hi @Grgur, could you explain this a little more. Ie. how would I do this with my specific case and cutting it into the 9 tiles. I am quite new to this area of python so more code would really be useful. Cheers – Aiyush Jan 04 '21 at 12:04
  • I didn't get what exactly you meant with your question when I was answering so I didn't put a detailed example. Do you want to resize the image so each tile has dimensions 3x3, do you just want to have 9 arrays of equal size? – Grgur Damiani Jan 04 '21 at 12:16
  • he's asking for a complete calculation of those slice bounds, for all nine regions. – Christoph Rackwitz Jan 04 '21 at 12:19
  • I see you uploaded an answer. I feel like you achieve the same result in fewer lines. Could you try it and tell me if it works? Thank you! – Grgur Damiani Jan 04 '21 at 12:42
  • @GrgurDamiani thanks again! I tried it, however, I received the error: height, width, dim = img.shape ValueError: not enough values to unpack (expected 3, got 2). `img = th1 height, width, dim = img.shape image_tile = [] for i in range(0,3): for j in range(0,3): image_tile.append(img[i * height/3:(i+1) * height/3, j * width/3:(j+1) * width/3]) plt.imshow(image_tile, 'gray') plt.show()` – Aiyush Jan 05 '21 at 07:58
  • @GrgurDamiani could you send a pastebin file or something alike where you have this working in a .py file with minimal reproducible code so that I can see better how it works? – Aiyush Jan 05 '21 at 07:58
  • I think your image is 2-dimensional, so you should just remove the dim part from that – Grgur Damiani Jan 06 '21 at 16:11
1

I have found a solution adapted from elsewhere and it works great!

img = th1
numrows, numcols = 3, 3
height = int(img.shape[0] / numrows)
width = int(img.shape[1] / numcols)
for row in range(numrows):
    for col in range(numcols):
        y0 = row * height
        y1 = y0 + height
        x0 = col * width
        x1 = x0 + width
        individual =  (img[y0:y1, x0:x1])
        plt.imshow(individual, 'gray')
        plt.xticks([]),plt.yticks([])
        plt.show()
Aiyush
  • 170
  • 13
  • You aren't making any provision for image sizes that are not evenly divided by your blocks - just a comment - it is OK as long as you realize that and it suits your needs. In this case you are *not processing* 2 pixels along the *right* edge. – wwii Jan 04 '21 at 22:17