Skip to content

Commit

Permalink
Updating docs/course/visual_perception.md
Browse files Browse the repository at this point in the history
  • Loading branch information
kaanaksit committed Nov 1, 2024
1 parent 71dde02 commit 5b5a969
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 16 deletions.
15 changes: 10 additions & 5 deletions docs/course/visual_perception.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ This formula gives us more insight on how we percieve colors from different digi
<br />- [Biomimetic Eye Modeling & Deep Neuromuscular Oculomotor Control](https://www.andrew.cmu.edu/user/aslakshm/pdfs/siggraph19_eye.pdf)


The story of color perception only deepens with the concept of [color opponency](http://dx.doi.org/10.1364/JOSAA.34.001099)[@shevell2017color]. This theory reveals that our perception of color is not just a matter of additive combinations of primary colors but also involves a dynamic interplay of opposing colors: red versus green, blue versus yellow. This phenomenon is rooted in the neural pathways of the eye and brain, where certain cells are excited or inhibited by specific wavelengths, enhancing our ability to distinguish between subtle shades and contrasts.

The story of color perception only deepens with the concept of [color opponency](http://dx.doi.org/10.1364/JOSAA.34.001099)[@shevell2017color].
This theory reveals that our perception of color is not just a matter of additive combinations of primary colors but also involves a dynamic interplay of opposing colors: red versus green, blue versus yellow.
This phenomenon is rooted in the neural pathways of the eye and brain, where certain cells are excited or inhibited by specific wavelengths, enhancing our ability to distinguish between subtle shades and contrasts.
Below is a mathematical formulation for the color opponency model proposed by [Schmidt et al.](https://opg.optica.org/josaa/fulltext.cfm?uri=josaa-31-4-A195&id=279354)[@schmidt2014neurobiological]

\begin{bmatrix}
Expand Down Expand Up @@ -102,9 +103,13 @@ Let us use this test to demonstrate how we can obtain LMS sensation from the col
```

1. Adding `odak` to our imports.
2. Generating arbitrary target primaries (the sample image).
3. Generate arbitrary primaries spectrum
4. Obtain LMS cone sensation
2. Loading an existing RGB image.
3. Defining the spectrum of our primaries of our imaginary display.
4. Obtain LMS cone sensations for our primaries of our imaginary display.
5. Calculating the LMS sensation of our input RGB image at the second stage of color perception using our imaginary display.
6. Calculating the LMS sensation of our input RGB image at the third stage of color perception using our imaginary display.
7. We are intentionally adding some noise to the input RGB image here.
8. We calculate the perceptual loss/difference between the two input image (original RGB vs noisy RGB).
<br />
This a visualization of a randomly generated image and its' LMS cone sensation.

Expand Down
8 changes: 4 additions & 4 deletions odak/learn/perception/color_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ def lms_to_primaries(self, lms_color_tensor):

def second_to_third_stage(self, lms_image):
'''
This function turns second stage [L,M,S] values into third stage [(S+L)-M, M-(S+L), (S+M)-L],
This function turns second stage [L,M,S] values into third stage [(M+S)-L, (L+S)-M, L+M+S],
See table 1 from Schmidt et al. "Neurobiological hypothesis of color appearance and hue perception," Optics Express 2014.
Parameters
Expand All @@ -336,9 +336,9 @@ def second_to_third_stage(self, lms_image):
'''
third_stage = torch.zeros_like(lms_image)
third_stage[:, 0] = (lms_image[:, 2] + lms_image[:, 0]) - lms_image[:, 1]
third_stage[:, 1] = lms_image[:, 1] - (lms_image[:, 2] + lms_image[:, 0])
third_stage[:, 2] = (lms_image[:, 2] + lms_image[:, 1]) - lms_image[:, 0]
third_stage[:, 0] = (lms_image[:, 1] + lms_image[:, 2]) - lms_image[:, 1]
third_stage[:, 1] = (lms_image[:, 0] + lms_image[:, 2]) - lms_image[:, 1]
third_stage[:, 2] = lms_image[:, 0] + lms_image[:, 1] + lms_image[:, 2]
return third_stage


Expand Down
15 changes: 8 additions & 7 deletions test/test_learn_perception_display_color_hvs.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,25 @@ def test(
'test/data/fruit_lady.png',
normalizeby = 255.,
torch_style = True
).unsqueeze(0).to(device) # (1)
).unsqueeze(0).to(device) # (2)

the_number_of_primaries = 3
multi_spectrum = torch.zeros(
the_number_of_primaries,
301
) # (2)
) # (3)
multi_spectrum[0, 200:250] = 1.
multi_spectrum[1, 130:145] = 1.
multi_spectrum[2, 0:50] = 1.

display_color = display_color_hvs(
read_spectrum ='tensor',
primaries_spectrum=multi_spectrum,
device = device
) # (3)
) # (4)

image_lms_second_stage = display_color.primaries_to_lms(image_rgb) # (4)
image_lms_third_stage = display_color.second_to_third_stage(image_lms_second_stage) # (5)
image_lms_second_stage = display_color.primaries_to_lms(image_rgb) # (5)
image_lms_third_stage = display_color.second_to_third_stage(image_lms_second_stage) # (6)


odak.learn.tools.save_image(
Expand All @@ -58,8 +59,8 @@ def test(
)


image_rgb_noisy = image_rgb * 0.6 + torch.rand_like(image_rgb) * 0.4 # (6)
loss_lms = display_color(image_rgb, image_rgb_noisy) # (7)
image_rgb_noisy = image_rgb * 0.6 + torch.rand_like(image_rgb) * 0.4 # (7)
loss_lms = display_color(image_rgb, image_rgb_noisy) # (8)
print('The third stage LMS sensation difference between two input images is {:.10f}.'.format(loss_lms))
assert True == True

Expand Down

0 comments on commit 5b5a969

Please sign in to comment.