Negative of an image using Pytorch transforms

Krishna_Garg: <p>I am trying to invert the images in my dataset. I know it is possible using OpenCV but I don’t know whether it is possible using torchvision.transforms. Any pointers would be appreciated.</p>

Nikronic: <p>Hi,</p>
<p>Transforms internally does not provide such a transform but as its core is PIL image library, you can simply use functions available in PIL to create custom transforms. Here is the one I extended for Negative:</p>
<pre><code class="lang-auto">
import PIL.ImageOps

def to_negative(img):
    img = PIL.ImageOps.invert(img)
    return img

class Negative(object):
    """Convert image to negative.

    Args:
        

    Returns:
        PIL Image: Negative version of the input.
         
    """
    def __init__(self):
        pass
    
    def __call__(self, img):
        """
        Args:
            img (PIL Image): Image to be converted to Negative.

        Returns:
            PIL Image: Negatived image.
        """
        return to_negative(img)

t = transforms.Compose([transforms.CenterCrop(10), 
                        Negative()])
</code></pre>
<p>Bests</p>

iacob: <p>You can use <code>torchvision.transforms.functional.invert()</code> from the <a href="https://stackoverflow.com/a/66624893/9067615" rel="noopener nofollow ugc">torchvision transforms</a> library.</p>

Sandesh_Baral: <p>torchvision.transforms.functional.invert() seems to be discontinued or something. I get AttributeError: module ‘torchvision.transforms.functional’ has no attribute ‘invert’ when I try to use it. My torch version is 1.7.1</p>

ptrblck: <p>Most likely you are using an older <code>torchvision</code> release. Note that <code>torch</code> and <code>torchvision</code> use different versioning and are not the same lib.</p>

alali: <p>I’m trying to use <code>torchvision.transforms.functional.invert()</code> on an entire dataset,<br>
Like the following:</p>
<pre><code class="lang-auto">train_ds = datasets.MNIST('./data', train=True, download=True,
                       transform=transforms.Compose([
                           transforms.ToTensor(),
                           transforms.functional.invert()
                       ]))
</code></pre>
<p>But I got error:<br>
<code>TypeError: invert() missing 1 required positional argument: 'img'</code></p>
<p>Is there a way to invert all images in a dataset without looping over each image?</p>

ptrblck: <p>You are trying to use the functional API operation in a transformation, which won’t work directly, so wrap it in e.g. <code>transforms.Lambda</code> or write a custom transformation class.<br>
This should work:</p>
<pre><code class="lang-python">data = torch.randn(100, 3, 224, 224)
out = torchvision.transforms.functional.invert(data)

transform = torchvision.transforms.Compose([
    torchvision.transforms.Lambda(lambda x: torchvision.transforms.functional.invert(x))
])
out = transform(data)
</code></pre>
<p>Also, since you are passing the current <code>transform</code> to the <code>MNIST</code> dataset, it will be applied on each sample, not the entire dataset.</p>

tommywolfheart: <p>Is  <code>torchvision.transforms.Lambda(transforms.functional.invert)</code> ok? It does what I want. I find I’m having issues with pickling the lambda in the above code snippet.</p>

ptrblck: <p>Yes, your code seems to work fine, too.</p>