Transform dataset to local binary pattern

Hello guys

Here is my local binary pattern function:

def lbp(x):

imgUMat = np.float32(x)

gray = cv2.cvtColor(imgUMat, cv2.COLOR_RGB2GRAY)

radius = 2
n_points = 8 * radius

METHOD = 'uniform'
    
lbp = local_binary_pattern(gray, n_points, radius, METHOD)
lbp = torch.from_numpy(lbp).long()
    
return lbp

Here I call lbp function:

input_img = plt.imread(trn_fnames[31])
x = lbp(input_img)

When I use x.shape it is:

torch.Size([600, 600])
Sounds good!!!

But my problem is when I use transforms.Lambda(lbp) in my transform function, my output image is torch.Size([600])

tfms = transforms.Compose([

transforms.Lambda(lbp)])

train_ds = datasets.ImageFolder(trn_dir, transform = tfms)

(train_ds[0][0][0]).shape
torch.Size([600])!!! >>>> my problem

I need torch.Size([600, 600])

I also different ways such as this:

tfms = transforms.Compose([

transforms.Lambda(lbp),
transforms.ToPILImage(),
transforms.Resize((sz, sz))])

And I got this error:

TypeError: pic should be Tensor or ndarray. Got <class ā€˜torch.Tensorā€™>.

I also added

transforms.ToTensor()])

But still have the same error:

TypeError: pic should be Tensor or ndarray. Got <class ā€˜torch.Tensorā€™>.

Iā€™ll appreciate to your comments please!
Thank you.

Hi @ptrblck
As always I hope you have some answers for me!
You are a Hero in this website :slight_smile:

The code seems to work correctly.
This code snippet applies the transformation only:

def lbp_transform(x):
    imgUMat = np.float32(x)
    lbp = imgUMat * 10 # fake transformation
    lbp = torch.from_numpy(lbp)
    return lbp

x = np.random.randn(600, 600)
out = lbp_transform(x)
print(out.shape)
> torch.Size([600, 600])

while this snippet wraps it in a torchvision.transforms.Compose object:

tfms = transforms.Compose([
    transforms.Lambda(lbp_transform),
    transforms.ToPILImage(),
    transforms.Resize((300, 300)),
    transforms.ToTensor()
])

out = tfms(x)
print(out.shape)
> torch.Size([1, 300, 300])

Are you sure this indexing is correct and you are not in fact indexing into the height dimension?

(train_ds[0][0][0]).shape
1 Like

Thanks @ptrblck
Your codes work correct but the problem is when I add Local Binary Pattern part in lbp_transfer function I get the error:

from skimage.feature import local_binary_pattern

def lbp_transform(x):

radius = 2
n_points = 8 * radius
METHOD = 'uniform'
imgUMat = np.float32(x)
gray = cv2.cvtColor(imgUMat, cv2.COLOR_RGB2GRAY)

**lbp = local_binary_pattern(gray, n_points, radius, METHOD)**
lbp = torch.from_numpy(lbp)
  
return lbp

tfms = transforms.Compose([

transforms.Lambda(lbp_transform),
transforms.ToPILImage(),
transforms.Resize((300, 300)),
transforms.ToTensor()
])

out = tfms(x)
print(out.shape)

> TypeError: pic should be Tensor or ndarray. Got <class ā€˜torch.Tensorā€™>.
My goal is convert all dataset images to texture images by using lbp, but I stocked in this step.

(train_ds[0][0][0]).shape

Shows my dataset image [0] shape, but if I use it by adding ā€œprintā€, it shows me error,

I canā€™t reproduce this issue, and this code works fine on my machine:

def lbp_transform(x):
    radius = 2
    n_points = 8 * radius
    METHOD = 'uniform'
    imgUMat = np.float32(x)
    gray = cv2.cvtColor(imgUMat, cv2.COLOR_RGB2GRAY)
    lbp = local_binary_pattern(gray, n_points, radius, METHOD)
    lbp = torch.from_numpy(lbp).float()
    return lbp


x = np.random.randn(600, 600, 3)
out = lbp_transform(x)
print(out.shape)
> torch.Size([600, 600])

tfms = transforms.Compose([
    transforms.Lambda(lbp_transform),
    transforms.ToPILImage(),
    transforms.Resize((300, 300)),
    transforms.ToTensor()
])

out = tfms(x)
print(out.shape)
> torch.Size([1, 300, 300])

Could you compare your code to my code snippet?

1 Like

Thanks @ptrblck the key part that you mentioned is ā€œ.float()ā€ in:

lbp = torch.from_numpy(lbp).float()

After you said on your machine works fine, I thought the problem is my Jupyter Notebook because when I run it in IDLE python or Google colab I get the correct answer
But when in the Jupyter Notebook I get this error:

TypeError: pic should be Tensor or ndarray. Got <class ā€˜torch.Tensorā€™>.

do you have any idea that works on Jupyter as well?

I guess you might be using different PyTorch and torchvision versions in your Jupyter environment and in your IDE, so you might need to check which Python kernel is executed.

1 Like

I will check it.
Thnak you @ptrblck

Hello, Extracting LBP generally (in the dataset class) seems like an expensive operation. Were you able to achieve good speed with the solution code?