Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ToTransform before Normalize causes Tensor no attribute astype Error #644

Closed
sarmientoj24 opened this issue Jun 12, 2020 · 11 comments
Closed

Comments

@sarmientoj24
Copy link

This is my albumentations transform. Before, this was Normalize --> ToTensor.
Changing the order (which I think is the right order) produces an error.

def get_transforms(phase, mean, std):
    list_transforms = []
    if phase == "train":
        list_transforms.extend(
            [
                HorizontalFlip(p=0.2),
                ShiftScaleRotate(
                    shift_limit=0,  # no resizing
                    scale_limit=0.1,
                    rotate_limit=10, # rotate
                    p=0.5,
                    border_mode=cv2.BORDER_CONSTANT
                )
                # albu.RandomRotate90(),
                # albu.Cutout(),
                # albu.RandomBrightnessContrast(
                #     brightness_limit=0.2, contrast_limit=0.2, p=0.3
                # ),
                # # albu.GridDistortion(p=0.3),
                # albu.HueSaturationValue(p=0.2),
                # albu.RandomContrast(p=0.2),
                # albu.MedianBlur(p=0.2)
                # Resize(320, 480),
            ]
        )
    list_transforms.extend(
        [
            ToTensor(),
            Normalize(mean=mean, std=std, p=1),
            
        ]
    )

    list_trfms = Compose(list_transforms)
    return list_trfms

When loading using DataLoader, it generates an error

     90     denominator = np.reciprocal(std, dtype=np.float32)
     91 
---> 92     img = img.astype(np.float32)
     93     img -= mean
     94     img *= denominator

AttributeError: 'Tensor' object has no attribute 'astype'
@ternaus
Copy link
Collaborator

ternaus commented Jun 13, 2020

This is the expected behavior.

Normalize expects numpy arrays, and ToTensor returns torch.Tensor

@ternaus ternaus closed this as completed Jun 13, 2020
@sarmientoj24
Copy link
Author

what should be done in order to do it?

@ternaus
Copy link
Collaborator

ternaus commented Jun 13, 2020

Can you apply ToTensor after Normalize ?

@sarmientoj24
Copy link
Author

Yes. But is that fine?

@sarmientoj24
Copy link
Author

sarmientoj24 commented Jun 13, 2020

Now I am having this error when I use ShiftScale Rotate

Error

error                                     Traceback (most recent call last)
<ipython-input-164-6ec0d9d0ef8e> in <module>()
      1 fake_loader = DataLoader(train_dataset, batch_size=1,
      2                           pin_memory=True, shuffle=True)
----> 3 batch = next(iter(fake_loader)) # get a batch from the dataloader
      4 images, masks = batch

10 frames
/usr/local/lib/python3.6/dist-packages/albumentations/augmentations/functional.py in shift_scale_rotate(img, angle, scale, dx, dy, interpolation, border_mode)
    143     matrix[0, 2] += dx * width
    144     matrix[1, 2] += dy * height
--> 145     img = cv2.warpAffine(img, matrix, (width, height), flags=interpolation, borderMode=border_mode)
    146     return img
    147 

error: OpenCV(4.1.2) /io/opencv/modules/imgproc/src/imgwarp.cpp:2594: error: (-215:Assertion failed) src.cols > 0 && src.rows > 0 in function 'warpAffine'

My DataLoader/Dataset

class DPWHDataset(Dataset):
  def __init__(self, mean=None, std=None, phase=None, dataset=None):
    self.data = dataset
    self.mean = mean
    self.std = std
    self.phase = phase
    self.transforms = get_transforms(phase, mean, std)
  
  def __len__(self):
    return len(self.data)

  def __getitem__(self, idx):
    image_name = self.data[idx]

    image_path = image_prefix + image_name + ".jpg"
    mask_path = binary_mask_prefix + image_name + "_mask.png"
    print(mask_path)

    mask = cv2.imread(mask_path, 0)

    # image = np.array(Image.open(image_path))
    # mask = np.array(Image.open(mask_path))
    image = cv2.imread(image_path)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    
    mask = create_channel_mask(mask)
    augmented = self.transforms(image=image, mask=mask)
    # image = augmented['image']
    # mask = augmented['mask']

    image = torchvision.transforms.ToTensor()(image)
    image = torchvision.transforms.Normalize(mean=self.mean, std=self.std)(image)
    mask = torchvision.transforms.ToTensor()(mask).permute(1, 2, 0)
    return image, mask

@Dipet
Copy link
Collaborator

Dipet commented Jun 13, 2020

Can you give reproducible example? Looks like mask or image is empty image.

@sarmientoj24
Copy link
Author

not really an empty image. how do i give reproducible example?

@Dipet
Copy link
Collaborator

Dipet commented Jun 13, 2020

This error indicates that your image has 0 height or width.

error: OpenCV(4.1.2) /io/opencv/modules/imgproc/src/imgwarp.cpp:2594: error: (-215:Assertion failed) src.cols > 0 && src.rows > 0 in function 'warpAffine'

We need sample code with image and mask on which you receive these errors.

@sarmientoj24
Copy link
Author

DataLoader

from PIL import Image
import torchvision

image_prefix = "/content/segmentation_dataset/new_img/"
color_mask_prefix = "/content/segmentation_dataset/new_color_mask/"
binary_mask_prefix = "/content/segmentation_dataset/mask/"


class DPWHDataset(Dataset):
  def __init__(self, mean=None, std=None, phase=None, dataset=None):
    self.data = dataset
    self.mean = mean
    self.std = std
    self.phase = phase
    self.transforms = get_transforms(phase, mean, std)
  
  def __len__(self):
    return len(self.data)

  def __getitem__(self, idx):
    image_name = self.data[idx]

    image_path = image_prefix + image_name + ".jpg"
    mask_path = binary_mask_prefix + image_name + "_mask.png"
    # print(mask_path)

    mask = cv2.imread(mask_path, 0)

    # image = np.array(Image.open(image_path))
    # mask = np.array(Image.open(mask_path))
    image = cv2.imread(image_path)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    
    mask = create_channel_mask(mask)

    augmented = self.transforms(image=image, mask=mask)
    image = augmented['image']
    mask = augmented['mask']

    image = torchvision.transforms.ToTensor()(image)
    image = torchvision.transforms.Normalize(mean=self.mean, std=self.std)(image)
    mask = torchvision.transforms.ToTensor()(mask).permute(1, 2, 0)
    return image, mask

Creator of n_channel_binary_mask

def create_channel_mask(mask):
  mask_palette = [1, 2, 3, 4, 5]
  final_mask = []
  for palette in mask_palette:
    new_mask = np.zeros((mask.shape[0], mask.shape[1]), dtype=np.float32)
    new_mask[mask == palette] = 1
    final_mask.append(new_mask)

  final_mask = np.asarray(final_mask)
  return final_mask

Albumentations

import albumentations as albu

def get_transforms(phase, mean, std):
    list_transforms = []
    if phase == "train":
        list_transforms.extend(
            [
                # HorizontalFlip(p=0.5),
                # ShiftScaleRotate(
                #     shift_limit=0,  # no resizing
                #     scale_limit=0.1,
                #     rotate_limit=10, # rotate
                #     p=0.8,
                #     border_mode=cv2.BORDER_CONSTANT
                # ),
                # # albu.RandomRotate90(),
                # albu.Cutout(),
                albu.RandomBrightnessContrast(
                    brightness_limit=0.2, contrast_limit=0.2, p=0.2
                ),
                # # albu.GridDistortion(p=0.3),
                albu.HueSaturationValue(p=0.2),
                albu.RandomContrast(p=0.2),
                albu.MedianBlur(p=0.2)
            ]
        )
    # list_transforms.extend(
    #     [
    #         Resize(600, 900, interpolation=cv2.INTER_NEAREST)
    #         # Normalize(mean=mean, std=std, p=1),
    #         # ToTensor(),
    #     ]
    # )

    list_trfms = Compose(list_transforms)
    return list_trfms

Sample Mask image
alligator10_color_mask

@sarmientoj24
Copy link
Author

sarmientoj24 commented Jun 13, 2020

Also, it seems like using flipping doesnt work on my mask properly
download (1)
download
It looks wrongly flipped

@Dipet
Copy link
Collaborator

Dipet commented Jun 13, 2020

Looks like all works fine

import requests
import matplotlib.pyplot as plt
import albumentations as A
import cv2
import numpy as np

response = requests.get("https://raw.githubusercontent.com/albumentations-team/albumentations_examples/master/notebooks/images/parrot.jpg")
img = cv2.imdecode(np.frombuffer(response.content, dtype=np.uint8), cv2.IMREAD_COLOR)
mask = np.zeros(img.shape[:2], dtype=np.float32)
mask[200:1000, 200:700] = 1

transforms = A.Compose([
    A.HorizontalFlip(p=1),
    A.ShiftScaleRotate(
        shift_limit=0,  # no resizing
        scale_limit=0.1,
        rotate_limit=10, # rotate
        p=1,
        border_mode=cv2.BORDER_CONSTANT
    ),
    A.RandomRotate90(p=1),
    A.Cutout(p=1),
    A.RandomBrightnessContrast(
        brightness_limit=0.2, contrast_limit=0.2, p=1
    ),
    A.GridDistortion(p=1),
    A.HueSaturationValue(p=1),
    A.RandomContrast(p=1),
    A.MedianBlur(p=1),
    A.Normalize(),
])

res = transforms(image=img, mask=mask)


plt.subplot(221)
plt.imshow(img)
plt.subplot(222)
plt.imshow(mask, cmap="gray")

plt.subplot(223)
plt.imshow(res["image"])
plt.subplot(224)
plt.imshow(res["mask"], cmap="gray")


plt.show()

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants