C3W2A_Assignment Center Cropping

Hi Mentors,

I’m really struggling to do the centre crop using Pytorch transform functionality i.e transforms.CenterCrop(new_shape).

The issue is I keep getting the error TypeError: ‘builtin_function_or_method’ object is not iterable. which i think is because of either the input tensor shape.

Now from the PyTorch manual it says it accepts a batch of tensor of (B, C, H, W)` shape. But the error doesn’t seem to be the case. I also tried transforming ToPILImage first, then CenterCrop and transform back ToTensor. Any suggestion how to tackle this please? I can get it to work using example tensor (H,W) which suggest transform function doesn’t like B, C in the tensor inputs.

Thanks in Advance, Jason.

Extract from Transforming and augmenting images — Torchvision main documentation
“”
The transformations that accept tensor images also accept batches of tensor images. A Tensor Image is a tensor with (C, H, W) shape, where C is a number of channels, H and W are image height and width. A batch of Tensor Images is a tensor of (B, C, H, W) shape, where B is a number of images in the batch. “”

3 Likes

Hi @Jasonwtli,

Pytorch’s transforms.CenterCrop can take a PIL image or a tensor. And, if given a torch Tensor, it is expected to have […, H, W] shape, where … means an arbitrary number of leading dimensions and H, W being the dimensions of the image. Under the hood, it uses torchvision.transforms.functional — Torchvision 0.11.0 documentation.

Can you give an example of how you are using it?

1 Like

Hi Vin,

I tried 2 methods which errors out. although it likes [H,W] shape only.

  1. define a transform to crop the image at center

    transform = transforms.CenterCrop(new_shape)

    crop the image using above defined transform

    cropped_image = transform(image)

transform = transforms.Compose([
transforms.ToPILImage(), # converts the tensor to PIL image
transforms.CenterCrop(new_shape), # crops at center
transforms.ToTensor() # Converts to PyTorch Tensor
])

   cropped_image = transform(image)

Thanks, Jason.

1 Like

Your code seems correct. Is the image variable a tensor?

I created a gist which you can open it Google colab and try it out. Here is the link to the gist.

1 Like

Thanks Vinoth.

The assertion uses (B, C, H, W) shape for both image tensor and cropping size. I think there are 2 issues. The first is it seems CenterCrop uses (H,W) rather than (B,C,H,W) in the assertion. The second is more problematic.

It doesn’t like transform(x) in the notebook. But when I try the same code in your colab. It works with the following example code:

x = torch.randn(8,1,10,10)
y = torch.randn(5,5)

transform = torchvision.transforms.CenterCrop(y.size())
print(transform(x))

It there some versioning or environment differences? Seems your colab has python 3.7 whereas my notebook uses python 3.6

/usr/local/lib/python3.7/dist-packages/torchvision/transforms/transforms.py

/usr/local/lib/python3.6/dist-packages/torchvision/transforms/functional.py

Thanks, Jason.

1 Like

@vinothpandian, @Jasonwtli I also seem to face the same issue. For now, I found a tedious but working solution on the web.

middle_height = image.shape[2] // 2
middle_width = image.shape[3] // 2
starting_height = middle_height - new_shape[2] // 2
final_height = starting_height + new_shape[2]
starting_width = middle_width - new_shape[3] // 2
final_width = starting_width + new_shape[3]
cropped_image = image[:, :, starting_height:final_height, starting_width:final_width] 

And as @Jasonwtli pointed it out, I guess the issue arises due to some difference in the version of the packages or some environment differences!

2 Likes

Tks for this! It was holding me up.

Seems like python versioning issue. Will wait for @vinothpandian to confirm. Cheers, Jason.

1 Like

@vinothpandian. Have you had a chance to look into this please? Is the python3.6 version specific to our own PC or is the version set by the server as part of the exercise?

As I might have similar problems downstream for other parts of the exercise.

Tks, Jason.

1 Like

Hey @Jasonwtli,

I am sorry, I had some issues with accessing the course materials. I will get back to you by tomorrow!

I apologize for the inconvenience.

1 Like

@vinothpandian Tks Vinoth. It’s ok, its not holding me up.

Separately, I thought I’ll just mention another issue I’ve resolved. And no doubt there will be questions on it in the future so I might as well post solution.

In the expanding block dividing an integer i.e input_channels with a /2 or *0.5 would return a float. Think this is just how python works? So, I would need to cast it explicitly back to int() or use //2 in the code.

Thanks, Jason.

2 Likes

I ran into exactly the same issue. I also suspect it is an environment issue that was not tested. In fact, if look at the code here (see code below), it is supposed to work and yet it fails with exactly the same error message you and I ran into at the beginning, that is the par where it complains “TypeError: ‘builtin_function_or_method’ object is not iterable”.

import torch
from torchvision.transforms import RandomAffine, RandomRotation, CenterCrop, Resize

batch_size = 128
channels = 3
H = 224
W = 224

images = torch.rand((batch_size, channels, H, W))

images = images.to('cuda:0')

affine = RandomAffine(degrees=0., translate=(0.1,0.1))
rotate = RandomRotation(9)
center = CenterCrop((24,24))
resize = Resize((32,32))

images = affine(images)
images = rotate(images)
images = center(images)
images = resize(images)

print(images.size())

1 Like

Late to the party, but remember that you can always grab H, W using (new_shape[2], new_shape[3]).

1 Like

Yes, I tried with the code:

    import torchvision.transforms as transforms 
    transform = transforms.CenterCrop((new_shape[-2], new_shape[-1])) 
    cropped_image = transform(image)

It actually passes the unit tests (with a ‘Passed’ message), but it cannot pass the grader (Cell #5. Can’t compile the student’s code. Error: TypeError(“‘builtin_function_or_method’ object is not iterable”,).
p.s. (tried with just one shape, as soon as the image is a square) - the same error with a grader, but interestingly, I can train the U-Net, but cannot submit the assignment)

1 Like

Hi @Vasili_Reikh,

is new_shape a tensor or a numpy array?

1 Like

The new_shape is a torch.Size (not a tensor/ array)

1 Like
1. code: transform = transforms.CenterCrop((new_shape[-2], new_shape[-1]))  >> Passed unit tests, but training stops after 2 epochs. Grader failed.
2. code: transform = transforms.CenterCrop((new_shape[2], new_shape[3]))  >> Passed unit tests,  training stops after 198 epochs. Grader failed.
3. code: transform = transforms.CenterCrop(new_shape[3])  >> Passed unit tests,  training stops after 198 epochs. Grader failed.
#new_shape: a torch.Size object with the shape you want x to have
1 Like

Hi @Vasili_Reikh,

Thank you for the output, can you please share the line where you define new_shape?

1 Like

new_shape is a parameter(in the function # UNQ_C2 :
def crop(image, new_shape): …

1 Like

Hi @Vasili_Reikh,

This is calling new_shape. Can you please show where you define it?

1 Like

I just passed it as an argument (is it a problem?):
import torchvision.transforms as transforms
transform = transforms.CenterCrop((new_shape[-2], new_shape[-1]))
cropped_image = transform(image)

1 Like