1

I have this func that splits my initial img into arrays of 100x100

def blockshaped(arr, nrows, ncols):
    h, w = arr.shape
    return (arr.reshape(h//nrows, nrows, -1, ncols)
               .swapaxes(1,2)
               .reshape(-1, nrows, ncols))

Then this loop makes a new_img filled with arrays of zeros if enumerate == even, and block if is not

image = np.full((1000,2000),5)
blocks = blockshaped(image,100,100)

new_image = []
for i,block in enumerate(blocks):
    if i%2==0:
        new_image.append(np.zeros((100,100)))
    else:
        new_image.append(block)

Now I dont know how can I build a final image 1000x2000 filled with my new_image arrays.

Any idea???

0

2 Answers 2

1

You can just invert the steps you apply in blockshaped() to achieve this. Note that I renamed some of your variables to make the descriptions shorter.


import numpy as np

def blockshaped(arr, nrows, ncols):
    r, c = arr.shape                                       #    (r, c)
    return (arr.reshape(r//nrows, nrows, c//ncols, ncols)  # -> (r/n, n, c/m, m)
               .swapaxes(1, 2)                             # -> (r/n,  c/m, n, m)
               .reshape(-1, nrows, ncols))                 # -> (r/n * c/m, n, m)

r, c = 1000, 2000
n, m = 100, 100
image = np.full((r, c), 5)
blocks = blockshaped(image, nrows=n, ncols=m)

# Create new empty image and only fill in the even blocks
new_image = np.zeros((len(blocks), n, m))
new_image[::2] = blocks[::2]
# new_image[1::2] = np.full((n, m), 13)  # do something odd if you want

# reverse blockshaped                              #    (r/n * c/m, n, m)
new_image = (new_image.reshape(r//n, c//m, n,  m)  # -> (r/n,  c/m, n, m)
                      .swapaxes(1, 2)              # -> (r/n, n, c/m, m)
                      .reshape(image.shape))       # -> (r, c)

import matplotlib.pyplot as plt
plt.imshow(new_image)

Stripped Image of Blocks

Sign up to request clarification or add additional context in comments.

1 Comment

it works fine, but it was my fault I placed the example of ever or odd just to not complicate too much the code, in fact depending of a condition, the block can be zeros or not, So I end with an arr that contain some original blocks and some zero blocks. And I am confused when I want to join all this blocks.
0

You have created 200 number of 100 x 100 array using

image = np.full((1000, 2000), 5)
blocks = block_shaped(image, 100, 100)

Then you want to fill the new array with the block values if counter is odd number.

new_image = []
for i,block in enumerate(blocks):
    if i%2==0:
        new_image.append(np.zeros((100,100)))
    else:
        new_image.append(block)
  • Instead of initializing new_image as an empty list, initialize as a numpy zeros array. The problem is what is the shape of the new_image?

The answer depends.

  • If you want each row to be the blocks value, then you need to declare the size:

    • new_image = np.zeros(shape=(2000, 10000))
      
    • Since each block is 100 x 100 = 10000 and the size of block is 200 x 100 x 100. We place each row block value, for instance new_image[0, 10000] = block.

    • import numpy as np
      from PIL import Image
      
      
      def block_shaped(arr, n_rows, n_cols):
           h, w = arr.shape
           return (arr.reshape(h//n_rows, n_rows, -1, n_cols).swapaxes(1, 2).reshape(-1, n_rows, n_cols))
      
      
      image = np.full((1000, 2000), 5)
      blocks = block_shaped(image, 100, 100)
      
      new_image = np.zeros(shape=(2000, 10000), dtype=np.uint8)
      
      for i, block in enumerate(blocks):
           if i % 2 != 0:
               new_image[i, :] = block.flatten()
      
      new_image = Image.fromarray(new_image)
      new_image.show()       
      
    • Result will be a blank image, but if you change image = np.full((1000, 2000), 5) to image = np.full((1000, 2000), 155). Then the result will be:

      • enter image description here

      • Upper part becomes gray.

  • If you want to set only (100, 100) parts of the image to the block for each odd i:

    • import numpy as np
      from PIL import Image
      
      
      def block_shaped(arr, n_rows, n_cols):
          h, w = arr.shape
          return (arr.reshape(h//n_rows, n_rows, -1, n_cols).swapaxes(1, 2).reshape(-1, n_rows, n_cols))
      
      
      image = np.full((1000, 2000), 155)
      blocks = block_shaped(image, 100, 100)
      
      new_image = np.zeros(shape=(1000, 2000), dtype=np.uint8)
      
      for i, block in enumerate(blocks):
          if i % 2 != 0:
              new_image[i:100+i, i:100+i] = block
      
      new_image = Image.fromarray(new_image)
      new_image.show()
      
    • Result:

      • enter image description here

1 Comment

Thanks for the answer, I think I have explain the problen wrong. 1.- I have an image (2000x1000) 2.- I split this img in sections of (100x100) total =200 blocks 3.- I loop all blocks and depending of a condition the block is left untouched, or is transformed into np.zeros 4,.- I end with a arr with some blocks untoched and some blocks with zeros. 5.- All this 4 steps are achived, but now I am confused about how can I rejoin all these blocks in a 2000x1000 img Thanks for your time!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.