How to interpret arguments to torchvision.transform.ColorJitter?

username: Sally_Goldin
cooked: <p>Can someone provide more clarity about the meaning of the ColorJitter arguments? I understand that we can separately control (or disable) brightness, contrast, saturation and hue modifications, but how do the actual values entered relate to results? The documentation says “brightness_factor is chosen uniformly from [max(0, 1 - brightness), 1 + brightness]” but how is the brightness_factor applied to modify the image values?</p>
<p>Suppose I wanted to vary brightness within a range of +/- 25% of the existing values. What would be appropriate argument values for brightness?</p>
<p>Thank you in advance!</p>

username: ptrblck
cooked: <p>For your use case <code>brightness = 0.25</code> should work. This will sample the random brightness factor in the range <code>[0.75, 1.25]</code>.</p>

username: Sally_Goldin
cooked: <p>So is the brightness factor simply applied multiplicatively to the image data value?</p>
<p>What about contrast? I understand the sampling issue; what I am trying to figure out is how the value that is randomly selected is applied to modify the relevant image property. I’d expect this to be different for the four different properties. In particular, it seems that changing contrast would require a histogram remapping, not just a fixed modification of each value.</p>
<p>(BTW I really appreciate your quick responses!)</p>

username: ptrblck
cooked: <p>Ah OK, then I have misunderstood the question. <img src="https://discuss.pytorch.org/images/emoji/apple/wink.png?v=9" title=":wink:" class="emoji" alt=":wink:"></p>
<p>I can’t find the underlying implementation in <code>PIL</code>, so take this information with a grain of salt:</p>
<ul>
<li>brightness: is an additive variable, which is directly added (or subtracted) to the image</li>
<li>contrast: slope, which is a multiplicative factor for each pixel value</li>
<li>hue: not sure, if there are other methods, but you could transform the RGB values to HSV and change the hue on the color wheel.</li>
<li>saturation: HSV conversion would work, otherwise should be:</li>
</ul>
<pre><code class="lang-python">color_max = max(R, G, B)
color_min = min(R, G, B)

if R == G == B:
    S = 0
else:
    S = 255 * (color_max - color_min) / (color_max + color_min)
</code></pre>

username: Sally_Goldin
cooked: <p>Thank you! Your previous reply was also useful!</p>

username: Monsieur_Didkekne
cooked: <p>Hello,<br>
I want to do contrast and brightness adjustment with the pytorch color jitter. I want the implementation the way you explained it (brightness should be an additive factor and contrast a multiplicative factor.</p>
<p>However I don’t think it is like that in the pytoch color jitter, I did some test :</p>
<pre><code class="lang-auto">t_color = torchvision.transforms.ColorJitter(brightness = (0,0))
img = t_color(img)
</code></pre>
<p>I did this on the image :<br>
<img src="https://discuss.pytorch.org/uploads/default/original/3X/5/b/5b1438798d75d52d87ea3b0b3e8f2509c9277421.png" alt="image_2021-11-05_132658" data-base62-sha1="cZILSyoUuBCBfWOrdzxo3RabbiN" width="261" height="248"></p>
<p>and the result was a black image.</p>
<p>There should be no change if it was an additive factor.</p>
<p>I Don’t know if there is an augment that implement the brightness with an additive factor but if someone know how to do it I would be happy.</p>
<p>PS : sorry for my approximate english, I’m not very good  at it.</p>

username: ptrblck
cooked: <p>You are setting the brightness to zero, so a black image would be expected.<br>
<code>ColorJitter</code> with a <code>brightness</code> argument is calling into <a href="https://github.com/pytorch/vision/blob/9a7dc1a127255343551903b8b64c25dc2b5df2b1/torchvision/transforms/functional_tensor.py#L155-L163"><code>adjust_brightness</code></a>, which is blending two images, the input image and a zero image (black). The brightness factor would be zero, which is used as <code>ratio</code> in <a href="https://github.com/pytorch/vision/blob/9a7dc1a127255343551903b8b64c25dc2b5df2b1/torchvision/transforms/functional_tensor.py#L314-L317"><code>_blend</code></a>.<br>
As you can see, you have an additive transformation as:</p>
<pre><code class="lang-python">return (ratio * img1 + (1.0 - ratio) * img2).clamp(0, bound).to(img1.dtype)
</code></pre>
<p>where <code>ratio=0.</code> and you are thus getting a black output image.</p>