Applying a hreshold on an Image

I have an image and I want to make the background totally equal to zero. In other words, the strategy that came to my mind was that using torch.clamp and setting the minimum value equal to the minimum value of the image. But I faced with the following error.

    smap = torch.clamp(torch.from_numpy(smap), min=torch.min(smap)).numpy()


Error: TypeError: min(): argument 'input' (position 1) must be Tensor, not numpy.ndarray

0013

How I can fix that?

It’s just saying you forgot to apply torch.from_numpy() on the input for min=torch.min(smap).

smap = torch.clamp(torch.from_numpy(smap), min=torch.min(torch.from_numpy(smap))).numpy()

Thank you for the answer. Unfortunately , the output is like the previous one and nothing has been changed. Do you have any suggestion that how I can fix the problem.

@Tm4 Worked for me:

import torch
import numpy as np

smap = np.random.rand(3,2)
smap = torch.clamp(torch.from_numpy(smap), min=torch.min(torch.from_numpy(smap))).numpy()

print(smap)

[[0.13507522 0.95144342]
[0.88192039 0.24267395]
[0.4150879 0.65108563]]

Thanks for the answer, in other words, I meant that although I used this strategy, the output does not contain a black background like the following image as I expected:

0003

Do you know which strategy I should use to apply such thresholding to have such image with a black background?

The normalization function is (image - min)/(max - min). In this case, sounds like you want a clamp to set the minimum value, and then normalize to that range.

import torch
from matplotlib import pyplot as plt

#Example 1: Normalization only to lowest value
dummy_image=torch.rand(3, 16, 16)
plt.imshow(dummy_image.permute(1,2,0))
plt.show()
min_val = dummy_image.min()

adjusted_image = (dummy_image-min_val)/(1-min_val)
plt.imshow(adjusted_image.permute(1,2,0))
plt.show()

#Example 2: Clamped value, and normalization to that value
dummy_image=torch.rand(3, 16, 16)
plt.imshow(dummy_image.permute(1,2,0))
plt.show()

clamped_val = 0.5

dummy_image[dummy_image<clamped_val]=0.5
min_val = dummy_image.min()
adjusted_image = (dummy_image-min_val)/(1-min_val)
plt.imshow(adjusted_image.permute(1,2,0))
plt.show()

Thanks for the solution but unfortunately when I apply each of two examples, I face the following error in another line of my script:

Exception has occurred: error
OpenCV(4.6.0) /io/opencv/modules/imgproc/src/colormap.cpp:736: error: (-5:Bad argument) cv::ColorMap only supports source images of type CV_8UC1 or CV_8UC3 in function 'operator()'
  File "/test.py", line 140, in main
    img = cv2.applyColorMap(frames_mask[i],cv2.COLORMAP_HOT)

How I can fix the problem?

What kind of object are you feeding to it and what are the dims? The example explicitly used a Pytorch tensor object with all values between 0 and 1 with dims 3, 16, 16.

I use this script for generating the maps. But I modified the code by changing fromVideo=True and also image_size=(224, 224).The code reads videos (*.AVI) and split videos to frames that the size of the frames is(224, 224). How I can fix the problem?

Moreover, the smap that I want to apply such operation on that has the shape of (224,224).

In order to view an image in imshow, it needs to have height, width and channels.

If you need just this specific image I would try:

result = torch.where(smap > threshold, smap, 0)

and look for the threshold that give the expected result.

To find the right threshold, plotting the histogram of the image would be helpful

It is the output map of a saliency detection method and it doesn’t contain any channel. The output for smap.shape is (224,224)

Thanks for the answer, but I want to apply the solution on different images of this kind and they would require different values for threshold. Moreover, when I use your answer, I see the following error:

Exception has occurred: TypeError
where() received an invalid combination of arguments - got (numpy.ndarray, numpy.ndarray, int), but expected one of:
 * (Tensor condition)
 * (Tensor condition, Tensor input, Tensor other, *, Tensor out)
 * (Tensor condition, Number self, Tensor other)
      didn't match because some of the arguments have invalid types: (e[31;1mnumpy.ndarraye[0m, e[31;1mnumpy.ndarraye[0m, e[31;1minte[0m)
 * (Tensor condition, Tensor input, Number other)
      didn't match because some of the arguments have invalid types: (e[31;1mnumpy.ndarraye[0m, e[31;1mnumpy.ndarraye[0m, e[31;1minte[0m)
 * (Tensor condition, Number self, Number other)
      didn't match because some of the arguments have invalid types: (e[31;1mnumpy.ndarraye[0m, e[31;1mnumpy.ndarraye[0m, e[31;1minte[0m)

There are always channels, even if the channels are just 1. Otherwise, it would contain no data. You can change:

plt.imshow(adjusted_image.unsqueeze(0).permute(1,2,0))

Thanks for the answer, because I do not need to show it and I want to save it using the following command:

cv2.imwrite(os.path.join(frames_path, '%04d.png'%(idx+1)), smap)

when I use your solution II receive the aforementioned error. Any idea?

The solution provided is purely in PyTorch. If you want to use that tensor elsewhere, you’ll need to offload it to NumPy with:

numpy_object = tensor_object.numpy()

You actually need no PyTorch for the solution. NumPy will work as well:

np.where(smap > threshold, smap, np.zeros_like(smap))

But as you mentioned - it is irrelevant for threshold that is changing