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