CS 465 Fall 2005 Homework 9 Solution ------------------------------------ (read this in a fixed-width font) 1.1 The pixel values (R_m, G_m, B_m) that are sent to the monitor go through the monitor's transfer function, scale the primary spectra to produce the monitor's output spectrum, and are then measured by the camera to produce the camera's (R_c, G_c, B_c). Transfer function: ?_l = (?_m/255)^gamma (where l stands for linear and ? is R, G, or B) Monitor spectrum: s = M_m * C_l where: [ | | | ] [ R_l ] M_m = [ s_r s_g s_b ] and C_l = [ G_l ] [ | | | ] [ B_l ] (s_r, s_g, s_b are the primary spectra of the monitor) Camera response: C_c = M_c * s where: [ --- r_r --- ] [ R_c ] M_c = [ --- r_g --- ] and C_c = [ G_c ] [ --- r_b --- ] [ B_c ] (r_r, r_g, r_b are the spectral sensitivity curves of the camera) So the whole thing is C_c = s * M_c * M_m * C_l where s is the unknown scale factor. We can find it using the information in the problem, by comparing M_c * M_m * [1;1;1] with the given result. In matlab, >> load m-rgb.txt >> load c-rgb.txt >> M_c = c_rgb(:,2:4)'; >> M_m = m_rgb(:,2:4); >> M_c * M_m ans = 1.3891 0.2020 0.1143 0.3831 1.2275 0.3718 0.1480 0.5920 1.0654 >> (M_c * M_m * [1;1;1]) ./ ([3175; 3691; 3361] / 4095) ans = 2.1996 2.1993 2.1996 ... and we conclude that s = 2.2. >> M_mc = 2.2 * M_c * M_m M_mc = 3.0561 0.4444 0.2514 0.8428 2.7005 0.8179 0.3256 1.3023 2.3439 ... and the final answer is C_c = M_mc * (X_m/255).^gamma. It was fine if your scale factor was different by a factor of 255 or 4095 or both. 1.2 The monitor's primary chromaticities are determined by the XYZ values of the monitor's primary spectra, and the x,y chromaticities are X/(X+Y+Z) and Y/(X+Y+Z). The XYZ values for the primary spectra are r_XYZ = M_x * s_r g_XYZ = M_x * s_g b_XYZ = M_x * s_b [ --- x-bar --- ] where M_x = [ --- y-bar --- ] [ --- z-bar --- ] where To compute these in Matlab: >> load xyz.txt >> M_x = xyz(:,2:4)'; >> prim_XYZ = M_x * M_m prim_XYZ = 2.4875 0.7996 0.8552 1.1841 2.7289 0.4451 0.0031 0.3169 4.4246 >> prim_xyz = prim_XYZ * diag(1./sum(prim_XYZ)) prim_xyz = 0.6769 0.2079 0.1494 0.3222 0.7096 0.0777 0.0008 0.0824 0.7729 The first two rows of this matrix are the (x,y) chromaticities of the three primaries. The plot is just a triangle with those three vertices. 1.3 First we compute the linear RGB values that I called C_l above, and then from that we compute the XYZ values, from which we get chromaticity. The first stage is just the inverse of part of the answer to problem 1.1: C_l = (M_mc)^-1 C_c The second stage looks much the same as 1.1, but uses the human color matching matrix rather than the camera's sensitivity matrix: c_XYZ = M_x * M_m * C_l The chromaticities can be computed by normalizing the XYZ to sum to 1. 1.4 The procedure of part 1.3 takes a camera RGB and generates XYZ. However, it can only do this because it knows it is looking at the display. If it was looking at an arbitrary spectrum, there'd be no way to know wheter the spectrum was the same one the monitor would produce or any one of the infinitely many other spectra that would result in the same camera RGB responses. These other spectra are metamers of the monitor's spectrum as far as the camera is concerned, but in general they would not be metamers for a human observer, so the result would be incorrect (we'd report the same XYZ because the RGBs are the same, despite the colors being distinct for a human observer).