Message Boards Message Boards

Color blind test using Mathematica?

Posted 9 years ago

In the test books, there is nothing special about the paper or the inks. I know this because scanned versions print just fine using toner or ink.

Seems like it would be a really neat project!

POSTED BY: Douglas Youvan
35 Replies

Here are three grids of external saturation vs internal saturation.

In the RED grid, I see only a faint contrast throughout and nothing in the first three columns.

In the GREEN grid, I see everything but the first column and good contrast.

In the BLUE grid, the central square is yellow, which isn't all that easy to see against whitish background, but it is definitely there on all but the first column.

See attachment.

Attachments:
POSTED BY: Eric Johnstone

Hi,

Is it possible to have the final code? The test disapears when I put the slider and I don't see the graphs. I am ophthalmologist and interessed in a test that might provide more information than an Ishihara test. I realize I'm years behind, but you never know.

Hedwig

Hi Hedwig,

I've attached the notebook, but there is something wrong with many of my notebooks in Version 14.1. It has something to do with the Dynamic function. When I evaluated the notebook, the sliders in the app were not staying put. Also, beware of the first line; set it to 1==0 or delete it.

Eric

Attachments:
POSTED BY: Eric Johnstone

Hi Eric, Thank you for the quick response, I didn't expect it. The test seems to work, but it will take some time before I understand what is going on. The ratio of saturation of inner to outer square is measured on a basis of R,G and B pseudocolors? Many thanks

Hedwig

Hi Hedwig,

Which version of Mathematica are you using? I recently bought a new computer to run Windows 11 and also installed version 14.1 of Mathematica. Could this computer be at fault?

I can't run the colorblind test, and it's been almost a decade, so I can't give you much help.

I remember that a datum can be removed by clicking on it in the graph. This is useful because outliers do occur, especially with inexperienced users.

What version of Mathematica are you using?

Eric

POSTED BY: Eric Johnstone

Hi Eric,

I have version 12.3 of mathematica on a MacBook Pro. I don't think the test is perfectly running but I can see results for every slider with a manually adapted saturation.

Hedwig

Hi Doug,

(Weird, the previous post wasn't on line when I went back to edit it, so this post repeats some of the points.)

Now that the computer colour blind measuring test is pretty much finished, we can consider your original observation: that the medium of the test doesn't matter. It could be a laser printer, ink-jet, or a monitor.

The computer test could be implemented on paper as a grid of surrounding saturation vs interior saturation for each colour. the line demarcating seen/unseen would be the curve of the computer test

I'd forgotten about colour blind testing being used to exclude people from certain jobs. It would have been a terrible thing if I had not been allowed to work at the university because of my colour blindness, considering what I have accomplished.

The alternative use of the computer test would be to:

1) create "sunglasses " that normalize the colours

2) create illuminators that normalize the illumination.

3) create a camera with inverse response in the non-defective colours so that the image would be normalized.. This would be the best way, because the response is sensitive to saturation, which a filter or illuminator would not be. We have the responses as equations, so these could be applied directly to RGB values.

In fact, if the corrections were applied to the RandomImage[] display, it should be possible to get three coincident straight lines. Or would it? The green and blue values would be distorted to make them follow the red response. Everything would be multiplied by some coefficient to bring the maximum to 1.0. That will be the next thing to do.

The sunglasses gave a good response on the our test, and I was declared "not colour blind" in the colour arrangement test. But they made no difference in the Ishihara. That will be the ultimate condition for colour correction--see the hidden figures in the Ishihara.

Attached is the test with the controls below the image. This makes it more useful for touch screens.

Eric

Attachments:
POSTED BY: Eric Johnstone

Hi Doug,

Now that the tester is done, it's time to go back to your original observation: that the medium isn't an essential part of the colour blind test. Any paper or printer type will do. Or monitor.

Each colour-graph can be shown as a two-dimensional grid of saturation of the background vs saturation of the inner square.

I forgot about testing for people who don't want others to know that they are colour blind because it disqualifies them for certain jobs. My colour blindness has certainly made seeing colour bands on resistors difficult (impossible). But it would have been a terrible thing if I had not been allowed to work at the university, considering what I have accomplished in spite of my colour blindness.

So the next part of the project is to make printable grids of test squares. This can make the computer version unnecessary. A line demarcating seen/unseen inner images will give the curve of the computer version.

Eric

POSTED BY: Eric Johnstone

Hi Patrik,

Amazing! I also went to StackExchange and found some code that would have required a lot of finagling to accomplish anything.

This might be the final version. I did fix up the Initialize to set the vals to zero instead of empty.

When I said a "small editing menu," I was just leaving room for ideas that haven't yet occurred to me. Nothing comes to mind, though.

Thank you for your help. I'm curious; how did you learn Mathematica?

The slightly modified code is attached.

Eric

Attachments:
POSTED BY: Eric Johnstone

Hi again!

Yeah I can really see how the scintillation helps you seeing the square at lower contrasts. I think your latest addition was really good. The {{"MouseUp", 1} :> .... event means that the primary button (button number 1) is the one we are interested in. I added it because simply "MouseUp" wouldn't work for me. Your new code works however, so I don't know what I was doing before.

What I'd like to do is have a little editing menu (delete a graph point for now).

From a statistical standpoint, it would probably be better to remove outliers on a predefined basis. But from a dynamic interactivity perspective your suggestion is golden and I couldn't help myself from looking into it.

User kglr on StackExchange made me realize something that I never would have know. In this thread, he/she shows ListPlot can plot buttons. So what I did was I set each button so that it would contain a function to remove the plot point in question and recalculate the fitted equations, the result was this (also attached):

drawGraphs[] := Module[{},
  {xxr, xxg, xxb} = FitColorPoints[];
  CreateDocument[{
    Dynamic@Panel@Show[
       Plot[{xxr, xxg, xxb}, {x, 0, 1}, 
        PlotStyle -> {Red, Green, Blue}],
       ListPlot[
        MapIndexed[
         Button[Tooltip@#,
           {vals = Delete[vals, #2],
            {xxr, xxg, xxb} = FitColorPoints[]}] &, vals, {2}], 
        PlotStyle -> {Red, Green, Blue}],
       PlotRange -> {{0, 1}, {0, 1}}, AxesOrigin -> {0, 0}, 
       GridLines -> Automatic, 
       AxesLabel -> {"Saturation", "Response"}],
    Dynamic@
     Style[Grid[{{"RED", "GREEN", "BLUE"}, 
        MatrixForm /@ (Sort /@ vals), {xxr, xxg, xxb}}, Frame -> All],
       ShowStringCharacters -> False]
    }
   ]
  ]

I needed to move your valsr, valsg, and valsb into a single list, vals, to accomplish this though! Using MapIndex, the second argument of the mapping is the position of the value in the list vals. There are lots of ways to expand on this if one is interested, the thread on stackexchange I linked to earlier shows them highlighting the plot points using the epilog option. By expanding on that code, a user could highlight a number of different plotpoints and delete them by pressing the delete key.

You talked about having a small editing menu, was there any more functionality you where thinking about rather than just deleting the outlying points?

Patrik

Attachments:
POSTED BY: Patrik Ekenberg

Hi Patrik,

Yup, it's really good code!

The constant scintillation wasn't really what I wanted, once I got used to it. The problem before was that you could only really see the inner square at low contrast when the mouse was moving. Here is some code with the Refresh[] image only while the mouse button is down. (In the attachment.)

I removed the inner braces and the 1 in {{"MouseUp", 1} :> (AppendTo[valsr,... What was your intention?

I've been trying all morning to find a way to edit the graphs with a mouse. Especially with the new automatic collection of data at a MouseUp, it's possible to get some erroneous data points. What I'd like to do is have a little editing menu (delete a graph point for now). The Tooltip knows when you are at a point in a ListPlot, but it doesn't return the point. Do you know of a way of accessing the graph like the Tooltip does?

Here is the effect of the scintillation while the mouse button is held down:

mouse held down

You can see the effect by the much smaller scatter in the red graph.

Eric

Attachments:
POSTED BY: Eric Johnstone

Awesome Eric, I'm glad you liked the code.

The constant scintillation is really cool! I'm a bit surprised that you were able to refresh it fast enough to be so seamless. On my old laptop I currently use, it takes about 1 millisecond to generate a new image:

In[1] := AbsoluteTiming[
  RandomImage[{0.5, 1.0}, {100, 100}, ColorSpace -> "RGB"]][[1]]
Out[1] := 0.00100784

An alternative would be to first generate a finite number of random images and then take a

In[2] := rngimg = Table[
   RandomImage[{0.5, 1.0}, {100, 100}, ColorSpace -> "RGB"], {20}];
In[3] := AbsoluteTiming[RandomSample[rngimg, 1]][[1]]
In[4] := AbsoluteTiming[rngimg[[RandomInteger[{1, 20}]]]][[1]]
Out[3] := 5.74734*10^-6
Out[4] := 8.62102*10^-6

But since your code is so fast, I don't think that is needed! Maybe if you need to extend the code in the future in a way that makes it slower!

Regarding the sliders, I was a bit surprised that there was no option to manipulate the speed/resistance of the sliders, though it might have to do with that it would require manipulating the sensitivity of the mouse cursor itself which might not be trivial for a program to do. The only alternative I can think of is to make the sliders larger by specifying the width of the slider using the ImageSize option.

ImageSize->500

works pretty good for me, though I don't have any troubles seeing colors so I can't tell how much accuracy is needed!

Patrik

POSTED BY: Patrik Ekenberg

Hi Patrik and Doug,

Doug, this isn't a test in the sense of Ishihara. It's more like a visual field test.

Patrik, I love your code. Adding constant scintillation was quite easy using Refresh[]. I put the ranges of all sliders back to {0,1} but there isn't really enough room to move them accurately unless you use the alt key trick. Notebook attached.

Eric

Attachments:
POSTED BY: Eric Johnstone

Hi Patrik,

That's some nice code! I haven't come close to understanding Dynamic[], but that seems to be where the power lies. It would be great to be free of Manipulate[]. I did manage to find how to monitor for MouseUp events using TrackingFunction[] in Manipulate.

One thing that we would like is to have the display continually scintillating, not only when the slider is being moved. I'll work on it, but any help is appreciated.

I used 0.75 as the lower bound for g and b because I personally didn't have any use for the range below that. The new code in the last notebook attachment uses the full range, but that concentrates all the action at the top end of the slider.

Doug,

I added {0,0} as one of the data points in every vals array. That would put your three responses almost in the same line. Not much scatter this time. Are you getting better at doing the test?

Eric

POSTED BY: Eric Johnstone

Patrik and Eric,

In reply to your question (Eric), I am really tense during the test because I am trying to be absolutely consistent in "when I see it". If anything, I push it towards "I definitely see it".

If this technique made it to ophthalmology, they might want a verifiable answer. Than would mean we would have to randomize the shape of what we are displaying. In that regard, I would follow Ishihara and use two numerals. Approaching always from the invisible side, when the subject calls out the correct numerals, you have their value.

You guys are so far ahead of me in coding, I am sorry that I can be of no help. It's also going to take some time for the biophysics of saturation to sink in. I also wanted to make it clear that asking about a CDF did not mean I wanted to close off the development.

I am very happy that you made so much progress.

Doug

POSTED BY: Douglas Youvan

Patrik,

Thank you for jumping in. That works great! Here's me again:

enter image description here

Thanks, Doug

P.S. Are we compatible with a CDF?

POSTED BY: Douglas Youvan

Wow! What an awesome thing you guys got going on here!

It isn't necessary to click on the Get colour values button. All that is required is to sense the mouse up when the slider is released. Suggestions?

I think that an event handler would be the way to go. They are associated with their respective expression so the "MouseUp" event will only trigger when the mouse is over that expression. So putting one of these on each of the sliders does the trick. However, I don't know if you can directly manipulate the Manipulate sliders. An alternative is to skip the Manipulate function and implement your own sliders. I did that in the attached Notebook.

The code became:

DynamicModule[{saturation = 0.5, r = 1.0, g = 1.0, b = 1.0},
 Column[{
   Labeled[Slider[Dynamic[saturation], {0, 1}], "S: ", Left],
   Labeled[
    EventHandler[
     Slider[Dynamic[r], {0.75, 
       1}], {{"MouseUp", 
        1} :> (AppendTo[valsr, {1 - saturation, r (1 - saturation)}]; 
        r = 1.0; g = 1.0; b = 1.0; saturation = RandomReal[];)}, 
     PassEventsDown -> True], "R: ", Left],
   Labeled[
    EventHandler[
     Slider[Dynamic[g], {0.75, 
       1}], {{"MouseUp", 
        1} :> (AppendTo[valsg, {1 - saturation, g (1 - saturation)}]; 
        r = 1.0; g = 1.0; b = 1.0; saturation = RandomReal[];)}, 
     PassEventsDown -> True], "G: ", Left],
   Labeled[
    EventHandler[
     Slider[Dynamic[b], {0.75, 
       1}], {{"MouseUp", 
        1} :> (AppendTo[valsb, {1 - saturation, b (1 - saturation)}]; 
        r = 1.0; g = 1.0; b = 1.0; saturation = RandomReal[];)}, 
     PassEventsDown -> True], "B: ", Left],
   Row[{Column[{
       Button["Initialise", valsr = {};
        valsg = {}; valsb = {};],
       Button["Draw graphs", drawGraphs[valsr, valsg, valsb]]}],
     Dynamic[(image = 
        ImageData[
         RandomImage[{saturation, 1.0}, {100, 100}, 
          ColorSpace -> "RGB"]]; 
       ImageCompose[Image[image, ImageSize -> 200], 
        Image[Partition[
          Transpose[{r, g, b}*
            Transpose[Flatten[image[[25 ;; 75, 25 ;; 75, All]], 1]]], 
          50], ImageSize -> 200]])]}, Spacer[2]]}]]

enter image description here

Is there a reason why the red slider in your code went from 0 to 1 and all the others went from 0.75 to 1?

Best regards, Patrik

Attachments:
POSTED BY: Patrik Ekenberg

Hi Doug,

I see you have a lot of scatter in the red, just like me. Maybe it's inherently hard to discern the square. I was looking through the demonstrations and came across a demo of a disk of random dots moving in a field of random dots. As soon as you stopped moving the disk, it just settled into the background and became invisible. Maybe if the inner square were moving, it would be easier to see. Something to try.

Here is a new, much easier version. I found out how to detect MouseUp events by using TrackingFunction[]. Now all you have to do is detect the inner square and release the mouse button. The three buttons have been turned into Reset buttons. If you aren't happy with one of the graphs, you can delete it and re-do it.

version 2

A notebook is attached.

Eric

Attachments:
POSTED BY: Eric Johnstone

Eric,

Here are two more trials. I have a hardcover copy of Ishihara, and I pass.

Dougenter image description here

enter image description here

POSTED BY: Douglas Youvan

Hi Doug,

Are we seeing the effect of the yellowing of your lenses in the waviness of your blue and green lines? I should add in my instructions that it's important to go close to the very ends of the saturation, otherwise the curves extrapolate in weird ways.

Are you normally aware of a red deficiency?

Eric

POSTED BY: Eric Johnstone

Hello everyone,

Here is a functional app to measure colour blindness.

cb view

Instructions

1) Click on Initialise to set the data collection arrays to zero.

2) A random saturation level for the image will be selected. Move one of the r, g, or b sliders until the central square appears. Keep adjusting the slider until the square is just visible. Click on the corresponding Get colour values button.

3) A new random saturation will appear. Continue until you have enough data points to generate smooth graphs.

4) Click on Draw graphs. A new notebook will appear with the graphs, data arrays, and the approximating equation.

5) Examine the graphs for regions that need more data. Go back to the tester and manually set the Saturation slider to the value needed. This can be done by positioning the slider visually so that it is matches the horizontal axis of the region needing data.

Discussion

This app is an implementation of a technique due to Douglas Youvan.

There is a significant improvement that eludes me, so I'm asking for help. It isn't necessary to click on the Get colour values button. All that is required is to sense the mouse up when the slider is released. Suggestions? I know that EventHandler[] is probably the way to go, but how do you relate the MouseUp to a particular slider?

It would be interesting to get some graphs from both normal and colour blind people. There are other types of colour blindness than red/green. (I always thought that my green vision must be defective, too. Not so.)

And suggestions for improvements and other features would be welcome.

A notebook is attached.

Eric

Attachments:
POSTED BY: Eric Johnstone

Eric,

I took the test twice. The values were very similar, and my red consistently fell off as shown in the attached gif.

Doug

Attachments:
POSTED BY: Douglas Youvan

Hi Doug,

Here is the result with my amber-tinted sunglasses: sunglasses

And that's why the fall colours explode with them on!

Eric

POSTED BY: Eric Johnstone

Eric,

Phenomenal! This belongs in a vision book that can display your work.

You are on a roll, so I don't want to divert you. But, could I suggest that you try "ortho" on an image that is invisible because of your deficit?

Although I pass Ishihara, Ortho should pick up images that I can't see either.

Also, I have yet to find any "Daltonization" algorithms.

Doug

POSTED BY: Douglas Youvan

Hi Doug,

I fixed the code to make collecting data easier:

valsb = {};

Manipulate[{Button["Get values", 
   AppendTo[
    valsb, {1 - saturation - offset, 
     b (1 - saturation - offset)}]], (image = 
    ImageData[
     RandomImage[{saturation + offset, 1.0}, {100, 100}, 
      ColorSpace -> "RGB"]]; 
   ImageCompose[Image[image, ImageSize -> 200], 
    Image[Partition[
      Transpose[{r, g, b}*
        Transpose[Flatten[image[[25 ;; 75, 25 ;; 75, All]], 1]]], 50],
      ImageSize -> 200]])}, {{offset, 0}, .05, -.05}, {{saturation, 
   0.5}, .95, 0.05}, {{r, 1.0}, 0.0, 1.0}, {{g, 1.0}, .85, 
  1.0}, {{b, 1.0}, .85, 1.0}]

The AppendTo[] function adds the data points directly to the list, which is valsb for the blue. More work on the interface is needed for an operational app, of course.

Using a different monitor, I got these results:

second test

Maybe I'm just getting better at taking the test. In both cases, though, the red scatter is appreciable. Now I know why I can't pick raspberries!

Eric

POSTED BY: Eric Johnstone

Hi Doug,

I've been testing myself. Here is the new code:

Manipulate[
  {
     PasteButton["Get values",{1-saturation-offset, b(1-saturation-offset)}],
     (image=ImageData[RandomImage[{saturation+offset,1.0},{100,100},ColorSpace->"RGB"]];
     ImageCompose[Image[image,ImageSize->200],
     Image[Partition[Transpose[{r,g,b}*Transpose[Flatten[image[[25;;75,25;;75,All]],1]]],50],ImageSize->200]])
  },
  {{offset,0},.05,-.05},{{saturation,0.5},.95,0.05},{{r,1.0},0.0,1.0},{{g,1.0},.85,1.0},{{b,1.0},.85,1.0}
]

To make the sliders less sensitive, I added a finer Saturation control. This isn't strictly necessary, because pressing the alt key while moving the sliders increases their sensitivity by 10. But that's an esoteric feature some might not know.

The response is taken as the red slider, say, multiplied by the saturation being tested. In the cases of the green and blue, this makes the response almost equal to the stimulus. But for the red, things are very different.

There is also a PasteButton[], which sends the values of the test datum to the current output position in the notebook. These form a series of lists, but commas and surrounding braces need to be added to finish them off.

The values are fitted to a third order polynomial. Here the blue values are fitted:

xxxb=Fit[valsb,{1,x,x^2,x^3},x]

The whole set of data points and fitted functions look like this:

Show[
   ListPlot[valsr, PlotStyle -> Red], 
   Plot[eqnr[x], {x, 0, 1}, PlotStyle -> Red], 
   Plot[eqng[x], {x, 0, 1}, PlotStyle -> Green], 
   ListPlot[valsg, PlotStyle -> Green],
   ListPlot[valsb, PlotStyle -> Blue], 
   Plot[eqnb[x], {x, 0, 1}, PlotStyle -> Blue], 
   PlotRange -> {{0, 1}, {0, 1}}, AxesOrigin -> {0, 0}, 
   AxesLabel -> {Saturation, Response}
]

totalcbresponse

Eric

POSTED BY: Eric Johnstone

Hey Eric,

Before I comment on your recent work, let me upload another program here.

This started at: http://et-al.com/pdf/document3.pdf . Look at Figure 5, panel F and the math that goes with it.

I re-wrote that code in Examples 3 and 4 in my Pseudocolor e-book in 2006: http://youvan.com/Examples/Example_4._Counterfeit_Detection_Based_on_Ink_Color.htm . Here, I've attached "otho 1" which is running in version 10.3. The main thing to note in the code is that on images with homogenous backgrounds the matrix will get identical pixel values and blow up from singularity. That's why you see me adding small random numbers.

I've now uploaded "ortho 2 click", and it is much easier to use. You get to pick three pixels (colors) and then orthonormalize the entire image.

Doug

Attachments:
POSTED BY: Douglas Youvan

Hey Eric,

Before I comment on your recent work, let me upload another program here.

This started at: http://et-al.com/pdf/document3.pdf . Look at Figure 5, panel F and the math that goes with it.

I re-wrote that code in Examples 3 and 4 in my Pseudocolor e-book in 2006: http://youvan.com/Examples/Example_4._Counterfeit_Detection_Based_on_Ink_Color.htm . Here, I've attached "otho 1" which is running in version 10.3. The main thing to note in the code is that on images with homogenous backgrounds the matrix will get identical pixel values and blow up from singularity. That's why you see me adding small random numbers.

Ortho 1 picks points randomly, but it is also advantageous to let the user do three mouse clicks for red, green, and blue. Those colors will be remapped to full color R, G, and B and every other color in between will be warped into these new color axes.

Eric - The second figure here: http://www.vischeck.com/daltonize/ is startling if it is correct. The deficit would seem to rule-out work in fluorescence microscopy. We also see reference in this link to "Daltonization". I'll look for the algorithms, next.

Could you please send a "hello" to doug@youvan.com ?

More soon ...

Doug

Attachments:
POSTED BY: Douglas Youvan

Hi Doug,

Have you come up with anything? This morning I discovered RandomImage[], and in true MMA style, it's very fast. Instead of a cross in the square, I used a square inside a square. I also found an interesting thing about the saturation (correct term?) of the background image. When it is at full saturation, I can only barely see the interior square when r is at zero.

Here's the code:

        Manipulate[
           (
              imag=ImageData[RandomImage[{saturation,1.0},{100,100},ColorSpace->"RGB"]];
              ImageCompose[Image[imag,ImageSize->200],
              Image[Partition[Transpose[{r,g,b}*Transpose[Flatten[imag[[25;;75,25;;75,All]],1]]],51],ImageSize->200]]
            ),
            {{saturation,0.5},1,0},{{r,1.0},0.0,1.0},{{g,1.0},0.0,1.0},{{b,1.0},0.0,1.0}
        ]

The reason I can see the green and blue so well is that I have lens implants in both eyes. The ophthalmologist showed me a yellow glass lens that he keeps in his office to show his patients how discoloured the lens becomes with age. It took a few months to get over the extreme blueness of my new vision. But I also remembered how blue snow used to look when I was a child.

Eric

Attachments:
POSTED BY: Eric Johnstone

Hi Doug,

The number of calculations for a single frame is 60,000 + the cross. To get the sort of scintillation you want, it looks like the background should be pre-calculated. Here is a first attempt that you can play with.

r=.5;b=1;g=1;
col=Table[For[i=1,i<=100,i++,For[j=1,j<=100,j++,tab2[[i,j]]={RandomReal[{RandomReal[],1.0}],RandomReal[{RandomReal[],1.0}],RandomReal[{RandomReal[],1.0}]}]]

For[i=47,i<=53,i++,For[j=1,j<=100,j++,tab2[[i,j]]={RandomReal[{RandomReal[],r}],RandomReal[{RandomReal[],g}],RandomReal[{RandomReal[],b}]}]]

For[i=1,i<=100,i++,For[j=47,j<=53,j++,tab2[[i,j]]={RandomReal[{RandomReal[],r}],RandomReal[{RandomReal[],g}],RandomReal[{RandomReal[],b}]}]]

Image[tab2,ImageSize->{400,400}],30];

This creates a list of 30 backgrounds plus the cross set by the rgb values at the start. I can see the cross at higher values of red when the display is animated.

Here is the animation.

ListAnimate[col, 16]

Next is to put this into a Manipulate. Tomorrow.

Eric

POSTED BY: Eric Johnstone

Erik,

I've now played with the test. You are better than me with G and B. However, R=0.4 is vivid Cyan to me.

The longer I look at the figure, the less confident I am.

Can you make the figure regenerate even when the sliders are not moving? That would eliminate bad random numbers and give more of an average for that value. Also, it might eliminate this saturation effect by distracting you with new images.

Doug

POSTED BY: Douglas Youvan

Eric,

I am still playing with your very nice code. Last night, I did about the same thing with a plethora of cut and paste jobs!

By Ishihara, I am not color blind.

Your code would be appreciated as CDF. There are other people interested that do not have Mathematica.

I'll get you some thresholds for my own vision. There's another color blind guy who has been looking at my work, but he would need a CDF.

I'm thinking we need to do something like balance these in Monochrome, so there is no hint of intensity. Beware of ColorConvert to grayscale - it does not do what you would expect on conversion to grayscale. (It's not a simple average).

More later ...

Doug

POSTED BY: Douglas Youvan

Hi Doug,

I played around with the colour blind test here: Ishihara. I can't see anything, even the one that red/green colour blinds are supposed to see. My wife could see everything.

Then I tried Color Arrangement Test and was rated as severely colour blind. So I tried it with my sunglasses on and was told I am not colour blind at all! Back to the Ishihara test with the sunglasses and I still couldn't see anything. So the sunglasses do provide some correction.

Here is your code with a manipulate for the red, green, and blue components.

tab1 = Table[{x, y}, {x, 100}, {y, 100}];
tab2 = tab1;
cbTest[r_, g_, b_] := 
  (For[i = 1, i <= 100, i++, 
    For[j = 1, j <= 100, j++, 
     tab2[[i, j]] = {RandomReal[{RandomReal[], 1.0}], 
       RandomReal[{RandomReal[], 1.0}], 
       RandomReal[{RandomReal[], 1.0}]}]]

   For[i = 47, i <= 53, i++, 
    For[j = 1, j <= 100, j++, 
     tab2[[i, j]] = {RandomReal[{RandomReal[], r}], 
       RandomReal[{RandomReal[], g}], RandomReal[{RandomReal[], b}]}]]

   For[i = 1, i <= 100, i++, 
    For[j = 47, j <= 53, j++, 
     tab2[[i, j]] = {RandomReal[{RandomReal[], r}], 
       RandomReal[{RandomReal[], g}], RandomReal[{RandomReal[], b}]}]]

   Image[tab2, ImageSize -> {400, 400}])

Manipulate[cbTest[r, g, b], 
    {{r, 1.0}, 0.0, 1.0}, {{g, 1.0}, 0.0, 1.0}, {{b, 1.0}, 0.0, 1.0}]

I can start to see the cross with red at 0.4 and the others at 1.0, but with my sunglasses on, 0.74

I can start to see the cross with green at 0.875 and the others at 1.0.

I can start to see the cross with blue at 0.833 and the others at 1.0.

Are you colour blind? If so, what values do you get?

See attached notebook for code.

Eric

Attachments:
POSTED BY: Eric Johnstone

Eric,

How is this for a start?

Doug

tab1 = Table[{x, y}, {x, 100}, {y, 100}];
tab2 = tab1;
For[i = 1, i <= 100, i++, For[j = 1, j <= 100, j++, tab2[[i, j]] = {
    RandomReal[{RandomReal[], 1.0}],
    RandomReal[{RandomReal[], 1.0}],
    RandomReal[{RandomReal[], 1.0}]} ]]

For[i = 47, i <= 53, i++, For[j = 1, j <= 100, j++, tab2[[i, j]] = {
    RandomReal[{RandomReal[], 0.5}],
    RandomReal[{RandomReal[], 1.0}],
    RandomReal[{RandomReal[], 1.0}]} ]]

For[i = 1, i <= 100, i++, For[j = 47, j <= 53, j++, tab2[[i, j]] = {
    RandomReal[{RandomReal[], 0.5}],
    RandomReal[{RandomReal[], 1.0}],
    RandomReal[{RandomReal[], 1.0}]} ]]

Image[tab2, ImageSize -> {500, 500}]

2nd try

POSTED BY: Douglas Youvan

Hi Douglas,

The fall colours have finished in Nova Scotia. Viewed directly, there isn't anything very spectacular, but when I put on my amber-tinted sunglasses, the reds become vibrant. So the sunglasses seem to give me normal colour vision.

Not only could MMA test for colourblindness, it could actually measure it and compensate. I've always wondered what normal people see.

Eric

POSTED BY: Eric Johnstone
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract