0001 % This script will help you find the RGB color displayed on your monitor that
0002 % appears gray in the photograph recorded by your camera. If you are working
0003 % with raw images, then this color will look gray to your camera without any
0004 % white balance mulitpliers applied. If you have a JPEG only camera, then the
0005 % color that will appear gray depends on the white balance setting used. Some
0006 % cameras can set a custom white balance on a target that saturates the CCD
0007 % resulting in white balance multipliers that are all 1 or at least all equal,
0008 % which is equivalent to no white balance at all. This trick can be used to
0009 % find the RGB color that looks gray to your JPEG only camera without white
0010 % balance.
0011 %
0012 % The RGB color that appears gray to your camera can be determined by solving a
0013 % set of simultaneous equations that relate a stimulus color (the color
0014 % displayed by the monitor) to the response color (the color recorded by the
0015 % camera). The parameters of the simultaneous equations, denoted M, are a set
0016 % of nine multipliers, three for each channel. The independent variable is the
0017 % stimulus, denoted S. The dependent variable is the reponse, denoted R.
0018 % M*S = R (eqn. 1)
0019 % if Srgb = [255   0   0; ...
0020 %              0 255   0; ...
0021 %              0   0 255]
0022 % then M*Srgb = Rrgb, and M = Rrgb*inv(Srgb)
0023 % therefore if Rgray is defined as [64; 64; 64]
0024 % then Sgray = inv(M)*Rgray, Sgray is the display's RGB color that looks gray
0025 % to the camera. Sgray most likely will not appear gray to the human eye.
0026 %
0027 % Before running this script, take a photograph of the monitor displaying solid
0028 % red (255, 0, 0), solid green (0, 255, 0), and solid blue (0, 0, 255). Use the
0029 % same camera settings for each picture. You should defocus or use a diffuser to
0030 % prevent recording the pixel pattern. If you are using this script to find the
0031 % best color to take flats, you should use a diffuser, because you need to use
0032 % the same focus for taking flats as you use for taking lights.
0033 %
0034 % The RGB color determined by this script will need to be fine-tuned to get it
0035 % to look gray to your camera. It may not be possible to get it to be exactly
0036 % gray, for example even when using an RGB color with no green (255, 0, 255)
0037 % the resulting photo still has a green cast.
0038 %
0039 % Once you've found the color your camera sees as gray, it can be used to take
0040 % flats that don't have a color cast or at least don't have a very strong color
0041 % cast. If you've found your camera's raw gray, then you should be able to use
0042 % this RGB color to set a custom white balance of equal multipliers. However,
0043 % this may not work perfectly.
0044 %
0045 % see % http://jethomson.wordpress.com/spectrometer-articles/rgb-flats/
0046 
0047 %-----
0048 ftype = 'PGM';
0049 access_bayer_pattern('gbrg');
0050 fl = list_dir(['data/A590/tests/camera_gray_test/e0/' ftype], '*', 1);
0051 
0052 % camera gray
0053 Rgray = [64; 64; 64];
0054 
0055 % display output/stimulus
0056 Srgb = [255 0 0; ...
0057         0 255 0; ...
0058         0 0 255];
0059 %-----
0060 
0061 if strcmpi(ftype, 'JPG')
0062     Srgb = sRGB2lin(Srgb);
0063     red_rsp = image_mean(sRGB2lin(fl{6})); % camera's response to red stimulus
0064     green_rsp = image_mean(sRGB2lin(fl{7}));
0065     blue_rsp = image_mean(sRGB2lin(fl{8}));
0066 else
0067     red_rsp = image_mean(fl{2});
0068     green_rsp = image_mean(fl{3});
0069     blue_rsp = image_mean(fl{4});
0070 end
0071 
0072 % row 1: red components of red, green, and blue responses
0073 % row 2: green components of red, green, and blue responses
0074 % row 3: blue components of red, green, and blue responses
0075 Rrgb = [red_rsp(1) green_rsp(1) blue_rsp(1); ...
0076         red_rsp(2) green_rsp(2) blue_rsp(2); ...
0077         red_rsp(3) green_rsp(3) blue_rsp(3)];
0078 
0079 
0080 % The backslash operator is faster but only works in this case because S is a
0081 % scaled identity matrix, 255*I. Therefore, M*S = S*M. However, if S were not a
0082 % scaled identity matrix, then M*S != S*M and one must use M = R*inv(S) instead.
0083 M = Srgb\Rrgb;
0084 
0085 %M*S = R  --> M = R*inv(S)
0086 %M = Rrgb*inv(Srgb)
0087 
0088 
0089 % Now determine the RGB value displayed by the LCD monitor that will result in
0090 % a gray image being recorded by the camera.
0091 % M*Sgray = Rgray
0092 % Sgray = inv(M)*Rgray
0093 if strcmp(ftype, 'JPG')
0094     Sgray = M\sRGB2lin(Rgray);
0095     Sgray = Sgray*(255/max(Sgray));
0096     display_color = round(lin2sRGB(Sgray))
0097 elseif strcmpi(ftype, 'PGM')
0098     Sgray = M\Rgray;
0099     Sgray = Sgray*(255/max(Sgray));
0100     display_color = round(Sgray)
0101 end