I would like to change a given block of the following image, and then rebuilding image back.
I would like to divide and change pixels from 224x224x3 blocks from such an image. As the image is 1024x1024x3, there will not be an integer number of 224x224x3 blocks, numpyso, I have to select a sub-area of the image to fit the block shape, like as follows:
>>> block_shape = np.array((224, 224, 3))
>>> nblocks = np.array(img.shape) // block_shape # integer division
>>> crop_r, crop_c, crop_ch = nblocks * block_shape
>>> cropped_img = img[:crop_r, :crop_c, :crop_ch]
The cropped image is, therefore, a sub-area of the image that will select non-overlapping blocks of 224x224x3 pixels
>>> cropped_img.shape
(896, 896, 3)
>>> Blocks = view_as_blocks(cropped_img, block_shape=(224, 224, 3))
>>> Blocks.shape
(4, 4, 1, 224, 224, 3)
Now, just suppose I want to change the pixels of a given block, like zeroing all pixels of the first block:
Blocks[0,0,:,:,:,:]=Blocks[0,0,:,:,:,:]*0
Now I have the blocks with one block changed. Then, I need to recover cropped_img with that block changed (by converting variable Blocks back to be only one image/NumPy array), and finally, save the image. How to do that in Python?
P.s= I checked a similar thread (
If you do need to unblock, you want to think of your blocks as nested lists, and use calls to np.concatenate
to concatenate the blocks on the leading axis along the remaining axes.
In this case, the leading axis is the rows of the blocks, and we want to concatenate along the rows of the remaining axes, which is axis 1:
intermediate = np.concatenate(blocked, axis=1)
print(intermediate.shape)
prints:
(2, 512, 256)
So we now have two "tall" blocks, and we want to concatenate them along the columns, which again will be axis 1 after ignoring the leading axis.
unblocked = np.concatenate(intermediate, axis=1)
fig, ax = plt.subplots()
ax.imshow(unblocked)
plt.show()
This shows the same image as above.
For your color image, the principle is the same, you just need to switch axis=1
for axis=2
.
CodePudding user response:
If you are willing to use Imagemagick directly (or call if using Python subprocess or do the same using Python Wand, which is based upon Imagemagick), it is very simple. Even non-full-sized tiles are kept appropriately.
Input:
convert man.jpg -crop 50x50% man_tile_d.png
This produces a 2x2 array of tiles labeled man_tile_00.png man_tile_01.png man_tile_02.png and man_tile_03.png
Then to build it back:
convert man_tile_*.png -background none -flatten man_tile_reconstitute.jpg