tag:blogger.com,1999:blog-32785370047216160952024-03-21T10:20:13.528-07:00kindofdoon: The Blog of Daniel W. DichterDaniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.comBlogger36125tag:blogger.com,1999:blog-3278537004721616095.post-34995639989135486042022-01-23T22:57:00.036-08:002022-03-25T15:39:21.908-07:00Solving Wordle Heuristically<div><span style="font-family: helvetica;">I recently wrote a paper about solving the popular word game Wordle.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">A preprint may be found <a href="https://drive.google.com/file/d/1TbrYHy7V-iYIUfMnUkdhAZbKbTsZDRKd/" target="_blank">here</a>.</span></div><div><span style="font-family: helvetica;"><br /></span><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb2XWeU58WwjjqhPwb3PgVM4yEglUOUMveyLdy07edpoQcqFY0r_2b-oGvYb_OYTD2kCjXEjF4-JSDQ3kSWo0LW_xYDlL2CfiUeigoRRIquh3LBrmoWOv24z3hSlHyfvWcbm9t7Xd6zbnypOYP7DhjrCuLTN759GgyrtCzQI5MTsinksyMVuZL3Toyhg/s1221/pages.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="960" data-original-width="1221" height="504" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhb2XWeU58WwjjqhPwb3PgVM4yEglUOUMveyLdy07edpoQcqFY0r_2b-oGvYb_OYTD2kCjXEjF4-JSDQ3kSWo0LW_xYDlL2CfiUeigoRRIquh3LBrmoWOv24z3hSlHyfvWcbm9t7Xd6zbnypOYP7DhjrCuLTN759GgyrtCzQI5MTsinksyMVuZL3Toyhg/w640-h504/pages.PNG" width="640" /></a></div></div>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-54422048409697607302021-12-02T06:30:00.001-08:002021-12-02T06:31:27.885-08:00Low-Cost Visible Light Spectral Imaging<span style="font-family: helvetica;">My research paper "<a href="https://www.aic-color.org/resources/Documents/jaic_v27_04.pdf">Low-Cost Visible Light Spectral Imaging</a>" was recently published in the Journal of the International Colour Association.<br /><br />It describes how to produce informationally-complete, observer-independent, high-resolution measurements of light & color for less than 10% the cost of a hyperspectral camera.<br /><br />This paper improves upon the methods described in my earlier article "<a href="http://www.kindofdoon.com/2020/09/low-cost-hyperspectral-imaging.html">Low-Cost Hyperspectral Imaging</a>".<br /></span><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXg3_KppsqKVM_zlzA6OcvheB0Ql8WGUvtvCXiCoXEsbNef_1_c7F8R1mP1NT6nhu5mRA_COtcWRy9UCkqpfj3ppLWoJNnkzs1MoJXtApTi4vxYLoBHjZWaK_MPVfotTsI-uIF1lXhkEPD/s1400/paper_spread.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="803" data-original-width="1400" height="368" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXg3_KppsqKVM_zlzA6OcvheB0Ql8WGUvtvCXiCoXEsbNef_1_c7F8R1mP1NT6nhu5mRA_COtcWRy9UCkqpfj3ppLWoJNnkzs1MoJXtApTi4vxYLoBHjZWaK_MPVfotTsI-uIF1lXhkEPD/w640-h368/paper_spread.png" width="640" /></a></div><br /><div><br /></div>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-84931730671695277792020-10-18T20:47:00.032-07:002021-12-02T06:39:08.754-08:00Low-Cost Hyperspectral Imaging<div><span style="font-family: helvetica;"><i>Update 2021-12-02: This article has been obsoleted by subsequent improvements to the methodology; see "<a href="http://www.kindofdoon.com/2021/12/low-cost-visible-light-spectral-imaging.html">Low-Cost Visible Light Spectral Imaging</a>".</i></span></div><div><span style="font-family: helvetica;"><b><br /></b></span></div><div><span style="font-family: helvetica;"><b>Abstract</b></span></div><span style="font-family: helvetica;"><div><span style="font-family: helvetica;"><br /></span></div>Hyperspectral imaging is an emerging technology for capturing light and color more accurately and with finer granularity than conventional photography. It is most commonly used for machine vision tasks in medicine, agriculture, forensics, and manufacturing. </span><span style="font-family: helvetica;">Hyperspectral images may be thought of as pre-RAW, observer- and device-independent images, providing greater optionality in subsequent image processing. </span><span style="font-family: helvetica;">Adoption remains hindered by the high cost; turnkey commercial solutions typically cost $10-25k. Reducing cost and improving access would open the technology to new fields and users.</span><div><div><br /></div><div><div><span style="font-family: helvetica;">Presented here is an efficient, practical method for low-cost, hyperspectral, visible-light imaging at ~5% the cost of a commercial solution. </span><span style="font-family: helvetica;">It is a variant of the spectral scanning paradigm, using a bandpass filter set and the camera's built-in Bayer filter to </span><span style="font-family: helvetica;">form a semi-orthonormal vector space for SPD estimation with approximately 7 principal components. </span><span style="font-family: helvetica;">The hardware setup consists of a Canon 650D DSLR camera with a 40 mm prime lens, a subset of 5 filters from the </span><a href="https://midopt.com/filter-kits/fs100/" style="font-family: helvetica;">MidOpt FS100</a><span style="font-family: helvetica;"> bandpass filter kit, a tripod, a quick-release plate, and a remote shutter. </span><span style="font-family: helvetica;">A photo is captured with each filter under the same camera settings, and spectral power distributions (SPDs) are estimated at each pixel as linear combinations of the filter-attenuated sensitivity curves, with weights given by the associated photo RGB values. The SPDs are then non-dimensionalized against a simulated equal-intensity response, dimensionalized against a presumed illuminant, and corrected using a calibration profile. Reconstructed </span><span style="font-family: helvetica;">RGB images may be calculated from SPDs using standard observer functions, e.g. CIE 1931 2° XYZ to simulate human color perception. The method is validated against a chart of 108 paint color samples of independently known properties, showing reasonable agreement, and a calibration profile is established. Several real-world examples are shown.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKKGxNMV4op-3L8fRETMT8LImt86IWh0GFBuN50ekSEEj-ab1Rr-bhm5Prje1PcbEvZk2vqOddFEYvay4gO9AXUJ9G4c1GlZIRf47XGrnCF35xydQOPN4CjFMniUEl_O0Z3dnHZ_XCgHsk/s1584/Hyperspectral+Imaging+CONOPS+Annotations+%25281%2529.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="744" data-original-width="1584" height="301" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKKGxNMV4op-3L8fRETMT8LImt86IWh0GFBuN50ekSEEj-ab1Rr-bhm5Prje1PcbEvZk2vqOddFEYvay4gO9AXUJ9G4c1GlZIRf47XGrnCF35xydQOPN4CjFMniUEl_O0Z3dnHZ_XCgHsk/w640-h301/Hyperspectral+Imaging+CONOPS+Annotations+%25281%2529.png" width="640" /></a></div><span style="font-family: helvetica;"><div style="text-align: center;">Concept diagram - click to enlarge</div></span><div class="separator" style="clear: both; text-align: left;"><br /></div><div><div><span style="font-family: helvetica;"><b>Related Work</b></span></div><div><br /></div><div><span style="font-family: helvetica;">A number of authors have explored spectral imaging with ordinary cameras:</span></div><div><ul style="text-align: left;"><li><span style="font-family: helvetica;">Cosentino used 12 bandpass filters to estimate SPD in 2D spatially and compared results to a commercial spectral imaging system, showing good agreement. However, because the Bayer filter is discarded in conversion to grayscale, the quantity and cost of the filters are higher than necessary, 12 and approximately $2k respectively. [3]</span></li><li><span style="font-family: helvetica;">Baek et al. developed a single-shot method using an ordinary prism to induce diffraction grating on a camera's image sensor; computation then separates the combined spatial and wavelength information. Although accurate, this method requires construction of a specialized prism adapter and has limitations associated with requiring edges and the spatial sparsity of spectral cues. [6]</span></li><li><span style="font-family: helvetica;">Habel et al. similarly developed a single-shot method using diffraction grating; however it requires construction of a large and complex camera objective and its reconstructed images are limited to 120 x 120 pixels. [5]</span></li><li><span style="font-family: helvetica;">Seoung used a three-camera setup for SPD estimation, using small variations in camera sensitivities. An image registration process is used to align images between cameras using planarity. PCA is performed on a spectral database of Munsell colors to create a vector space for describing SPD as low-dimension linear combinations. A system of linear equations is solved at each pixel. [4]</span></li></ul></div><div><br /></div><div><span style="font-family: helvetica;">By comparison, the proposed method has the following advantages:</span></div><div><ul><li><span style="font-family: helvetica;">The camera's built-in Bayer filter is leveraged to reduce the required photo/filter pairs</span></li><li><span style="font-family: helvetica;">No requirement for planarity or high-contrast edges within the scene</span></li><li><span style="font-family: helvetica;">Image registration is not required</span></li><li><span style="font-family: helvetica;">Only a single camera is required</span></li><li><span style="font-family: helvetica;">All hardware is commercial-</span><span style="font-family: helvetica;">off-the-shelf; no construction required</span></li><li><span style="font-family: helvetica;">Total filter quantity and cost are minimized at 5 and $500 respectively</span></li><li><span style="font-family: helvetica;">SPD calculation is mathematically simple and computationally fast, occurring at the datacube (not pixel) level at megapixel scale</span></li><li><span style="font-family: helvetica;">Matrix inversion at each pixel is avoided for faster datacube-level linear algebra</span></li><li><span style="font-family: helvetica;">RAW images are not required</span></li></ul><div><b><span style="font-family: helvetica;"><br /></span></b></div><div><b><span style="font-family: helvetica;">Filtered Photo Capture and SPD Estimation</span></b></div></div></div><div><b><span style="font-family: helvetica;"><br /></span></b></div><div><span style="font-family: helvetica;">The essential goal of this method is to use a commodity camera in place of a hyperspectral camera. The key differences between the two types of camera are:</span></div><div><ul style="text-align: left;"><li><span style="font-family: helvetica;">A hyperspectral camera has near-uniform sensitivity over its domain; an ordinary camera has non-linear trichromate sensitivities that mimic the human eye.</span></li><li><span style="font-family: helvetica;">A hyperspectral camera has an adjustable filter system that allows it to reject all except the narrow wavelength band being measured; an ordinary camera's trichromate filters (found in the Bayer filter) are fixed and broad.</span></li></ul><span style="font-family: helvetica;"><div><span style="font-family: helvetica;"><br /></span></div></span></div><div><span style="font-family: helvetica;">The visible wavelength band spans approximately 400 to 700 nm. A visible-light hyperspectral camera may report SPD with a wavelength resolution of 5 or 10 nm. Thus, at each pixel, an SPD measurement comprises some 30-60 values. </span><span style="font-family: helvetica;">However, it has been shown empirically that 99% of observed color variance can be explained by 8 principal components in surface reflectance [4]; thus, SPDs may reasonably be estimated from much fewer than 30-60 measurements. Note that SPDs and reflectance differ by a factor of the illuminant, which is of lower dimensionality; SPDs may be thought of has having the same number of principal components as surface reflectance with decent approximation.</span></div><div><b><span style="font-family: helvetica;"><br /></span></b></div><div><span style="font-family: helvetica;">Ordinary cameras employ a Bayer filter to attenuate the spectral sensitivity of a camera to mimic that of the human eye. Bayer filters are an ultra-fine mosaic of red, green, and blue (R, G, B) sub-filters that cover the image sensor. An ordinary camera may be thought of as having uniform spectral sensitivity that is attenuated by the Bayer filter.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisAO2ZV322nqnFD_BHY-9UqSmvOulnuzS3vfG9JnLZLLMGgvk_ek4lpqnFNSEO36zE3h9vGb1XHHYQJOg1f5jaPTPqyff1unocNivpQqX_NO0TMs881Ug4KIXKYIpcH7KNnmSjGunhYTx3/s500/500px-Bayer_pattern_on_sensor.svg.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="325" data-original-width="500" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisAO2ZV322nqnFD_BHY-9UqSmvOulnuzS3vfG9JnLZLLMGgvk_ek4lpqnFNSEO36zE3h9vGb1XHHYQJOg1f5jaPTPqyff1unocNivpQqX_NO0TMs881Ug4KIXKYIpcH7KNnmSjGunhYTx3/s16000/500px-Bayer_pattern_on_sensor.svg.png" /></a></div><br /><div style="text-align: center;"><span style="font-family: helvetica;">Bayer filter illustration, showing red, green, and blue sub-filters on an image sensor. Source: <a href="https://en.wikipedia.org/wiki/Bayer_filter">Wikipedia</a>.</span></div></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><span>In essence, ordinary photos represent the dot product of the camera's spectral sensitivity with the SPDs of the scene, at each pixel, for each color channel. These dot product values become RGB values after minor processing, such as demosaicing, white balance, levels, etc. </span>Note that a dot product is fundamentally a lossy operation; in a photo, the SPD itself is not measured, only its dot products.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">A filter placed in front of a camera's lens further attenuates its spectral sensitivity. This attenuation is described by the filter's transmission spectrum, which reports the fraction of light admitted as a function of its wavelength. This attenuation occurs as a simple element-wise multiplication, i.e. wavelength-by-wavelength. The filter may be thought of as modifying the spectral sensitivity of the camera by attenuation.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">A system of equations are developed to describe filtered photo capture and SPD estimation, beginning with the following definitions:</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfcFc4VTLTwvhinggb5ia_AgjJdSQSjWw3AUqtqbzdaoIi9ujnpHdfeJiVCxYJ3oWU8XvKY5PbFSClN-70emlvkHakbYSTipJzqvavDqq2V751JAkpJoQUz0vJLOO7ZDZ_w96VPctmYWE3/s633/equations_1.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="367" data-original-width="633" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfcFc4VTLTwvhinggb5ia_AgjJdSQSjWw3AUqtqbzdaoIi9ujnpHdfeJiVCxYJ3oWU8XvKY5PbFSClN-70emlvkHakbYSTipJzqvavDqq2V751JAkpJoQUz0vJLOO7ZDZ_w96VPctmYWE3/s16000/equations_1.PNG" /></a></div><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;">The process of filtered photo capture is modeled as follows:</span></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqXPwPpWhGgpaOwQSvhm7kLAXwatOAo3w1stTMM4ji0YzPTOjhWV86dX4MQMygTPn8hTrl-Y49hfIwOztxDtFqSqYPnVk9CIZA0Uebbez5Lk2trWesTiCMxNke2Rof_FyjswQfrb0TWCxF/s399/equations_2.PNG" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: helvetica;"><img border="0" data-original-height="51" data-original-width="399" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqXPwPpWhGgpaOwQSvhm7kLAXwatOAo3w1stTMM4ji0YzPTOjhWV86dX4MQMygTPn8hTrl-Y49hfIwOztxDtFqSqYPnVk9CIZA0Uebbez5Lk2trWesTiCMxNke2Rof_FyjswQfrb0TWCxF/s16000/equations_2.PNG" /></span></a></div><span style="font-family: helvetica;"><br /></span><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;">The process is described in terms of proportionality rather than equality, to avoid dimensionalizing the SPD and modeling finer details such as ISO and shutter speed.</span></div></div></div></div></div><div><div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;">A set of "ST" curves are calculated, equal in quantity to the number of photo color channels, 3, times the number of filters, 5, for 15 total. This quantity is equal to the total number of color measurements per pixel:</span></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_KapYUSfVbLiBJRO4gnleo3cS0OxBov41GoZMPu1HRlIoKxE8YL9Igi-bAPBbItkslhjWPhXoL95pKz9jKbI1d5GdPdVlmEs2z9qWKdKsT7BtM-fvWgzW1AlENdEE50-NBRkkqrjSD8hm/s425/equations_3.PNG" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: helvetica;"><img border="0" data-original-height="32" data-original-width="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_KapYUSfVbLiBJRO4gnleo3cS0OxBov41GoZMPu1HRlIoKxE8YL9Igi-bAPBbItkslhjWPhXoL95pKz9jKbI1d5GdPdVlmEs2z9qWKdKsT7BtM-fvWgzW1AlENdEE50-NBRkkqrjSD8hm/s16000/equations_3.PNG" /></span></a></div><span style="font-family: helvetica;"><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">It is convenient to define a single "st" index as a composite of the filter/photo index and color channel index. The vector U is then calculated as the sum of all ST curves over the st index:</span></div><br /></span><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihpSo1nIlDfTWE5KyYZUnPk35Rqi8hu92WAmbk-9-JHaRD-5hIbZEov9PjeNceW6CE7BAH76_6aRI7IOkiGHemwbfvpGysKx9T43TeglqU9crjU6xzYvin_y3vfDNlReCH0uegnjMwHkao/s177/equations_4.PNG" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: helvetica;"><img border="0" data-original-height="52" data-original-width="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihpSo1nIlDfTWE5KyYZUnPk35Rqi8hu92WAmbk-9-JHaRD-5hIbZEov9PjeNceW6CE7BAH76_6aRI7IOkiGHemwbfvpGysKx9T43TeglqU9crjU6xzYvin_y3vfDNlReCH0uegnjMwHkao/s16000/equations_4.PNG" /></span></a></div><span style="font-family: helvetica;"><br />Finally, SPDs are reconstructed as linear combinations of the ST curves weighted by the associated photo values scaled 0-1, which are then normalized by U 0-1, then scaled by the illuminant and calibration curves:</span></div><div><span style="font-family: helvetica;"><br /></span><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBSgZFOPECm6MWWrT1Z9u6REaEuCPb_LpMvPKVg5zicJkAsoaRC20o9y2uWTbfT8FNtEAoIcy5FRaO8Ng57gBSSbJGrNQp2c5-jb1QFRSkv3KSH5f2vNtS40Pgg2Yusyb7o_X6MvoNzkPO/s427/equations_5.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="61" data-original-width="427" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBSgZFOPECm6MWWrT1Z9u6REaEuCPb_LpMvPKVg5zicJkAsoaRC20o9y2uWTbfT8FNtEAoIcy5FRaO8Ng57gBSSbJGrNQp2c5-jb1QFRSkv3KSH5f2vNtS40Pgg2Yusyb7o_X6MvoNzkPO/s16000/equations_5.PNG" /></a></div></div></div><div><div><span style="font-family: helvetica;"><br /></span></div><div><b><span style="font-family: helvetica;">Image Reconstruction from SPDs</span></b></div><div><b><span style="font-family: helvetica;"><br /></span></b></div><div><span style="font-family: helvetica;">Images can be reconstructed from SPDs standard methods. [7] </span><span style="font-family: helvetica;">The preceding discussion has neglected the subject of units/scaling due to the associative nature of the equations. However, scaling becomes important in image reconstruction due to the fixed limits of the color space.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">Any set of observer functions (e.g. for a population, camera, individual, etc.) can be used for image reconstruction. The most common of these is the </span><span style="font-family: helvetica;">1931 CIE 2° XYZ observer. [8] Taking the dot product of the SPD at each pixel with each of the observer sensitivity curves, an XYZ tristimulus color is obtained. These XYZ colors are then normalized 0-1 and converted to RGB for display.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV7fYjLRDyTI6Se-23XpltC_UITYark_Jaxwfa32ovGqVUzLPY7WwTXK-TOzPMdZvr3Z02X6-WMVyflDXWh_cOJtEiCB_upBxNWezKbttZRQuS2EH82PnsilSIVVHyYEqe3luWh9Atfp62/s398/observer_cie_1931_2_deg_XYZ.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV7fYjLRDyTI6Se-23XpltC_UITYark_Jaxwfa32ovGqVUzLPY7WwTXK-TOzPMdZvr3Z02X6-WMVyflDXWh_cOJtEiCB_upBxNWezKbttZRQuS2EH82PnsilSIVVHyYEqe3luWh9Atfp62/s16000/observer_cie_1931_2_deg_XYZ.png" /></a></div></div><div style="text-align: center;"><span style="font-family: helvetica;">Standard tristimulus observer functions for image reconstruction from SPDs</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">Because SPDs are relative, not absolute, the sensor has no ability to set the black point and white point in the image. Instead, the operator may manually specify where these limits occur according to their knowledge of the scene, or aesthetic g</span><span style="font-family: helvetica;">oals for the image. They may also elect to scale their image to the limits of the color space for maximum contrast, although this is generally unlikely to produce perceptually accurate colors.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">A simple default scaling method is suggested here:</span></div><div><ul style="text-align: left;"><li><span style="font-family: helvetica;">Convert the image to grayscale.</span></li><li><span style="font-family: helvetica;">Calculate the probability density function (PDF) of the image pixel values.</span></li><li><span style="font-family: helvetica;">Calculate the cumulative distribution function (CDF) as the cumulative sum of the PDF.</span></li><li><span style="font-family: helvetica;">Look up the values corresponding to 1% and 99% in the CDF</span></li><li><span style="font-family: helvetica;">Using </span><span style="font-family: courier;"><a href="https://www.mathworks.com/help/images/ref/imadjust.html">imadjust</a></span><span style="font-family: helvetica;"> or equivalent</span><span style="font-family: helvetica;">, scale the value range of the image so that 1% and 99% on the CDF correspond to 5% and 95% on the value range</span></li></ul></div><div><span style="font-family: helvetica;">These values are good for default general-purpose scaling, but may be adjusted depending on the specific scene being imaged.</span></div><div><br /></div><div><span style="font-family: helvetica;"><b>Computational Approach</b></span></div><div><span style="font-family: helvetica;"><b><br /></b></span></div><div><span><span style="font-family: helvetica;">All computation described in this article is implemented in MATLAB. Although SPDs may be calculated pixel-by-pixel, this approach scales poorly to multiple-megapixel images. Instead, SPDs are calculated at the datacube level using </span><a href="https://www.mathworks.com/help/matlab/ref/reshape.html"><span style="font-family: courier;">reshape</span></a><span style="font-family: helvetica;"> and </span><a href="https://www.mathworks.com/help/matlab/ref/repmat.html"><span style="font-family: courier;">repmat</span></a><span style="font-family: helvetica;"> to eliminate multiple </span></span><span style="font-family: courier;">for</span><span style="font-family: helvetica;"> loops and leverage MATLAB's matrix math efficiency. </span><span style="font-family: helvetica;">This works as follows:</span></div><div><ol style="text-align: left;"><li><span style="font-family: helvetica;">Initialize an SPD datacube with zeros for all entries, measuring m-by-n-w, for photos of resolution n-by-m and w wavelengths</span></li><li><span style="font-family: helvetica;">Pick an ST curve</span></li><li><span style="font-family: helvetica;">Retrieve the color channel of the photo corresponding to this ST curve</span></li><li><span style="font-family: helvetica;">Reshape the ST curve along the 3rd (wavelength) dimension with </span><span style="font-family: courier;">reshape</span></li><li><span style="font-family: helvetica;">Repeat the ST curve at each pixel with </span><span style="font-family: courier;">repmat</span></li><li><span style="font-family: helvetica;">Repeat the color channel at each wavelength with </span><span style="font-family: courier;">repmat</span></li><li><span style="font-family: helvetica;">Calculate the element-wise product of the color datacube and the ST datacube</span></li><li><span style="font-family: helvetica;">Add this result to the SPD datacube</span></li><li><span style="font-family: helvetica;">Repeat back to Step 2 for all remaining ST curves</span></li><li><span style="font-family: helvetica;">Divide the SPD datacube by the sum of all ST curves, similarly reshaped and repeated</span></li><li><span style="font-family: helvetica;">Multiply the SPD datacube by the illuminant and calibration curves, similarly reshaped and repeated</span></li></ol><div><span style="font-family: helvetica;"><br /></span></div></div><div><span style="font-family: helvetica;">Depending on the camera and filter set, some wavelengths may have zero or near-zero sensitivity. This commonly occurs at the fringes of the visible light spectrum, where the camera is least sensitive. At these wavelengths, the SPD is undefined, or nearly so. </span><span style="font-family: helvetica;">To address this, wavelength channels corresponding to a sensitivity of < 1% of the peak value are discarded, and set equal to the closest non-discarded wavelength channel. Depending on the specific camera-filter system, it may be preferable in other cases to interpolate or extrapolate instead.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">This "insensitivity" check is performed on U, the sum of the ST curves over the st index, shown below. It may be thought of as the overall sensitivity of the camera/filter system, as a function of wavelength. For a truly non-overlapping filter set, e.g. for a narrow bandpass filter set, U would have a sawtooth shape, and interpolation would be preferable in the insensitive regions between peaks. For the regular bandpass filter set under consideration, overlap occurs, and insensitivity occurs only at the extremes of the domain, where the SPDs from the closest "sensitive" wavelength are simply copied, or held.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiStxqR9DA4QbzjUu85AHU4zbo-xEj9qy_wuwzSbxBWH5i7STpw-qWYelOQ0Mok4sdjP2mDm8PthpoHo0yeO3HgPCl9hWl_MPUI8rOFc4IQcFeMzy8gQ59IGd_OUPH61-TucIZnd2nc3lPO/s392/U_sum_of_ST.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="280" data-original-width="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiStxqR9DA4QbzjUu85AHU4zbo-xEj9qy_wuwzSbxBWH5i7STpw-qWYelOQ0Mok4sdjP2mDm8PthpoHo0yeO3HgPCl9hWl_MPUI8rOFc4IQcFeMzy8gQ59IGd_OUPH61-TucIZnd2nc3lPO/s16000/U_sum_of_ST.png" /></a></div></div><div style="text-align: center;"><span style="font-family: helvetica;">Overall sensitivity, used to normalize and determine of where to interpolate/extrapolate</span></div><div style="text-align: center;"><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><b>Filter Set Selection</b></span></div><div><span style="font-family: helvetica;"><b><br /></b></span></div><div><span style="font-family: helvetica;">As discussed in Seeoung et al. [4], real-world reflectance spectra can empirically be decomposed into approximately 8 principal components, supposing > 99% of variance is to be explained. SPDs differ from reflectance by a factor of the illuminant, which by inspection is of lower dimensionality for everyday cases. [8] [9]</span></div><div><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIvQT5wAlspMYv_4tUuKRWIbmhGe8FJ3v4oeosBUi3xEOa8tKz0fNtP53jNYaekmR2aFyb4gTkx4XRL-QLgfJal3Ltil8o34l3ThL8ae2GIj0UkQ_x_DUSpxmL0VTsf2CeHfbVRH61nrT0/s510/illuminant_comparison.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="417" data-original-width="510" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIvQT5wAlspMYv_4tUuKRWIbmhGe8FJ3v4oeosBUi3xEOa8tKz0fNtP53jNYaekmR2aFyb4gTkx4XRL-QLgfJal3Ltil8o34l3ThL8ae2GIj0UkQ_x_DUSpxmL0VTsf2CeHfbVRH61nrT0/s16000/illuminant_comparison.png" /></a></div><div style="text-align: left;"><br /></div><div><span style="font-family: helvetica;">From the perspective of sensor design, this indicates that SPDs should be well-approximated by 8 values distributed evenly over the visible wavelength band of roughly 400 to 700 nm, equivalent to a spectral resolution of approximately 43 nm. Between these wavelength values, interpolation can be used to good approximation. </span><span style="font-family: helvetica;">For an image sensor with monochromatic sensitivity, this would necessitate at least 8 filters. However, the </span><span style="font-family: helvetica;">trichromate</span><span style="font-family: helvetica;"> </span><span style="font-family: helvetica;">sensitivity of ordinary cameras can be used to decrease the filter count.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">The principal components of a camera/filter set system can be evaluated using the ST matrix shown ab</span><span style="font-family: helvetica;">ove:</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicAjncgHBPUpkyBFEev_e1S3HSjVAF96nRDhy1UVoMfRf5Q1qnuJMsi_vV8CuGIpY25HSTzGVqYuWkmlmBq3hRbl1mApW8tkyXnSc-K-AEn3S6g2Qs5KLKBvrLfVmaBs5bLMKTbi-hXFJS/s425/equations_3.PNG" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: helvetica;"><img border="0" data-original-height="32" data-original-width="425" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicAjncgHBPUpkyBFEev_e1S3HSjVAF96nRDhy1UVoMfRf5Q1qnuJMsi_vV8CuGIpY25HSTzGVqYuWkmlmBq3hRbl1mApW8tkyXnSc-K-AEn3S6g2Qs5KLKBvrLfVmaBs5bLMKTbi-hXFJS/s16000/equations_3.PNG" /></span></a></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">which expands as follows:</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLjChAt-On9plCSA3wOpseVaMxEbGMliZPUlvKYXujwQfkEpFHdas27JsIBdusgIhw-we5HmT61kWGNWJnKqmKLqFX3MHil3la29tobzYPMXN3S-cRJqC-77Q8-tCipPxOJU3atLBuZxf9/s369/sys_lin_eq_ST.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="307" data-original-width="369" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLjChAt-On9plCSA3wOpseVaMxEbGMliZPUlvKYXujwQfkEpFHdas27JsIBdusgIhw-we5HmT61kWGNWJnKqmKLqFX3MHil3la29tobzYPMXN3S-cRJqC-77Q8-tCipPxOJU3atLBuZxf9/s16000/sys_lin_eq_ST.PNG" /></a></div><br /><span style="font-family: helvetica;">where 1, 2, 3, ... λ denotes the wavelength index and a, b, c, ... st denotes the ST index.</span></div><span style="font-family: helvetica;"><br />At an arbitrary pixel, the ST matrix can be used to set up an over-defined system of linear equations per the photo capture expression:</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; margin-left: 1em; margin-right: 1em;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKv8iJWNvVQD6bJV3DOGidhlqSPZ53eXFLeOCDoRg_ilSr54c5P04dAOTmAMxs4RpblBrc9DqeykrFZdkIXO95wMm8X6ow-O4ZYuZAORG8nv_oD-y55c2isFs-3OXtihQNRMkRcx0aUzGI/s143/sys_lin_eq_compact.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="24" data-original-width="143" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKv8iJWNvVQD6bJV3DOGidhlqSPZ53eXFLeOCDoRg_ilSr54c5P04dAOTmAMxs4RpblBrc9DqeykrFZdkIXO95wMm8X6ow-O4ZYuZAORG8nv_oD-y55c2isFs-3OXtihQNRMkRcx0aUzGI/s0/sys_lin_eq_compact.PNG" /></a></span></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVu7L9HN_td12DSM298Eau01V5ro3ppsknsuETB5-BymrWr3M4G9XoYYMkxj6PqDGiUUffJIlWd2K58Ygz1OmI16HyCyvluW9_dYiVkHBZEyB_itIbTDxb_6LIW47m3GaTu89mUlhIB7vu/s482/sys_lin_eq_expanded.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="309" data-original-width="482" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVu7L9HN_td12DSM298Eau01V5ro3ppsknsuETB5-BymrWr3M4G9XoYYMkxj6PqDGiUUffJIlWd2K58Ygz1OmI16HyCyvluW9_dYiVkHBZEyB_itIbTDxb_6LIW47m3GaTu89mUlhIB7vu/s16000/sys_lin_eq_expanded.PNG" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;">where COL is a vector of color measurements, and SPD is a vector of the spectral power distribution.</span></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;">This system of linear equations is equivalent to the canonical </span><span style="font-family: helvetica;">Ax=b </span><span style="font-family: helvetica;">formulation with a known measurement vector b (COL), known transformation matrix A (ST), and unknown predictor vector x (SPD). It is mathematically possible to solve this over-defined system directly, e.g. with a linear least-squares (LLS) method:</span></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: helvetica;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzptNayQJnrdCtCFc0kjjrc2ZeN0dRKZSGHfAO1Fy-VRvFFJHWGj7YHesp6ll49krugl7oUtclwYM9rXyjbhBylBcIWP-Zr_cJ5BxTDA1HoldAg8xTFYMNZo0FqgVEEgoIPA7iBGpqXGgf/" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="69" data-original-width="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzptNayQJnrdCtCFc0kjjrc2ZeN0dRKZSGHfAO1Fy-VRvFFJHWGj7YHesp6ll49krugl7oUtclwYM9rXyjbhBylBcIWP-Zr_cJ5BxTDA1HoldAg8xTFYMNZo0FqgVEEgoIPA7iBGpqXGgf/s16000/image.png" /></a></div><br />However, the ST matrix tends to be poorly conditioned, producing non-physical and non-convergent results for SPD if using LLS. LLS is also prohibitively slow at megapixel scale.</span></div></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">Nevertheless, the ST matrix is still useful for principal component analysis (PCA), to estimate the spectral resolution of the camera / filter set system. Because PCA is a function only of the transformation matrix ST, it can be performed in the absence of any photo data, and is a powerful tool for evaluating filter sets.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">It can be shown using PCA that the ideal filter set has transmission spectra with minimal overlap and maximum uniformity. </span><span style="font-family: helvetica;">If the spectra do not overlap, the filters are orthogonal in SPD vector space, and their utility in terms of PC per filter is maximized. </span><span style="font-family: helvetica;">It follows that ideal filters have "spike" spectra that measure a single wavelength only. In practice, this is best realized with a series of bandpass filters with minimal FWHM.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">Using this PCA approach, several filter sets were evaluated, ranging in quantity from 5 to 12, and in cost from $30 to $3,500. These included options from Thorlabs, Edmund Optics, MidOpt, and PixelTeq. These fell roughly into the following tiers:</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQbXfMLHbY42spQjP9zZKb3vYiJgk9bWIu96uNIU4XsXfMAm1DVJfSU228J_1p2_bILO9qYN4_EDA_OWp3toTFmij23rqmWFWI4pMiNdxul6G-uiC7VJunLNtvxjD4c9bsv2rktEzY286I/s683/filter_tier_list.png" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: helvetica;"><img border="0" data-original-height="88" data-original-width="683" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQbXfMLHbY42spQjP9zZKb3vYiJgk9bWIu96uNIU4XsXfMAm1DVJfSU228J_1p2_bILO9qYN4_EDA_OWp3toTFmij23rqmWFWI4pMiNdxul6G-uiC7VJunLNtvxjD4c9bsv2rktEzY286I/s16000/filter_tier_list.png" /></span></a></div><span style="font-family: helvetica;"><div style="text-align: center;">Comparison of filter set tiers by key cost and performance metrics; selection highlighted</div></span><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><br /></span></div><span style="font-family: helvetica;">The tiers differ significantly in terms of cost and performance. Gel-like color filters are very cheap, [2] but because their transmission spectra are arbitrary and usually non-zero nowhere, they overlap significantly, and it is practically difficult to develop more than 5 PC. Further, they usually lack published transmission data. Bandpass filters with 60-90 FWHM are more expensive but get much closer to the target of 8 PC. Their relatively broad FWHM limits the maximum number of useful filters than can be used to ~5, and the PC count to ~7. Narrow bandpass filters with 20-40 FWHM are more expensive yet but offer greater optionality. They can be made to develop as many as 14 PC. 8 PC is also achievable, but still at substantially greater cost than with regular bandpass filters and 7 PC, at ~$1,400 vs.$500.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">Size and form factor/deployability were also considered. The ~43 mm diameter size required is relatively large relative to typical offerings, which commonly are limited to 1" [25.4 mm]. Many filter kits come in large, bulky cases, or are unmounted.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">Ultimately, the <a href="https://midopt.com/filter-kits/fs100/">MidOpt FS100</a> was selected. At $500 and 10 filters, it is an outlier in value, despite only 5 of the 10 filters being useful for visible light imaging. The swiveling fan form factor is ideal for no-contact lens filtering, as it can be operated with one hand, protects the filters, and is extremely compact when collapsed.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi01YqkGnx-frvaI-_QttpaPjsLrDPwWisFZ54tup3QNUIe__TTSUj8k5CH49crliHvafT6mL_XLA-Lnsj4FDGtt624V2pHBnvPiSRM5fR7ya4kkBIRBsSC-FY-F_9Zj5mHYxDdmO-Wzl0M/s576/MidOpt_FS100_swatch-filter-kit.jpg" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: helvetica;"><img border="0" data-original-height="562" data-original-width="576" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi01YqkGnx-frvaI-_QttpaPjsLrDPwWisFZ54tup3QNUIe__TTSUj8k5CH49crliHvafT6mL_XLA-Lnsj4FDGtt624V2pHBnvPiSRM5fR7ya4kkBIRBsSC-FY-F_9Zj5mHYxDdmO-Wzl0M/w320-h312/MidOpt_FS100_swatch-filter-kit.jpg" width="320" /></span></a></div><span style="font-family: helvetica;"><div style="text-align: center;"><a href="https://midopt.com/filter-kits/fs100/">MidOpt FS100</a> Filter Swatch Kit</div><div style="text-align: center;"><br /></div></span></div><div><span style="font-family: helvetica;">Several filters in the FS100 kit are not useful for this application as they either operate outside the visible light range, are polarizing filters, or excessively overlap another filter. The useful subset of filters were removed and re-bound using a shorter brass binding post:</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghQqCzvmqcjo9SOIJG87e_dw-qOykcRrxQ-LcFpNwvefmTWiJH56ipYKEnH0m5vzW569fxb8hhmKCcQC3x6dC6_n-aj0CIsa7wl2XaSxDsuABOxTd5s8oGDs69SDMAmEEv7u4TmbSca_ZV/s1776/midopt_fs100_subset_calibrated.jpg" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: helvetica;"><img border="0" data-original-height="1592" data-original-width="1776" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghQqCzvmqcjo9SOIJG87e_dw-qOykcRrxQ-LcFpNwvefmTWiJH56ipYKEnH0m5vzW569fxb8hhmKCcQC3x6dC6_n-aj0CIsa7wl2XaSxDsuABOxTd5s8oGDs69SDMAmEEv7u4TmbSca_ZV/s320/midopt_fs100_subset_calibrated.jpg" width="320" /></span></a></div><div style="text-align: center;"><span style="font-family: helvetica;">Subset of useful filters from MidOpt FS100</span></div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">The filter colors appear artificially warm in this picture due to their red-orange reflective coatings. The final filter subset is:</span></div><div><ol style="text-align: left;"><li><span style="font-family: helvetica;">MidOpt <a href="https://midopt.com/filters/bp470/">BP470</a>, FWHM 85 nm, blue</span></li><li><span style="font-family: helvetica;">MidOpt <a href="https://midopt.com/filters/bp525/">BP525</a>, FWHM 80 nm, light green</span></li><li><span style="font-family: helvetica;">MidOpt <a href="https://midopt.com/filters/bp590/">BP590</a>, FWHM 75 nm, orange</span></li><li><span style="font-family: helvetica;">MidOpt <a href="https://midopt.com/filters/bp635/">BP635</a>, FWHM 60 nm, light red</span></li><li><span style="font-family: helvetica;">MidOpt <a href="https://midopt.com/filters/bp660/">BP660</a>, FWHM 65 nm, dark red</span></li></ol></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRC7XD0jA2oqXxyxtQ636MEw9Tp8ocagWaKBQQ4uwMJLxkbWfO-oNlDTW4ZznT8MNS4vInrW3GukBcW9tQyp0GHRAvWG5h6F6td-bbFrRJ2X_6qOK1Wql-iKbHswESGXfYjdFX_r1f554C/s507/midopt_fs100_transmissions.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="507" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRC7XD0jA2oqXxyxtQ636MEw9Tp8ocagWaKBQQ4uwMJLxkbWfO-oNlDTW4ZznT8MNS4vInrW3GukBcW9tQyp0GHRAvWG5h6F6td-bbFrRJ2X_6qOK1Wql-iKbHswESGXfYjdFX_r1f554C/s16000/midopt_fs100_transmissions.png" /></a></div><div style="text-align: center;"><span style="font-family: helvetica;">Bandpass transmission spectra for filters chosen from MidOpt FS100 kit</span></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXAyBQqZO1C-iM246ajHzAUatEAJ26gfnDpOrXBq3eBf4_K9oux3kNZGaTiMf3WpTpYcJdhKpAZXjv2JbDxcOns2I6q0aiaIP9vGYc8yKISKxZKS19Z_byTZFw1RN3oONO46z3R3MY5DUs/s556/midopt_fs100_colors.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="156" data-original-width="556" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXAyBQqZO1C-iM246ajHzAUatEAJ26gfnDpOrXBq3eBf4_K9oux3kNZGaTiMf3WpTpYcJdhKpAZXjv2JbDxcOns2I6q0aiaIP9vGYc8yKISKxZKS19Z_byTZFw1RN3oONO46z3R3MY5DUs/s16000/midopt_fs100_colors.png" /></a></div></div><div style="text-align: center;"><span style="font-family: helvetica;">Colors for filters chosen from MidOpt FS100 kit - for visual check only, not used in calculation</span></div><div><span style="font-family: helvetica;"><b><br /></b></span></div><div><span style="font-family: helvetica;">This filter set is shown to have 7 PC of diminishing explanative power, using the same standard as Seoung et al.: [4]</span></div><div><span style="font-family: helvetica;"><b><br /></b></span></div><div><span style="font-family: helvetica;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8kGDWHTE23BBEHDaWYGX6JnrpKpvvaaWh36-f8zFuvMaP-5AveDYYJ4GBKmySj-LOy3l6pvaldTQvOB2PJZAMzBBj8caFyJjtrIJ6-CtNMR7dYsDcGmQVAWKSyT8s4x1HEZI8ZsvSFsCS/s395/sensor_PCA.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="395" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8kGDWHTE23BBEHDaWYGX6JnrpKpvvaaWh36-f8zFuvMaP-5AveDYYJ4GBKmySj-LOy3l6pvaldTQvOB2PJZAMzBBj8caFyJjtrIJ6-CtNMR7dYsDcGmQVAWKSyT8s4x1HEZI8ZsvSFsCS/s16000/sensor_PCA.png" /></a></div><div class="separator" style="clear: both; text-align: center;">Principal component analysis of camera/filter system, showing ~7 PC</div><div class="separator" style="clear: both; text-align: center;"><br /></div></span></div><div><span style="font-family: helvetica;"><b>Photographic Aspects</b></span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><i>Camera Selection</i></span></div><div><span style="font-family: helvetica;"><i><br /></i></span></div><div><span style="font-family: helvetica;">It is a prerequisite for this method that the spectral sensitivity of the camera is known. This data is not typically reported by the manufacturer, nor can it be measured without specialized equipment. Fortunately, literature provides data for some common models, most prominently Jiang et al. who published a database of 28 models in 2013, which is used in this study. [1]</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">In some cases, it may be acceptable to use a similar camera's data, particularly if the manufacturer is the same and the model year/type is similar. Because camera spectral sensitivities are designed to mimic the human eye, they generally resemble standard observer functions with minor deviations.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-6JgfzxkdySvxdo1jvP8Kk_BHx-a3iEcn0iDtFrBCPR_RFjRoTF-UxRpoclmaI9EYlHO_Fl1woU1mtgD7nLNjuLLUKQ2DE9jmpQdF4r4y76fW3ViziCRSH196mZ0Yg6fMbOBQso5Yd7sO/s507/canon_spectral_sensitivities.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="417" data-original-width="507" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-6JgfzxkdySvxdo1jvP8Kk_BHx-a3iEcn0iDtFrBCPR_RFjRoTF-UxRpoclmaI9EYlHO_Fl1woU1mtgD7nLNjuLLUKQ2DE9jmpQdF4r4y76fW3ViziCRSH196mZ0Yg6fMbOBQso5Yd7sO/s16000/canon_spectral_sensitivities.png" /></a></div><div style="text-align: center;"><br /></div><span style="font-family: helvetica;">In this study, photos are captured with a Canon 650D, with sensitivity data given by the similar Canon 600D. </span></div><div><span style="font-family: helvetica;"><i><br /></i></span></div><div><span style="font-family: helvetica;"><i>Photo Capture</i></span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">Minimizing perturbation of the camera while capturing the photo stack is critical. To this end, a tripod and remote shutter are used. The filters are neither attached to nor in contact with the camera at any time; they are simply held in front of the lens by hand at a distance of approximately 1/4". A prime (i.e. non-zoom, or fixed focal length) lens is preferable as it has one fewer degree of freedom than a zoom lens, and is less prone to perturbation and backlash. Prime lenses also have smaller apertures than zoom lenses, which enables use of smaller filters. </span><span style="font-family: helvetica;">A Canon 40 mm prime lens is used in this study, chosen for its generality and naturalistic field of view. Accounting for the crop-sensor of the Canon 650D, the effective focal length is approximately 65 mm.</span></div><div><span style="font-family: helvetica;"><span style="font-family: helvetica;"><br /></span></span></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica; margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1163" data-original-width="2704" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiilBvSTenjqql-EbPnfYUcjZnE-6iZR-y9SCWomr5uNmNjyfK48R3G_2QaiC71ZrtbK9lcZJqPkMkjDgZeS5zPwg99IzZdq4t9-2otVTLMY6aQPPZsWNZkf7SlyYtO-GL0TfZscFxsMpHm/w640-h276/photo_setup.jpg" width="640" /></span></div><div><span style="font-family: helvetica;"></span></div><div><span style="font-family: helvetica;"><div style="font-family: "Times New Roman";"><div style="text-align: center;"><span style="font-family: helvetica;">Photography setup: filter fan in left hand, remote shutter in right hand; no contact with camera</span></div></div></span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">Since this method deliberately avoids the RAW format, care must be taken to avoid saturating the limits of the color space while capturing photos, particularly by overexposure. Saturation occurs in color channels individually before the corresponding grayscale image saturates; therefore the R, G, and B histograms should be inspected individually, rather than the grayscale histogram by itself.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">ISO and exposure time should be minimized to reduce sensor noise and blurriness, while still ensuring that the image adequately spans the color space. The specific settings for ISO and exposure time will vary depending on the subject and imaging goals. White balance should be set to match the scene as best as possible.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">It is advisable to take several test photos without a filter to correct the camera settings before capturing the photo stack. The goal should be to get the unfiltered photo just shy of overexposure, so that the filtered photos have maximum dynamic range without saturation. Because the MidOpt filters have a very high peak transmission of 90-100%, no adjustment of ISO or shutter speed is necessary between t</span><span style="font-family: helvetica;">he test photos and the stack photos. These test photos also serve as a qualitative check for the reconstructed images.<br /><br /><b>Validation and Calibration<br /></b><br />SPD estimates are compared against samples of known properties - specifically, a color chart consisting of 108 samples of oil paint mixtures </span><span style="font-family: helvetica;">spanning the color gamut, originally developed by painter Richard Schmid. [10] [11] </span><span style="font-family: helvetica;">SPDs are estimated by capturing a filtered photo stack of the Schmid chart under noon daylight, corresponding to the CIE D65 illuminant. </span><span style="font-family: helvetica;">SPD ground truth is calculated as the product the D65 illuminant and the spectral reflectance of each swatch, as measured by the </span><a href="https://www.variableinc.com/spectro.html" style="font-family: helvetica;">Spectro 1</a><span style="font-family: helvetica;"> spectrophotometer. The quality of SPD estimation is assessed by comparing the estimated and measured SPDs for each swatch.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-usNuTGNrQ3MxZv7kFybtLUrS1FKi2ndZ9WcpbbPZo9mUvgfARx07kS8H2L4GtIwbl8mc06MkF-1gUh4b342CxsALcjQ-kgV_xFjlV1eM95oCLn-h862ObL2NNfhus-FQkpUtDFck747Y/s1500/schmid_without_calibration.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1500" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-usNuTGNrQ3MxZv7kFybtLUrS1FKi2ndZ9WcpbbPZo9mUvgfARx07kS8H2L4GtIwbl8mc06MkF-1gUh4b342CxsALcjQ-kgV_xFjlV1eM95oCLn-h862ObL2NNfhus-FQkpUtDFck747Y/w640-h426/schmid_without_calibration.png" width="640" /></a></div><div style="text-align: center;"><span style="font-family: helvetica;">Comparison of measured vs. estimated SPD at each swatch for un-calibrated system</span></div><span style="font-family: helvetica;"><br /></span><span style="font-family: helvetica;">From this comparison, a calibration curve is developed. At each swatch, the ratio of estimated to measured SPD is calculated, i.e. the required gain to eliminate error between measurement and estimation. These gains are averaged at each wavelength for all swatches, resulting in the following calibration curve:</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX29MxAawUsmHSJHxsaoX1nMvEYbQkj6Oq3AUXw9wqTGM6OJMVjRUUeUmlanfpFazxb4SDdhTZVrU0NKF8vMdtwwTCZP9X1T8VkVrK8darX1I8bP8glXgQfeFx4XpzYZYnlXBCIRB1O8Ar/s398/schmid_calibration_curve_pre.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX29MxAawUsmHSJHxsaoX1nMvEYbQkj6Oq3AUXw9wqTGM6OJMVjRUUeUmlanfpFazxb4SDdhTZVrU0NKF8vMdtwwTCZP9X1T8VkVrK8darX1I8bP8glXgQfeFx4XpzYZYnlXBCIRB1O8Ar/s16000/schmid_calibration_curve_pre.png" /></a></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;">Overall error signal for Schmid chart before calibration</span></div><div class="separator" style="clear: both; text-align: center;"><br /></div><span style="font-family: helvetica;">To maintain generality and avoid overfitting, a simple linear calibration curve is fit to this curve:</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2s_UBwOMhoEGQtQdd1ggtbu66drMTGuTEIwAhIzW_eKiCKjWZ0kqAOHcNfsIufSFFQsSX9jFFKPH5vzCVmHBxyV7jTiP_5d5V81r7ASi5U1RaIFLP9vaFegrE8h2tpTmTiM-mSAOTvkxB/s398/schmid_calibration_curve_simple.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2s_UBwOMhoEGQtQdd1ggtbu66drMTGuTEIwAhIzW_eKiCKjWZ0kqAOHcNfsIufSFFQsSX9jFFKPH5vzCVmHBxyV7jTiP_5d5V81r7ASi5U1RaIFLP9vaFegrE8h2tpTmTiM-mSAOTvkxB/s16000/schmid_calibration_curve_simple.png" /></a></div><div style="text-align: center;"><span style="font-family: helvetica;">Fitted calibration curve to minimize error signal for Schmid chart</span></div><div><span style="font-family: helvetica;"><br /></span></div><span style="font-family: helvetica;">The Schmid chart is then reevaluated using the calibration curve:<br /><div style="text-align: center;"><br /></div></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ2LwJlAhr4WoiECCeYsJBSyB0F8hHhVyV7_3HAwdIdFaWARCfD4lbZjAfkeA5LzVPlrw176jju6zIb5NvD09gTgJwCODMs_xvxlwnQ10Pb_BzjO2PKcazVRXfBOqruPf319nsFRMtTrC-/s1500/schmid_with_calibration.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1000" data-original-width="1500" height="427" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ2LwJlAhr4WoiECCeYsJBSyB0F8hHhVyV7_3HAwdIdFaWARCfD4lbZjAfkeA5LzVPlrw176jju6zIb5NvD09gTgJwCODMs_xvxlwnQ10Pb_BzjO2PKcazVRXfBOqruPf319nsFRMtTrC-/w640-h427/schmid_with_calibration.png" width="640" /></a></div><div style="text-align: center;"><span style="font-family: helvetica;">Comparison of measured vs. estimated SPD at each swatch for calibrated system</span></div><div style="text-align: center;"><br /></div><span style="font-family: helvetica;">The fit between measurement and estimation is much improved. The average error is centered on 1.00, indicating that the linear fit has the intended effect.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9DG7WGwCKLY4TE_kBQqsAhtgHqKqEoMFwzgldwrwNwriC1osVeH6M3ZNaNBzZeDR7gi0e7XUBerDUdKO0EP1SxuzWN55swmlUW69zvl5sFTdI41vSg0-uUz3AW1eBtZJqcAuRqvth4PIi/s398/schmid_calibration_curve_post.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9DG7WGwCKLY4TE_kBQqsAhtgHqKqEoMFwzgldwrwNwriC1osVeH6M3ZNaNBzZeDR7gi0e7XUBerDUdKO0EP1SxuzWN55swmlUW69zvl5sFTdI41vSg0-uUz3AW1eBtZJqcAuRqvth4PIi/s16000/schmid_calibration_curve_post.png" /></a></div><div style="text-align: center;"><span style="font-family: helvetica;">Overall error signal for Schmid chart after calibration</span></div><br /><div class="separator" style="clear: both; text-align: left;"><b style="font-family: helvetica;">Results</b></div></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;">Several results are shown. All are calculated with a D65 illuminant, the Schmid calibration curve applied, a wavelength resolution of 20 nm, and value scaled to 5% and 95% with a nominal gamma (linearity) value of 1.00. For each, the unfiltered/test (left) and reconstructed (right) images are compared, and a mesh of characteristic spectra are shown.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><br /></span></div><div style="text-align: center;"><span style="font-family: helvetica;">Schmid Color Chart</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaU0lGUZkt6PxvwoKjrJB2-qoWTTKw23D-Jknkn_7TxRrVl22R2Hr7wUanIcBUC42AM9O6b2ELh43arfFXEo_IBrhScCI48TGilAyqCl8zLE0W7Oc9-IgJudXUqgVNuHOxUMXzR1mtsmNU/s2000/IMG_2500_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaU0lGUZkt6PxvwoKjrJB2-qoWTTKw23D-Jknkn_7TxRrVl22R2Hr7wUanIcBUC42AM9O6b2ELh43arfFXEo_IBrhScCI48TGilAyqCl8zLE0W7Oc9-IgJudXUqgVNuHOxUMXzR1mtsmNU/w200-h133/IMG_2500_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnfzo3Qn1p0NanK8UvNy2fCQYPddDkiN2p6ElUah4xVlLfK1gzZtN0RkOgdjWyWlpxFIX9aSMUDfzrQ_G1uAq4LGjA1IBEGUVRDMmAFzFqMkKOLuy_ByexdCFBOZMH2q1wqHUTYbxiCZQF/s2000/IMG_2501_hyperspectral_2000_px_18-Oct-2020_22-20-12.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnfzo3Qn1p0NanK8UvNy2fCQYPddDkiN2p6ElUah4xVlLfK1gzZtN0RkOgdjWyWlpxFIX9aSMUDfzrQ_G1uAq4LGjA1IBEGUVRDMmAFzFqMkKOLuy_ByexdCFBOZMH2q1wqHUTYbxiCZQF/w200-h133/IMG_2501_hyperspectral_2000_px_18-Oct-2020_22-20-12.JPG" width="200" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqp9YnXpxD_9SjkGrzfH_jFKdmCR_FjYVT_V9_-yOD-1QedD2NZx8jO65ahjsDVFUIUPCb8hNjaD78Po46CwH_bjWGq40Wm7Dnfq4bUuW-_Ql5sWe0VbxTufIWPSXXuuK2cshCFAmBuUZY/s1563/IMG_2501_hyperspectral_2000_px_18-Oct-2020_22-20-12_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqp9YnXpxD_9SjkGrzfH_jFKdmCR_FjYVT_V9_-yOD-1QedD2NZx8jO65ahjsDVFUIUPCb8hNjaD78Po46CwH_bjWGq40Wm7Dnfq4bUuW-_Ql5sWe0VbxTufIWPSXXuuK2cshCFAmBuUZY/w640-h268/IMG_2501_hyperspectral_2000_px_18-Oct-2020_22-20-12_spectra.png" width="640" /></a></div><div><br /></div><div><br /></div><br /><div style="text-align: center;"><span style="font-family: helvetica;">Cabbage</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6PGV_6_I18SVrOKIOl2a0nh1bqbzNm0G0_YjrypPrb4AR4egULd2aZcY19Cy0UBtpmlG7WbDQMOQkCZa9SAW2bFSSCOLELqY5Sx_qchisfvsFZciDb1_dTDVsbT5NnX3OVdBylIgmwZvM/s2000/IMG_2468_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6PGV_6_I18SVrOKIOl2a0nh1bqbzNm0G0_YjrypPrb4AR4egULd2aZcY19Cy0UBtpmlG7WbDQMOQkCZa9SAW2bFSSCOLELqY5Sx_qchisfvsFZciDb1_dTDVsbT5NnX3OVdBylIgmwZvM/w200-h133/IMG_2468_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlbSYdjzzCxYUxbzS2jHGe0ipjaU9ih91xDxh0OAEy5YQsKVy0L_b7ObUFJqWH79cY3QD2fSeEXKe3BKbt_D4YpwFY9COJMyF00rIo0ucfg3CvGcPnbStYYLEEs_Owdmhd_2a5_7DSAGrK/s2000/IMG_2469_hyperspectral_2000_px_18-Oct-2020_22-52-03.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjlbSYdjzzCxYUxbzS2jHGe0ipjaU9ih91xDxh0OAEy5YQsKVy0L_b7ObUFJqWH79cY3QD2fSeEXKe3BKbt_D4YpwFY9COJMyF00rIo0ucfg3CvGcPnbStYYLEEs_Owdmhd_2a5_7DSAGrK/w200-h133/IMG_2469_hyperspectral_2000_px_18-Oct-2020_22-52-03.JPG" width="200" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkKNLysHn5bBtMsX8vdGW8VL-WPsLjZoAhEg7fezWZxdrjrFwY5IlRxTpnLT1kQB1CS4K5Siu6Gwicna0B4583syygfHZAGbuV_I9uZnewrIagFLA1ErCOqarve6Tm3QEeTKXdp9N2cptn/s1563/IMG_2469_hyperspectral_2000_px_18-Oct-2020_22-52-03_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkKNLysHn5bBtMsX8vdGW8VL-WPsLjZoAhEg7fezWZxdrjrFwY5IlRxTpnLT1kQB1CS4K5Siu6Gwicna0B4583syygfHZAGbuV_I9uZnewrIagFLA1ErCOqarve6Tm3QEeTKXdp9N2cptn/w640-h268/IMG_2469_hyperspectral_2000_px_18-Oct-2020_22-52-03_spectra.png" width="640" /></a></div><div><br /></div><div><br /></div><div><br /></div><div style="text-align: center;"><span style="font-family: helvetica;">John W. Weeks Bridge</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbs3eIj-7xlWz8Mopp_4Rp7ebHK1XSnYzmbq-QSn-MvFzx-fiCgObI7tCuaeC5dN_mPFkjmpVC7AtPtkhxK0VHg9yEcl9ndfdBcnN6zq2zvaTsmO92MbNqo2raRMTblPdUed01NX1nPVbI/s2000/IMG_2620_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbs3eIj-7xlWz8Mopp_4Rp7ebHK1XSnYzmbq-QSn-MvFzx-fiCgObI7tCuaeC5dN_mPFkjmpVC7AtPtkhxK0VHg9yEcl9ndfdBcnN6zq2zvaTsmO92MbNqo2raRMTblPdUed01NX1nPVbI/w200-h133/IMG_2620_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDGspcBxo1ZpSxEEKyb7J7KC3aO4hKVqoAK4KvblLDAjBpmGeUxUqhHJ0W4GncvI1eM-07O0rQJypkGMLTcUEGfVzHPC0Lmf5HwzGQcou7yxtnh6Q1Q_aC19G7vToVGKrzlXyFGOb-_I0U/s2000/IMG_2621_hyperspectral_2000_px_18-Oct-2020_15-05-26.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDGspcBxo1ZpSxEEKyb7J7KC3aO4hKVqoAK4KvblLDAjBpmGeUxUqhHJ0W4GncvI1eM-07O0rQJypkGMLTcUEGfVzHPC0Lmf5HwzGQcou7yxtnh6Q1Q_aC19G7vToVGKrzlXyFGOb-_I0U/w200-h133/IMG_2621_hyperspectral_2000_px_18-Oct-2020_15-05-26.JPG" width="200" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPVDgcEIoscCkOjOTIMt6cUWDr36jONK9xXm27kW0ggtFAgwFk3L3zwHlDWNVqeFVKnYZVA0-hWrlHJhJpSQd1ksB7sXPB2_6XDteVNaL1OTWWncyFRv80_f4cMtEEDJtNkz0k-CFNOrKW/s1563/IMG_2621_hyperspectral_2000_px_18-Oct-2020_15-05-26_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPVDgcEIoscCkOjOTIMt6cUWDr36jONK9xXm27kW0ggtFAgwFk3L3zwHlDWNVqeFVKnYZVA0-hWrlHJhJpSQd1ksB7sXPB2_6XDteVNaL1OTWWncyFRv80_f4cMtEEDJtNkz0k-CFNOrKW/w640-h268/IMG_2621_hyperspectral_2000_px_18-Oct-2020_15-05-26_spectra.png" width="640" /></a></div><div><br /></div><div><br /></div><div><br /></div><div style="text-align: center;"><span style="font-family: helvetica;">Little Fresh Pond 1</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Zb_gYhVFq4gWZasTVeY75wEW03bnp0Gd6QtKR9bx2t_cutm9yhQSGihqqf-FrlqZ5mkMZV4I3WWDxAoPjW7UOCZp571dAnggtdx6Bruc6AEru8Uxx-WrLSP8luVbS85f8ULw51h4vOPm/s2000/IMG_2740_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Zb_gYhVFq4gWZasTVeY75wEW03bnp0Gd6QtKR9bx2t_cutm9yhQSGihqqf-FrlqZ5mkMZV4I3WWDxAoPjW7UOCZp571dAnggtdx6Bruc6AEru8Uxx-WrLSP8luVbS85f8ULw51h4vOPm/w200-h133/IMG_2740_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAM19ynwgqniIjBOrmX8j9QKlrcVTBS1DARDOpD14ZZkHximp5Fq-WsUSICGtkl1RVVfMkNQ9qPSXdvukaPzEw53gylJgZHheMvTSct7r510l8_r1K2mDN3ga0SFK14iD2HEJHvgwcegdE/s2000/IMG_2741_hyperspectral_2000_px_18-Oct-2020_17-57-44.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAM19ynwgqniIjBOrmX8j9QKlrcVTBS1DARDOpD14ZZkHximp5Fq-WsUSICGtkl1RVVfMkNQ9qPSXdvukaPzEw53gylJgZHheMvTSct7r510l8_r1K2mDN3ga0SFK14iD2HEJHvgwcegdE/w200-h133/IMG_2741_hyperspectral_2000_px_18-Oct-2020_17-57-44.JPG" width="200" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_kvNp6h7wAviDTshCbT5MqQove2aKqnqJNPhcAzlXHzPrGuz3__1YL_6a1PbUQ6kho6RFMwHe2RxXRUiycXLf-uDzNEmvr8Vqahcuu5KJEQcLnsYGtYId48RLqRU8L4ulj-ZLg5QPiiYq/s1563/IMG_2741_hyperspectral_2000_px_18-Oct-2020_17-57-44_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_kvNp6h7wAviDTshCbT5MqQove2aKqnqJNPhcAzlXHzPrGuz3__1YL_6a1PbUQ6kho6RFMwHe2RxXRUiycXLf-uDzNEmvr8Vqahcuu5KJEQcLnsYGtYId48RLqRU8L4ulj-ZLg5QPiiYq/w640-h268/IMG_2741_hyperspectral_2000_px_18-Oct-2020_17-57-44_spectra.png" width="640" /></a></div><span style="font-family: helvetica;"><div><span style="font-family: helvetica;"><br /></span></div><br /></span><div><span style="font-family: helvetica;"><br /></span></div><div style="text-align: center;"><span style="font-family: helvetica;">Sugar Maple</span></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWVF1_Mp57OGDRwtUE-8uvfWEV8qvmpLKhCWVpo8coQCWlMKiw6YeNHIK5UtYJl5UbLUe79CWZcQZ5OLjr-3G6e1KVaX4aJREqlXLzJy0llUBaQ0oqTS-mhNEtjCu116N7KHKz9L0JOhps/s2000/IMG_2719_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWVF1_Mp57OGDRwtUE-8uvfWEV8qvmpLKhCWVpo8coQCWlMKiw6YeNHIK5UtYJl5UbLUe79CWZcQZ5OLjr-3G6e1KVaX4aJREqlXLzJy0llUBaQ0oqTS-mhNEtjCu116N7KHKz9L0JOhps/w200-h133/IMG_2719_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ8gr85fo4oBNJ24N_xDOilRZHPSXl32FX7I8O9oby5y1YNl5WoxrPNLFx6rHsci2nIY1J-G4UW-EEBVOvGxgIUYbbDyh-WeYhhPj5nst4KsAgC75BP8i88bJpqQuN7QP_NXLFlK5in4kU/s2000/IMG_2720_hyperspectral_2000_px_18-Oct-2020_16-03-26.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJ8gr85fo4oBNJ24N_xDOilRZHPSXl32FX7I8O9oby5y1YNl5WoxrPNLFx6rHsci2nIY1J-G4UW-EEBVOvGxgIUYbbDyh-WeYhhPj5nst4KsAgC75BP8i88bJpqQuN7QP_NXLFlK5in4kU/w200-h133/IMG_2720_hyperspectral_2000_px_18-Oct-2020_16-03-26.JPG" width="200" /></a></span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOuVZs_eSMBj9RSCu5MRMQXfLtY4Ynuicfk9TXNTD3_6UhA8AXZFjRqrgo8FMmJ94Luuxt1jEgeuKrWVTL5EaNAYxmUG8pmyQlLm9oAQgfiRS6TLG-RLTw9j2qs23_FQR7PLHycFTedIeV/s1563/IMG_2720_hyperspectral_2000_px_18-Oct-2020_16-03-26_spectra.png" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: helvetica;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOuVZs_eSMBj9RSCu5MRMQXfLtY4Ynuicfk9TXNTD3_6UhA8AXZFjRqrgo8FMmJ94Luuxt1jEgeuKrWVTL5EaNAYxmUG8pmyQlLm9oAQgfiRS6TLG-RLTw9j2qs23_FQR7PLHycFTedIeV/w640-h268/IMG_2720_hyperspectral_2000_px_18-Oct-2020_16-03-26_spectra.png" width="640" /></span></a></div><span style="font-family: helvetica;"><br /></span><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><br /></span></div><div style="text-align: center;"><span style="font-family: helvetica;">Little Fresh Pond 2</span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9V8p1WVOgbprREzClczKIFrHFTvEuonm2RbBYENdJ6L_9JW0Po85AIZlT90b6MxOpGilEw6sWED-zZUXG6bjS6m6715MB3bxP9isiq9BW-EyNikQBexS1PDG9YA_ZZx9zfOj4xdd0vsy7/s2000/IMG_2763_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9V8p1WVOgbprREzClczKIFrHFTvEuonm2RbBYENdJ6L_9JW0Po85AIZlT90b6MxOpGilEw6sWED-zZUXG6bjS6m6715MB3bxP9isiq9BW-EyNikQBexS1PDG9YA_ZZx9zfOj4xdd0vsy7/w200-h133/IMG_2763_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWPzxxC2ryp-SGrxJynT4VwQCelvG4LPyapJXnqNNlkKyZij430skyUIyrjmEj96HV7LK3RjK3fQOYMaWrVySr6UTUcxQSs4r0e_vOfe-Tj9jxOFvpsg2taxtq5_36ARD_40BLQ_VCH_R0/s2000/IMG_2764_hyperspectral_2000_px_18-Oct-2020_18-00-45.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWPzxxC2ryp-SGrxJynT4VwQCelvG4LPyapJXnqNNlkKyZij430skyUIyrjmEj96HV7LK3RjK3fQOYMaWrVySr6UTUcxQSs4r0e_vOfe-Tj9jxOFvpsg2taxtq5_36ARD_40BLQ_VCH_R0/w200-h133/IMG_2764_hyperspectral_2000_px_18-Oct-2020_18-00-45.JPG" width="200" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnshyphenhyphenbuxskjnWWcMLEwDhbUrF8nCgyKeO81C7kfLeYE8FuCEF1Cegfd4WUJ9nZXgSoWLyW9_qrhcOLtyP4psoJ2WGMd9ULAu83pc2Vhe2CQP7xNkKrn7ahf-9HJjZkJzAQBW4yZqG4xVEU/s1563/IMG_2764_hyperspectral_2000_px_18-Oct-2020_18-00-45_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnshyphenhyphenbuxskjnWWcMLEwDhbUrF8nCgyKeO81C7kfLeYE8FuCEF1Cegfd4WUJ9nZXgSoWLyW9_qrhcOLtyP4psoJ2WGMd9ULAu83pc2Vhe2CQP7xNkKrn7ahf-9HJjZkJzAQBW4yZqG4xVEU/w640-h268/IMG_2764_hyperspectral_2000_px_18-Oct-2020_18-00-45_spectra.png" width="640" /></a></div><div><br /></div><div><br /></div><br /><div style="text-align: center;"><span style="font-family: helvetica;">Western Av. Bridge</span></div></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4dA2zwOIV78IGmpdKairT1QA5jJiA3mKP0trBXW8KO1wu2jvawZ86nc_C7OUHomJFkcMefElEfScx3iKg0U4qyaUyh36D68N4K1te78EIQHYVZTg5rjvuZ-R_9EvmojetqIwzcTDRaRKV/s2000/IMG_2595_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4dA2zwOIV78IGmpdKairT1QA5jJiA3mKP0trBXW8KO1wu2jvawZ86nc_C7OUHomJFkcMefElEfScx3iKg0U4qyaUyh36D68N4K1te78EIQHYVZTg5rjvuZ-R_9EvmojetqIwzcTDRaRKV/w200-h133/IMG_2595_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihExg-ahpsMn_5D9CQ11_17UH-UHNf4QhNJmmrPEzzgfCr_oERsYhZ6VsdmgOXIZD0iIUvgSbd9Mmme2xRR0LC15vIokQNhCoQdkjIAEiq-tE0rmviCZAIMKJZeHizlup2uh9654UT2qQW/s2000/IMG_2596_hyperspectral_2000_px_18-Oct-2020_15-03-19.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihExg-ahpsMn_5D9CQ11_17UH-UHNf4QhNJmmrPEzzgfCr_oERsYhZ6VsdmgOXIZD0iIUvgSbd9Mmme2xRR0LC15vIokQNhCoQdkjIAEiq-tE0rmviCZAIMKJZeHizlup2uh9654UT2qQW/w200-h133/IMG_2596_hyperspectral_2000_px_18-Oct-2020_15-03-19.JPG" width="200" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7DTl_holom2q7rypexPmKkMsnhKrOyUDcDoZYL1c6j5ydGbf-OtcWt2opAjG8dYiLR_cIfxu-mAZuWXwxf4ODA_xMZTkMIHCxT0q2eG8SNp5Ak-dMLUyxxO2dbPVNcrAkA0MgVPnYyBc_/s1563/IMG_2596_hyperspectral_2000_px_18-Oct-2020_15-03-19_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7DTl_holom2q7rypexPmKkMsnhKrOyUDcDoZYL1c6j5ydGbf-OtcWt2opAjG8dYiLR_cIfxu-mAZuWXwxf4ODA_xMZTkMIHCxT0q2eG8SNp5Ak-dMLUyxxO2dbPVNcrAkA0MgVPnYyBc_/w640-h268/IMG_2596_hyperspectral_2000_px_18-Oct-2020_15-03-19_spectra.png" width="640" /></a></div><div style="text-align: center;"><span style="font-family: helvetica;"><br /></span></div><div style="text-align: center;"><span style="font-family: helvetica;"><br /></span></div><div style="text-align: center;"><span style="font-family: helvetica;"><br /></span></div><div style="text-align: center;"><span style="font-family: helvetica;">John W. Weeks Bridge Entrance</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2R1jDwYtcRKT40XD_hhpU1Fxpgf98UtGL8UgAdvvnHuH6s6JZVP9KXNtf_OGfLGuTqCM3We8BfNn0yNm-3BmHuLXhw3YzR7L3VTdj5GKAHeZLmzP0qXPTM45AupJAx5zeNudzYJG0QOiA/s2000/IMG_2564_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2R1jDwYtcRKT40XD_hhpU1Fxpgf98UtGL8UgAdvvnHuH6s6JZVP9KXNtf_OGfLGuTqCM3We8BfNn0yNm-3BmHuLXhw3YzR7L3VTdj5GKAHeZLmzP0qXPTM45AupJAx5zeNudzYJG0QOiA/w200-h133/IMG_2564_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisYHolI3xPAJHOpkiG-VlWHLIVXNtDibQLxzMbmuvxDSSaX9_dLcLoH-rycAD7EtseqmqB_txeWS7ExUjrTWRbfdj2RWxxXbaIrQoZLx-5oNG4ridyGkOZ4YnZ8ZS62rYa93U0HvsvUHml/s2000/IMG_2565_hyperspectral_2000_px_18-Oct-2020_18-51-29.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisYHolI3xPAJHOpkiG-VlWHLIVXNtDibQLxzMbmuvxDSSaX9_dLcLoH-rycAD7EtseqmqB_txeWS7ExUjrTWRbfdj2RWxxXbaIrQoZLx-5oNG4ridyGkOZ4YnZ8ZS62rYa93U0HvsvUHml/w200-h133/IMG_2565_hyperspectral_2000_px_18-Oct-2020_18-51-29.JPG" width="200" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL-TzRT8qu5F3wlYMevmB9FxR8UdIWBqdCO56i7Fl6D4E4ZqIubPSuiXmz9LC1OdoQJm4h-BjG7EQqgT7qIW1u8ST3S5i0b45RDW4MEAiL-DaHh2zQcv-L901E3q4Nuun2j7Rt6EJGufib/s1563/IMG_2565_hyperspectral_2000_px_18-Oct-2020_18-51-29_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgL-TzRT8qu5F3wlYMevmB9FxR8UdIWBqdCO56i7Fl6D4E4ZqIubPSuiXmz9LC1OdoQJm4h-BjG7EQqgT7qIW1u8ST3S5i0b45RDW4MEAiL-DaHh2zQcv-L901E3q4Nuun2j7Rt6EJGufib/w640-h268/IMG_2565_hyperspectral_2000_px_18-Oct-2020_18-51-29_spectra.png" width="640" /></a></div></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div style="text-align: center;"><span style="font-family: helvetica;">Belmont Victory Gardens, Rock Meadow</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjixj3AJsg5YJY40A8lF1PDS6-XucFTspzHFAdLN1JG9RIx5pSbB5YMRp2D1noQaMcFtyzmnCHrNt60FCmwZPy_aMSyq1XAelY8k_G5SlM0mm3Yz_rVId9XKVuErGNxctfKX50rBoR5exRI/s2000/IMG_2454_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjixj3AJsg5YJY40A8lF1PDS6-XucFTspzHFAdLN1JG9RIx5pSbB5YMRp2D1noQaMcFtyzmnCHrNt60FCmwZPy_aMSyq1XAelY8k_G5SlM0mm3Yz_rVId9XKVuErGNxctfKX50rBoR5exRI/w200-h133/IMG_2454_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj23mDv6JePAlD8MhWx7u2V18GW5mAunJXnVz1yGBPvDYqUnBmNZfR5o6_kvezXvDYe-G052wQ4YRekGaol6SRWhz0azLhEcn6-V4UrAov5E3ldc8QS-bQb_JxF3bEQtiWIhTUa3bIRsQAv/s2000/IMG_2460_hyperspectral_2000_px_18-Oct-2020_23-04-32.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj23mDv6JePAlD8MhWx7u2V18GW5mAunJXnVz1yGBPvDYqUnBmNZfR5o6_kvezXvDYe-G052wQ4YRekGaol6SRWhz0azLhEcn6-V4UrAov5E3ldc8QS-bQb_JxF3bEQtiWIhTUa3bIRsQAv/w200-h133/IMG_2460_hyperspectral_2000_px_18-Oct-2020_23-04-32.JPG" width="200" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitZqcfmgyZgb8d8pEmjqTntzHLSbOrM3Q6wN-OPZR0z1qzhRE8F5wgrXaPfufg6te-fvKl5yS3C64cA_qNV4fS9h-MjSwtQVtXAUr8Mq2slw9j8dksyLWNCrYBrAn2JDEmnymuk2p3om63/s1563/IMG_2460_hyperspectral_2000_px_18-Oct-2020_23-04-32_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitZqcfmgyZgb8d8pEmjqTntzHLSbOrM3Q6wN-OPZR0z1qzhRE8F5wgrXaPfufg6te-fvKl5yS3C64cA_qNV4fS9h-MjSwtQVtXAUr8Mq2slw9j8dksyLWNCrYBrAn2JDEmnymuk2p3om63/w640-h268/IMG_2460_hyperspectral_2000_px_18-Oct-2020_23-04-32_spectra.png" width="640" /></a></div></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><br /></span></div><div><div style="text-align: center;"><span style="font-family: helvetica;">Thicket</span></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJAMQd3TH05vhpLVl73_sFnWOxp5KL_RYpChg_MXrLQAWI7AbK5GXgSbqpFU7tdoSWuRNhAK2U0oWpvfCdFQKHhkxyvC90dzWuYWopruUBgg1i9HtGskYOjiICFLPCvWFugu3te8CewE0C/s2000/IMG_2406_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJAMQd3TH05vhpLVl73_sFnWOxp5KL_RYpChg_MXrLQAWI7AbK5GXgSbqpFU7tdoSWuRNhAK2U0oWpvfCdFQKHhkxyvC90dzWuYWopruUBgg1i9HtGskYOjiICFLPCvWFugu3te8CewE0C/w200-h133/IMG_2406_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB4bLnBNLMnAd7OP_a6EW8EIJuUvpg9zoDQZ_bB45sQhfa2jaD-yXdKQm0u6GDkfK0d976pzLmiQxJN8x9U7aQbafEdW16KH1mCh2RuzbGGSKokeTxdAaAykBZYhWADNvNQaOa-1qyThmW/s2000/IMG_2412_hyperspectral_2000_px_18-Oct-2020_22-55-56.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhB4bLnBNLMnAd7OP_a6EW8EIJuUvpg9zoDQZ_bB45sQhfa2jaD-yXdKQm0u6GDkfK0d976pzLmiQxJN8x9U7aQbafEdW16KH1mCh2RuzbGGSKokeTxdAaAykBZYhWADNvNQaOa-1qyThmW/w200-h133/IMG_2412_hyperspectral_2000_px_18-Oct-2020_22-55-56.JPG" width="200" /></a></div></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4YyH5EV8AT_QAD_qSNvXGCbuTTwXYWhpwI7t7wuFPLsuC4Nez0k9haJfGRtpA1tNLg0cbL6qeNZKHAEMAHlvs-Q0Y_ge0VuWEgZFZRtMIJtApqN0-mRfbbqc1NjM4xpDYO_XU9OFEX2fX/s1563/IMG_2412_hyperspectral_2000_px_18-Oct-2020_22-55-56_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4YyH5EV8AT_QAD_qSNvXGCbuTTwXYWhpwI7t7wuFPLsuC4Nez0k9haJfGRtpA1tNLg0cbL6qeNZKHAEMAHlvs-Q0Y_ge0VuWEgZFZRtMIJtApqN0-mRfbbqc1NjM4xpDYO_XU9OFEX2fX/w640-h268/IMG_2412_hyperspectral_2000_px_18-Oct-2020_22-55-56_spectra.png" width="640" /></a></div></div><div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;"><br /></span></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;">JFK Memorial Park 1</span></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaRiqoQoL5kMIwRIf4VxGwQDV3dtWArH3MlGpnIk0NUtRrSLkiFugBDVkm2ljwRPQLv7y4i9XBd0ftZMErLfc9A3TfZkQh_juTPzWD5w7qe7O7crq22Lv4XhmfMmwYBHsVmLEBLqqrVt4B/s2000/IMG_2577_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiaRiqoQoL5kMIwRIf4VxGwQDV3dtWArH3MlGpnIk0NUtRrSLkiFugBDVkm2ljwRPQLv7y4i9XBd0ftZMErLfc9A3TfZkQh_juTPzWD5w7qe7O7crq22Lv4XhmfMmwYBHsVmLEBLqqrVt4B/w200-h133/IMG_2577_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixUt5-tJYXXIPuzGsXTJu5tP7Xauf4Wg0lxXE6-fWm7FxFXiIJyl6PyQdrkxBudLbpGRiiKLtDEZo5iPfuODJBbRHvWNm1vMT8vS_rEA_qDKD-YMBBqXGWzD17rfHq3jZ1h4KDl3WDcssf/s2000/IMG_2578_hyperspectral_2000_px_18-Oct-2020_14-57-06.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixUt5-tJYXXIPuzGsXTJu5tP7Xauf4Wg0lxXE6-fWm7FxFXiIJyl6PyQdrkxBudLbpGRiiKLtDEZo5iPfuODJBbRHvWNm1vMT8vS_rEA_qDKD-YMBBqXGWzD17rfHq3jZ1h4KDl3WDcssf/w200-h133/IMG_2578_hyperspectral_2000_px_18-Oct-2020_14-57-06.JPG" width="200" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimbfMgQ-djbyCHYc6wOXCDJfUTW1zIbT6UFYfaf6Iqynaui6W16laRVrSkeqpG1L6Oopqr41BzqXqtqmiwwZ9PbsipfKDfg8orO3lXmxiinfhVEDYiFe_CNbSa1z2kdV7Ho1c_vwSFHM7O/s1563/IMG_2578_hyperspectral_2000_px_18-Oct-2020_14-57-06_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimbfMgQ-djbyCHYc6wOXCDJfUTW1zIbT6UFYfaf6Iqynaui6W16laRVrSkeqpG1L6Oopqr41BzqXqtqmiwwZ9PbsipfKDfg8orO3lXmxiinfhVEDYiFe_CNbSa1z2kdV7Ho1c_vwSFHM7O/w640-h268/IMG_2578_hyperspectral_2000_px_18-Oct-2020_14-57-06_spectra.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><span style="font-family: helvetica;">JFK Memorial Park 2</span></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig27znkS7ptcntvfyLJ3zlcDsAplCcy-9i56sK5gN-NNHKhMiuED25124fCocvLhKCD9YD0PMbc88nZ_eeVobpnMbmDx5XWQt0UbWAK4uLFv7HFNrScOni6OxibA9P3__A1cKsQztiQci7/s2000/IMG_2589_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig27znkS7ptcntvfyLJ3zlcDsAplCcy-9i56sK5gN-NNHKhMiuED25124fCocvLhKCD9YD0PMbc88nZ_eeVobpnMbmDx5XWQt0UbWAK4uLFv7HFNrScOni6OxibA9P3__A1cKsQztiQci7/w200-h133/IMG_2589_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7uC972egguE-4NBfgYWiVW4TkkO7ffMFpNSrRkqY1eFJG1G-CBYG68bvjIHYQG7F11yUQb5oiEJgd23V2QcrE0SblRIhdD_ARhDw2LATcn2EquEANhAMZ2ZV_DsoYVfGxhjB6tQgBRTXT/s2000/IMG_2590_hyperspectral_2000_px_18-Oct-2020_15-24-46.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7uC972egguE-4NBfgYWiVW4TkkO7ffMFpNSrRkqY1eFJG1G-CBYG68bvjIHYQG7F11yUQb5oiEJgd23V2QcrE0SblRIhdD_ARhDw2LATcn2EquEANhAMZ2ZV_DsoYVfGxhjB6tQgBRTXT/w200-h133/IMG_2590_hyperspectral_2000_px_18-Oct-2020_15-24-46.JPG" width="200" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXtCM4-Q52gJ86Dw8vFYcGohPMlbcQCpRFvJTcWkH725dONM2f0ldiyXHF0Vqr4FWSmoPYPXkc73CqnzoSD_FwGDgBx6BvgqG-4lQupb09WhaVC40yaQulBgmaCYhc1_1fLRvwwYocoA-3/s1563/IMG_2590_hyperspectral_2000_px_18-Oct-2020_15-24-46_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXtCM4-Q52gJ86Dw8vFYcGohPMlbcQCpRFvJTcWkH725dONM2f0ldiyXHF0Vqr4FWSmoPYPXkc73CqnzoSD_FwGDgBx6BvgqG-4lQupb09WhaVC40yaQulBgmaCYhc1_1fLRvwwYocoA-3/w640-h268/IMG_2590_hyperspectral_2000_px_18-Oct-2020_15-24-46_spectra.png" width="640" /></a></div><div><br /></div><div><br /></div><br /><span style="font-family: helvetica;"><div class="separator" style="clear: both; font-family: "Times New Roman"; text-align: center;"><span style="font-family: helvetica;">Desk</span></div><div class="separator" style="clear: both; font-family: "Times New Roman"; text-align: center;"><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCOVwmPZRPlVaYPs5A7v8SrSRyziA2EKTqeht1DF3nWekx1kco4sNAzZvhAn0ndOZapMan8J1JeWMCmg-SnKVLmUgk4Szmf-ZenOA93DJn9hN4R93OOp6xL2wXykS3ItTTdB_zw7Hz5bou/s2000/IMG_2307_resized_2000_px.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCOVwmPZRPlVaYPs5A7v8SrSRyziA2EKTqeht1DF3nWekx1kco4sNAzZvhAn0ndOZapMan8J1JeWMCmg-SnKVLmUgk4Szmf-ZenOA93DJn9hN4R93OOp6xL2wXykS3ItTTdB_zw7Hz5bou/w200-h133/IMG_2307_resized_2000_px.JPG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAXV__1WNzH_Vmsq2wUNwb-z5I_toJjaW38kQRXD__ypRqBdy6z6kvapZ_uQ1kRZ9H9V3zuC_HAyvKdfnSmsnkLuLGH5TWmh8IZ28fGC64xkwF9yYrjgJxHqzm2t8ixLoIFyscayUocUsf/s2000/IMG_2308_hyperspectral_2000_px_19-Oct-2020_09-25-13.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1334" data-original-width="2000" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAXV__1WNzH_Vmsq2wUNwb-z5I_toJjaW38kQRXD__ypRqBdy6z6kvapZ_uQ1kRZ9H9V3zuC_HAyvKdfnSmsnkLuLGH5TWmh8IZ28fGC64xkwF9yYrjgJxHqzm2t8ixLoIFyscayUocUsf/w200-h133/IMG_2308_hyperspectral_2000_px_19-Oct-2020_09-25-13.JPG" width="200" /></a></div><div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVjdYSWBslhXQ6fH1ZOHdfKNwD_OVd547fdUBn74r2tU6vdv1WSCHk0AzQ2s_UHrdJVqRWcIzwTVh5srAp9Wwt241xXo4rHKkS42-QNXFTDdeQdPqL86b4cH3vGJ9NKSviE0vazOgtaI9U/s1563/IMG_2308_hyperspectral_2000_px_19-Oct-2020_09-25-13_spectra.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="656" data-original-width="1563" height="268" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVjdYSWBslhXQ6fH1ZOHdfKNwD_OVd547fdUBn74r2tU6vdv1WSCHk0AzQ2s_UHrdJVqRWcIzwTVh5srAp9Wwt241xXo4rHKkS42-QNXFTDdeQdPqL86b4cH3vGJ9NKSviE0vazOgtaI9U/w640-h268/IMG_2308_hyperspectral_2000_px_19-Oct-2020_09-25-13_spectra.png" width="640" /></a></div><div><br /></div></div></span></div><div><b><span style="font-family: helvetica;">Conclusions</span></b></div><div><b style="font-family: helvetica;"><br /></b></div><div><span style="font-family: helvetica;">A simple method for hyperspectral imaging with a commodity camera is demonstrated using only commercially-available hardware. Accounting for the camera's Bayer filter reduces the number of lens filters required by increasing the number of principal components in the photo capture transformation matrix, ST. For the specific choice of a Canon 650D camera and the MidOpt FS100 filter kit, reasonable agreement is shown for samples of known properties between measured vs. estimated SPDs. Future work may examine in greater depth the filter selection sub-problem to improve SPD estimation and/or reduce cost, and/or study differences between unfiltered and reconstructed images.</span></div><div><span style="font-family: helvetica;"><br /></span></div><div><span style="font-family: helvetica;"><b>Source Code</b></span></div><div><span style="font-family: helvetica;"><b><br /></b></span></div><div><span style="font-family: helvetica;">A MATLAB GUI was developed to facilitate rapid adjustment and iteration of SPD estimation and image reconstruction parameters. It currently supports 2 filter sets, 7 illuminants, 28 cameras, and 2 observers, and can readily be expanded as needed. Full source code may be found on <a href="https://github.com/kindofdoon/Hyperspectral_Imaging">GitHub</a>.</span></div><div><span style="font-family: helvetica;"><b><br /></b></span></div><div><div class="separator" style="clear: both; font-family: helvetica; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgae_mO0ozZIw7Cr0BxCZHmJ7hg8qkrwte7vxtdIWcQCqSpcYLt6uDfKOOfltOFzOkk7zuEhruvZDzj71QxKsWewGMSDVeEirH9V03y5n3ea016P4aEtPjiXcFnb59O10mQ53nOIPPmuea9/s1837/GUI_sample.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1047" data-original-width="1837" height="364" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgae_mO0ozZIw7Cr0BxCZHmJ7hg8qkrwte7vxtdIWcQCqSpcYLt6uDfKOOfltOFzOkk7zuEhruvZDzj71QxKsWewGMSDVeEirH9V03y5n3ea016P4aEtPjiXcFnb59O10mQ53nOIPPmuea9/w640-h364/GUI_sample.PNG" width="640" /></a></div><div style="text-align: center;"><span style="font-family: helvetica;">MATLAB GUI for creation of SPDs and reconstructed images</span></div></div><div><b style="font-family: helvetica;"><br /></b></div><div><b style="font-family: helvetica;">References</b></div><div><span style="font-family: helvetica;"><div style="font-family: "Times New Roman";"><span style="font-family: helvetica;"><b><br /></b></span></div><div><ol style="text-align: left;"><li><span style="font-family: helvetica;">Jiang et al. <a href="http://www.gujinwei.org/research/camspec/"><i>What is the Space of Spectral Sensitivity Functions for Digital Color Cameras?</i></a> IEEE Workshop on the Applications of Computer Vision (WACV), 2013.</span></li><li>Leeuw et al. <i><a href="https://www.mdpi.com/1424-8220/13/6/7872">In situ Measurements of Phytoplankton Fluorescence Using Low Cost Electronics</a></i>. Sensors 2013, 13, 7872-7883.</li><li>Antonino Cosentino. <i><a href="https://www.researchgate.net/publication/278965076_Multispectral_Imaging_of_Pigments_with_a_digital_camera_and_12_interferential_filters">Multispectral Imaging of Pigments with a Digital Camera and 12 Interferential Filters</a></i>. e-Preservation Science, 2015.</li><li><span style="font-family: helvetica;">Seoung et al. <i><a href="https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Oh_Do_It_Yourself_CVPR_2016_paper.pdf">Do It Yourself Hyperspectral Imaging with Everyday Digital Cameras</a></i>. IEEE Conference on Computer Vision and Pattern Recognition (CVPR), </span>2016.</li><li>Habel et al. <i><a href="https://www.cg.tuwien.ac.at/research/publications/2012/Habel_2012_PSP/Habel_2012_PSP-Draft.pdf">Practical Spectral Photography</a></i>. Eurographics, Volume 31, Number 2, 2012.</li><li>Baek et al. <i><a href="http://vclab.kaist.ac.kr/siggraphasia2017p2/prism_main.pdf">Compact Single-Shot Hyperspectral Imaging Using a Prism</a></i>. ACM Transactions on Graphics, Vol. 36, No. 6, Article 217. Publication date: November 2017.</li><li>Lindbloom. <i><a href="http://www.brucelindbloom.com/index.html?Eqn_Spect_to_XYZ.html">Spectral Computation of XYZ</a></i>. Revised Sat, 08 Apr 2017 18:57:27 GMT.</li><li>Colour & Vision Research Laboratory, University College London. <i><a href="http://cvrl.ioo.ucl.ac.uk/index.htm">Standard Illuminants</a></i>.</li><li>PublicResource.org. CIE 15: Supplementary Tables [10 CFR 430 Subpart B, App. R, 4.1.1], <a href="https://law.resource.org/pub/us/cfr/ibr/003/cie.15.2004.tables.xls">cie.15.2004.tables.xls</a>.</li><li>Dichter. <i><a href="http://www.kindofdoon.com/2019/07/how-paints-mix.html">How Paints Mix</a>.</i> 2019.</li><li>Schmid. <i><a href="https://www.richardschmid.com/ProductDetails.asp?ProductCode=SKUAP">Alla Prima II</a></i>. Page 219. Fourth Printing, March 2018.</li></ol></div></span></div></div>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-5939326227634267482020-06-27T08:59:00.008-07:002020-10-28T16:38:40.946-07:00Visualizing Color Space in 2D<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">I present here </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">an optimized visualization of a perceptually uniform 3D color gamut in 2D space, or "color map", and show a few ways it can be used. It is designed </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">to provide persistent awareness of position within color space, so that it can be navigated, learned, and utilized more effectively by practitioners of digital color, such as painters, photographers, illustrators, etc.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">This is a follow-up to my previous </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">"</span><a href="http://www.kindofdoon.com/2020/05/color-navigation-map.html" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Color Navigation Map</a><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">" article, with the same goals but an alternate approach. In my view, this approach fully supersedes the previous one, although</span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"> no single "best" visualization exists. Like a map projection, it represents a balance of competing tradeoffs.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div style="text-align: center;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFYZu7b4DwpU4Z23WQFaZBq-yukYmnaeoR9uVplQABKDiMdNRvAmF2Jez0jSxnW3jDpRziFBTEQChDXkRFM7UNUmrylenfh8xwMi5pgUCbpD8R1ivTPIAuMCrPIz2wV7-Lb94XvdpxDvH_/s1600/color_gamut_Lab_541_colors_5_JND_11.5_dE_12x_scale_transparent.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="204" data-original-width="732" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFYZu7b4DwpU4Z23WQFaZBq-yukYmnaeoR9uVplQABKDiMdNRvAmF2Jez0jSxnW3jDpRziFBTEQChDXkRFM7UNUmrylenfh8xwMi5pgUCbpD8R1ivTPIAuMCrPIz2wV7-Lb94XvdpxDvH_/s1600/color_gamut_Lab_541_colors_5_JND_11.5_dE_12x_scale_transparent.png" /></a></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<span face="" style="clear: left; float: left; font-family: "helvetica neue", arial, helvetica, sans-serif; margin-bottom: 1em; margin-right: 1em;"></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">5.0 JND, 541 colors</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZTicZUGoUft6nSe4vJ0KiosVIflpwO4sfgMIbDeWU0yw9fE1H5epWr7o4eqYPee0tCOrRWWIhvYlT0bjwYEcOgdyk16W69O2AeUmgp1LijW8j1JMOGGH5LK573MCIP4cPm-JP-wDSqwFJ/s1600/color_gamut_Lab_1052_colors_4_JND_9.2_dE_8x_scale_transparent.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="152" data-original-width="728" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZTicZUGoUft6nSe4vJ0KiosVIflpwO4sfgMIbDeWU0yw9fE1H5epWr7o4eqYPee0tCOrRWWIhvYlT0bjwYEcOgdyk16W69O2AeUmgp1LijW8j1JMOGGH5LK573MCIP4cPm-JP-wDSqwFJ/s1600/color_gamut_Lab_1052_colors_4_JND_9.2_dE_8x_scale_transparent.png" /></a><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif; margin-left: 1em; margin-right: 1em;"></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">4.0 JND, 1,052 colors</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjt_n4_60AG3wsHqsU60k6QSPvGGK-16O-rclt27u7IO21I3YVElqL1WMWxTA0IUJuXnELq7kFFj9xOcPRNEl2BpXd-8mZPAUaSwqbJlnFOnE0FtjxYwTGyP3R9O-_-Sf461mfzdXK7Ej3J/s1600/color_gamut_Lab_2509_colors_3_JND_6.9_dE_4x_scale_transparent.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="108" data-original-width="628" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjt_n4_60AG3wsHqsU60k6QSPvGGK-16O-rclt27u7IO21I3YVElqL1WMWxTA0IUJuXnELq7kFFj9xOcPRNEl2BpXd-8mZPAUaSwqbJlnFOnE0FtjxYwTGyP3R9O-_-Sf461mfzdXK7Ej3J/s1600/color_gamut_Lab_2509_colors_3_JND_6.9_dE_4x_scale_transparent.png" /></a><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif; margin-left: 1em; margin-right: 1em;"></span></div>
<div class="separator" style="clear: both;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">3.0 JN</span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">D, 2,509 colors</span></div>
<div class="separator" style="clear: both;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH0-q47l0rVB4RGcdhDnBtLQHINc3fLXZi1W_gGbj7WmjV2DN-rDbcqxzYJZoJ-RB1UdSdhOEFjwXL2ipCkuUsOw4niyiEor9nCRz9Ijg7M8nTuWoWOoa3tFPrFKj5D2BjeLfZNUB3fZ66/s1600/color_gamut_Lab_8434_colors_2_JND_4.6_dE_2x_scale_transparent.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH0-q47l0rVB4RGcdhDnBtLQHINc3fLXZi1W_gGbj7WmjV2DN-rDbcqxzYJZoJ-RB1UdSdhOEFjwXL2ipCkuUsOw4niyiEor9nCRz9Ijg7M8nTuWoWOoa3tFPrFKj5D2BjeLfZNUB3fZ66/s1600/color_gamut_Lab_8434_colors_2_JND_4.6_dE_2x_scale_transparent.png" /></a><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">2.0 JND, 8,434 colors</span></div>
<div class="separator" style="clear: both;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNbD7H25z472NzDeXKCgChocqZUFx0_LOUmoP-P9SyC4PEZR5xY8Hvi37Jto5Y6aWgOngAAQUQFzwiRrD1MzHsvan9x8WDS37LxwPU5A2fimGI-jB62DKvuvm0BwhivmCQo2X73A6jUFzx/s1600/color_gamut_Lab_67455_colors_1_JND_2.3_dE_1x_scale_transparent.png" style="clear: left; font-family: "times new roman"; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNbD7H25z472NzDeXKCgChocqZUFx0_LOUmoP-P9SyC4PEZR5xY8Hvi37Jto5Y6aWgOngAAQUQFzwiRrD1MzHsvan9x8WDS37LxwPU5A2fimGI-jB62DKvuvm0BwhivmCQo2X73A6jUFzx/s640/color_gamut_Lab_67455_colors_1_JND_2.3_dE_1x_scale_transparent.png" /></a><br />1.0 JND, 67,455 colors</span></div>
<div style="text-align: left;">
<br /></div>
<b><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Technical Summary</span></b><br />
<b><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></b>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">The method used to generate these color maps is as follows:</span><br />
<ol>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Generate a preliminary 5-bit color gamut in RGB space.</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Convert the gamut to L</span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">ab space under the standard D65 illuminant.</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Calculate the boundary of the gamut point cloud, obtaining an irregular concave polyhedron.</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Generate a final color gamut within the polyhedron, using a fixed </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">ΔE resolution for perceptual uniformity.</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Section the final gamut at each L value.</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Convert each section to an RGB image, with exactly one pixel for each color.</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Arrange the sections laterally, with a axes horizontal, b axes vertical, and L axes aligned vertically.</span></li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvDAnoYvzhI3ZBLXBKdc3iYQmeuI-Zd2VaXipeKXxLi4kB96WjgtvAxWvqWgthMW2plwVDvxSEpjf9EZ2c2OURu19pnTPgj0iwrcfN9m18myEpwKDJ6ccAEU32Y_l7fqkVqgxUTg9AXEvX/s1600/color_gamut_sections_labeled.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="193" data-original-width="765" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvDAnoYvzhI3ZBLXBKdc3iYQmeuI-Zd2VaXipeKXxLi4kB96WjgtvAxWvqWgthMW2plwVDvxSEpjf9EZ2c2OURu19pnTPgj0iwrcfN9m18myEpwKDJ6ccAEU32Y_l7fqkVqgxUTg9AXEvX/s1600/color_gamut_sections_labeled.png" /></a></div>
<br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">By design, the final color map is extremely compact and efficient:</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPwPPyyuZteqtfARolyLipBotyTEunaUy3iAicCS2duu9EUOxwlu6BfrqqbwghcWRYf4dNA1ITq_deJ-AVTA5m9DaIEIujpUeuK_pv0T_M1oCy3ao4juh6Jln0fATVJy5LlHhBX2uFeqB9/s1600/color_map_properties_table.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="173" data-original-width="683" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPwPPyyuZteqtfARolyLipBotyTEunaUy3iAicCS2duu9EUOxwlu6BfrqqbwghcWRYf4dNA1ITq_deJ-AVTA5m9DaIEIujpUeuK_pv0T_M1oCy3ao4juh6Jln0fATVJy5LlHhBX2uFeqB9/s1600/color_map_properties_table.png" /></a></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b>Why Map Color?</b></span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b><br /></b></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">To begin, it bears mentioning why color mapping is worthwhile in the first place. In essence, it does for color what a geographical map does for global positioning. It tells the navigator where they are in space, what else is around, and in which direction to travel to reach their destination. Imagine how difficult navigation would be without maps. We are effectively "mapless" when it comes to color, which makes it harder than necessary to use and understand. Solving this problem is my goal.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Which Gamut To Map?</b><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Now, some discussion on scope. For practical reasons, I attempt to visualize only the set of colors capable of being displayed by standard computer/phone screens. These screens generally show color in the RGB (red-green-blue) format with 8-bit resolution for each channel. Altogether, this paradigm provides 256^3 = 2^8^3 = 2^24 = 16.7 million unique colors. While RGB color is linear with respect to colored light, human perception of color is highly irregular and nonlinear. In other words, RGB is a good color model for screens, but not for people. It is therefore natural to introduce the Lab color space which by design is perceptually uniform.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Perceptual uniformity means that physical distance between color corresponds 1:1 with their perceived color distance (at least in theory - there are limitations). It's important to realize that color measurement can always be interpreted as geometry, e.g. a pixel's color can be plotted as a point in 3D space, and a gamut (set of colors) can be plotted as a point cloud in 3D space. </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Euclidean (straight-line) distance in Lab space is a very good measure of perceived color distance, and is conventionally denoted as </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">ΔE, with the letter "E" tracing back to the original German </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><i>empfindung</i> for "sensation". </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">It is also helpful to think of color distance in terms of JNDs, or just noticeable differences, commonly defined as 2.3 </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">ΔE.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Filling the RGB gamut in Lab space with uniformly-distributed colors at ΔE = 2.3 = 1.0 JND generates about 67,000 unique colors. Compare this to the 16.7 million colors in the RGB gamut, and you'll see that perceptually speaking, we can do with many fewer colors. In fact, a gamut about 1/250 the size of the standard 8-bit RGB gamut is perceptually "complete", give or take. Of course, there are good practical reasons why a larger gamut is used. But for my purposes they are not relevant, so I use a smaller, perceptually uniform gamut instead.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">As for the "best" </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">ΔE value to use, it depends on the application. In some cases, a lower resolution is actually preferable, and a good example of this can be found in hardware stores paint swatches. It is actually helpful for there to be <i>fewer</i> choices, up to a point, because they are more differentiable, and more consideration can be given to each. In other cases, where very accurate matching is desired, a higher resolution will be preferable. For my purposes, primarily as an oil painter, I prefer a ΔE of 4.6, or 2.0 JND.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH2fiFN0c1bWTlYyFxDujx2kKg_kIIqVIaFrc0m-dto-EvBaNAnqZ_J3qqedSiUBUIBV1u43ALlylS31l8nE9SCb76UdMusVHxahxPShfXQMHrTioE_7CUH1HcwcUVsdjxIjckJM2gyhA3/s1600/paint_swatches_rotated_cropped_calibrated.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="705" data-original-width="1600" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH2fiFN0c1bWTlYyFxDujx2kKg_kIIqVIaFrc0m-dto-EvBaNAnqZ_J3qqedSiUBUIBV1u43ALlylS31l8nE9SCb76UdMusVHxahxPShfXQMHrTioE_7CUH1HcwcUVsdjxIjckJM2gyhA3/s640/paint_swatches_rotated_cropped_calibrated.jpg" width="640" /></a></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Hardware store paint swatches: a good example of the benefits of low resolution (</span><a href="https://www.billstruevalue.com/paint.html" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Bill's True Value</a>)</div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">In short, the gamut I choose to map represents a perceptually uniform subset of all colors capable of being displayed by modern screens, with the resolution tailored to fit the application.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b><br /></b></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b>Visualization Goals</b></span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b><br /></b></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">With the gamut established, the next task is deciding how to best visualize it. I stipulate that it be in 2D, i.e. that it be a simple image, so that a user can see all colors all at once without having to rotate, scroll, or otherwise interact. I also want it to be maximally continuous, consistent, and intuitive. By this I mean that colors should be near their closest neighbors, placed using the same set of "rules", and understood with minimal explanation.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Given the 2D constraint, it is not possible to be maximally continuous, consistent, and intuitive, all at once. In other words, it is not possible to meaningfully reduce the rank of color from 3D to 2D, in any general sense, without irreversible loss of information. This would be a true breakthrough, so it is not surprising that it has stubbornly resisted all attempts to "crack" it, from me and all previous color theorists.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">After considering many visualization approaches, some of which are captured in the Appendix, I settled on a simple arrangement of cross-sections. This inherently introduces discontinuities (between cross-sections), but their quantity is minimized; otherwise this visualization is extremely consistent and intuitive.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b>Map Design</b></span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Given the cross-section approach, the next question is how to section, and how to arrange the sections. To minimize discontinuity, the natural choice is to take the sections along the axis with the smallest range. At 1.0 JND, the RGB gamut in Lab space has the following domains:</span><br />
<br />
<ul>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">L: 2.3 to 98.9, 42 JND</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">a: -83.8 to 95.5, 78 JND</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">b: -105.6 to 92.2, 86 JND</span></li>
</ul>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Note that the size of the domains vary significantly by axis. Because of the perceptual uniformity of Lab space, position and direction are irrelevant to color distance - only the Euclidean distance matters. Therefore, it's completely valid to compare ΔE values regardless of which axis/axes they occur along.</span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">The interpretation of this domain data is interesting: it is saying that L, or value/brightness, is the <i>least</i> perceptually consequential component of color. What we think of as hue (color name) and saturation (color intensity) are about twice as perceptually important. Hue and saturation are defined in Lab space as angle and distance about the L axis, which is also the "neutral" axis because all purely gray shades occur along it. The LCh color space uses these more intuitive coordinates, but it's fundamentally describing the same data. This is the same as how a point in 3D space can be described in Cartesian or spherical coordinates, and still refer to the same point.</span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR8Bmw__UwqSZ1rA335S48L9wQz0Tqx51LEL122Qfaw0PJ0TYVlIoDBBQvcMEpWXFB6LsmOtr4tOHJXZOx68q1ks1LfOkHHgSVfayOMls8WIIykgnQ_IZTHL9xxr0O4TVBM0u7U-77oykg/s1600/gamut_inside_boundary.GIF" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="574" data-original-width="577" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjR8Bmw__UwqSZ1rA335S48L9wQz0Tqx51LEL122Qfaw0PJ0TYVlIoDBBQvcMEpWXFB6LsmOtr4tOHJXZOx68q1ks1LfOkHHgSVfayOMls8WIIykgnQ_IZTHL9xxr0O4TVBM0u7U-77oykg/s1600/gamut_inside_boundary.GIF" /></a></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">RGB color gamut in Lab space, polyhedral boundary shown as gray mesh, uniformly filled</span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">This indicates that the optimal section plane is a-b, i.e. perpendicular to / along the L axis, which has the smallest domain. Further, it suggests that the gamut is not exactly square, and that b is generally larger in magnitude than a, which turns out to be true. Therefore, to minimize the size of the color map image, the sections should be arranged with the b axis vertical, for better packing. This also lends itself nicely to having a horizontal and b vertical, which is more intuitive than vice versa due to the alphabetical Cartesian x-y convention. I arrange the sections such that their neutral axes are all aligned, they are as close together as possible without overlapping, with a and b positive corresponding to right and up, and with L increasing across sections from left to right.</span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b>Map Properties</b></span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b><br /></b></span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">To validate the method and build intuition about the visualization, it's worthwhile looking at the color map on a channel-by-channel basis.</span></div>
<div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEBsYN9MSa__903_rMyq2MAn45Okp-U5t9FMF3HNE_45jHm-XnMFh3DPnPDha5VOXJkrhmrEVjOa1WGPpPMp0WB5gufZnl0_2B0xQ8xoqwwlGSxGAbKZIq7zqGWExtkrmPsGl5LavbDUMm/s1600/color_map_hue_channel.png" style="margin-left: 1em; margin-right: 1em;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><img border="0" data-original-height="98" data-original-width="753" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEBsYN9MSa__903_rMyq2MAn45Okp-U5t9FMF3HNE_45jHm-XnMFh3DPnPDha5VOXJkrhmrEVjOa1WGPpPMp0WB5gufZnl0_2B0xQ8xoqwwlGSxGAbKZIq7zqGWExtkrmPsGl5LavbDUMm/s1600/color_map_hue_channel.png" /></span></a></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"> Lab hue channel</span></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Lab hue corresponds to angle about the L/neutral axis, with an artificial appearance of a seam where 0° meets 360°. In reality, the two angles are equivalent, as in a circle.</span></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrsxPFTPbOgUDGhCh7GnYOd8pJH-PuiRNbZAlSw4uQqKm0uKPEmCRyFkaQKg6TkzqUv6ZWhpAkRT18q8ealQHmKR_OsHTb7a-ckyR8nKXB0J2UeVXe0nzI_Ha95El3p_WccAQT3YEE-BKW/s1600/color_map_sat_channel.png" style="margin-left: 1em; margin-right: 1em;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><img border="0" data-original-height="103" data-original-width="749" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrsxPFTPbOgUDGhCh7GnYOd8pJH-PuiRNbZAlSw4uQqKm0uKPEmCRyFkaQKg6TkzqUv6ZWhpAkRT18q8ealQHmKR_OsHTb7a-ckyR8nKXB0J2UeVXe0nzI_Ha95El3p_WccAQT3YEE-BKW/s1600/color_map_sat_channel.png" /></span></a></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"> Lab saturation channel</span></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Lab saturation corresponds to normal distance from the L/neutral axis, so each section has a circular appearance. Note that highly saturated colors occur more at higher values.</span></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiehTM4eK_eIYV-0uFsI2gzq0o-g8mJiV0kaErAi1RGVIUj6XeO0ALireNhC1E0m8gaZWwfoEHxgina-vxGZGMnCjaYxnyz2u6IxytyNYcMbjpiQU86ggRujkXZQIUQy5UGsnR7NqSlwxCA/s1600/color_map_val_channel.png" style="margin-left: 1em; margin-right: 1em;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><img border="0" data-original-height="106" data-original-width="749" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiehTM4eK_eIYV-0uFsI2gzq0o-g8mJiV0kaErAi1RGVIUj6XeO0ALireNhC1E0m8gaZWwfoEHxgina-vxGZGMnCjaYxnyz2u6IxytyNYcMbjpiQU86ggRujkXZQIUQy5UGsnR7NqSlwxCA/s1600/color_map_val_channel.png" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Lab value channel</span></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Lab value is constant within sections, so there is a simple linear relationship across sections from left to right, progressing from darkest (black) to lightest (white).</span></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPjV7zUMBSN_VZLcl2XrP7qtzZrdgWJ_sMLy1CRrTzpCSwYt9c8EXaWBYHxJ-HpH8p4x7TVjC5kxyy9jWCZIBRRiaOj76oW-DXp_LMwBVu1bhuWBSjFX8sfB0wQOp4VMFNvWqZ9KpY2cOD/s1600/color_map_a_channel.png" style="margin-left: 1em; margin-right: 1em;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><img border="0" data-original-height="100" data-original-width="753" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPjV7zUMBSN_VZLcl2XrP7qtzZrdgWJ_sMLy1CRrTzpCSwYt9c8EXaWBYHxJ-HpH8p4x7TVjC5kxyy9jWCZIBRRiaOj76oW-DXp_LMwBVu1bhuWBSjFX8sfB0wQOp4VMFNvWqZ9KpY2cOD/s1600/color_map_a_channel.png" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Lab a channel</span></div>
<div class="separator" style="clear: both; text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">a is the horizontal distance within the section, corresponding to a theoretical green-magenta axis.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhw-31uen7FkSJPl1gKpJ2CfDhtiz4uFv4zWPRZ43TpxBquskk9X4QJ_X7zj52NRczKuaPAqxAGwIA0dLf2I6Ep4nCZqr4ZXqKH7xyB2P-DzbWClbgnxhJJHtFgUmDFCAkD6Yt5A7PCFS1Y/s1600/color_map_b_channel.png" style="margin-left: 1em; margin-right: 1em;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><img border="0" data-original-height="100" data-original-width="753" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhw-31uen7FkSJPl1gKpJ2CfDhtiz4uFv4zWPRZ43TpxBquskk9X4QJ_X7zj52NRczKuaPAqxAGwIA0dLf2I6Ep4nCZqr4ZXqKH7xyB2P-DzbWClbgnxhJJHtFgUmDFCAkD6Yt5A7PCFS1Y/s1600/color_map_b_channel.png" /></span></a></div>
<div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Lab b </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">channel</span></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"></span><br />
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">
b is the vertical distance within the section, corresponding to a theoretical blue-yellow axis. It is loosely accurate to think of it as a color temperature axis, from cool to warm.</span></div>
<div style="text-align: center;">
<span style="text-align: left;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></span></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b>Map Usage</b></span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b><br /></b></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">The next question that should rightfully be asked is: so what? To answer that, </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">I show three cases for how this color map can be used for interacting with color.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><u>Case 1: which color should I pick?</u></span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">I am not a fan of conventional color pickers such as those found in Photoshop, GIMP, etc., because they are fundamentally rooted in 2D and are disorientating to use.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqrl8ZXa2FxmY72zw3IOhGEZj6mczM9wMpxOAQoPcbqesmzvSQ78NkyN7t2YD0AGJFymU8eAgTT71l2lOy_4A-KctylmjPsBWBfwhmQGSkVXe8HpiYh5-NdwTqdoNU-jdY9nmIiLQ5lNMB/s1600/color_picker_GIMP.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="345" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqrl8ZXa2FxmY72zw3IOhGEZj6mczM9wMpxOAQoPcbqesmzvSQ78NkyN7t2YD0AGJFymU8eAgTT71l2lOy_4A-KctylmjPsBWBfwhmQGSkVXe8HpiYh5-NdwTqdoNU-jdY9nmIiLQ5lNMB/s1600/color_picker_GIMP.gif" /></a></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Picking a color in GIMP in HSV space</span></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><i><br /></i></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Here, the color map has the advantage of keeping all colors visible and intuitively arranged at all times. The user can pick freely, find neighbors easily, and visualize how their selection fits within the broader gamut.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD-x5Sky_7BSve1Z4PRkUhtyPgWHTdC241Rl497ll8t4H5o_bIsSbm45vU8RkdzI_X6vVoFfjThO6mnojuj5Xn7K3nUoFgByp8wuS42FdeLTL5SWPVIw89H9xckXCkGeP_FWbvGviOWFdM/s1600/color_pick_demo_2.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="195" data-original-width="742" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhD-x5Sky_7BSve1Z4PRkUhtyPgWHTdC241Rl497ll8t4H5o_bIsSbm45vU8RkdzI_X6vVoFfjThO6mnojuj5Xn7K3nUoFgByp8wuS42FdeLTL5SWPVIw89H9xckXCkGeP_FWbvGviOWFdM/s1600/color_pick_demo_2.gif" /></a></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Demo of picking arbitrary colors from the color map</span></div>
<br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><u>Case 2: where is this color within space?</u></span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><i><br /></i></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Because of how relativistic and cognitive color perception is, it is often very challenging to actually identify "what" a color actually is. </span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Its context can have a shockingly significant effect on how it is perceived, as many well-known optical illusions neatly show. It may be desirable to gauge or counteract these effects by showing where an arbitrary color, e.g. from an image, occurs within the color map.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9zJYqk9n3m1dwlklLu_gJ9nl94lZDD-NZ2qlsgLlX2no2UXrXp8hl6gPn5GMhS-ozOv5WzhGVbd_GQg0XPIRCdoYRK2RVZIz748nbZgD8RMwfebrazg2fEklGLLv8NaESxhGWxywzL4xJ/s1600/789px-Checker_shadow_illusion.svg.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="789" height="303" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9zJYqk9n3m1dwlklLu_gJ9nl94lZDD-NZ2qlsgLlX2no2UXrXp8hl6gPn5GMhS-ozOv5WzhGVbd_GQg0XPIRCdoYRK2RVZIz748nbZgD8RMwfebrazg2fEklGLLv8NaESxhGWxywzL4xJ/s400/789px-Checker_shadow_illusion.svg.png" width="400" /></a></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><a href="http://persci.mit.edu/gallery/checkershadow">Checker shadow illusion</a>: A and B are the exact same color!</span></div>
<br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Because the color map has many fewer unique colors than images do, locating an arbitrary color on the color map is done by error minimization. It is approximate, not exact. In many cases, such as mine, exact matching is not important.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4PG0csqEYTFXJP2dp0D0ZFz-nzBnSN7-Oq2FRoqhpj8aLBET8g2apC9jBieKN35iITgjU9TBunCB_xlLzWVeCeamHjjua5hFKByIrPFKD9r9WXbR3vPb2OVPwZljWMpv9HaH3OdFK1IdJ/s1600/color_match_demo_9.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="365" data-original-width="704" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4PG0csqEYTFXJP2dp0D0ZFz-nzBnSN7-Oq2FRoqhpj8aLBET8g2apC9jBieKN35iITgjU9TBunCB_xlLzWVeCeamHjjua5hFKByIrPFKD9r9WXbR3vPb2OVPwZljWMpv9HaH3OdFK1IdJ/s1600/color_match_demo_9.gif" /></a></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Demo: locating arbitrary image colors within the color map</span></div>
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Note that when the color is displayed as a standalone swatch and dissociated from its context, its appearance can change dramatically. For example, note that the cloud shadows are actually beige-brown, but appear gray in the context of the image.</span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI-9f7BL9Kz8uwsdrMd4ygCFkDXL9y8UwALbWrZ_H_0I-oaoZ39u4RI7B68nQaaK5H0AhUuzwWQ7PVoZLbtVwgyVIKSiT6-7e4feR4odt-X0f9goSaH_uaqROLvksbONoCkf0DxkNVLYpR/s1600/color_match_demo_10.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="365" data-original-width="704" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiI-9f7BL9Kz8uwsdrMd4ygCFkDXL9y8UwALbWrZ_H_0I-oaoZ39u4RI7B68nQaaK5H0AhUuzwWQ7PVoZLbtVwgyVIKSiT6-7e4feR4odt-X0f9goSaH_uaqROLvksbONoCkf0DxkNVLYpR/s1600/color_match_demo_10.gif" /></a></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><i><br /></i></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Here, the dissociation shows that the grassy field, which "reads" as beige-brown, is actually better described as a strong orange.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><i><br /></i></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><u>Case 3: how is this image working?</u></span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><b><br /></b></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">A user may wish to better understand how a image is working, i.e. visualize how it is using the color gamut to achieve its effect(s). This is rarely trivial, so another case where visualization can provide insight.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">The error minimization approach described above is fine for a single color, but for a whole image it is prohibitively slow. To work around this, I define a Lab precision in units of ΔE, round both image and map to the precision, then simply match exactly between the image and map. This is more approximate but operates dramatically faster. I set ΔE such that at least 95% of image colors are matched to map colors, which is typically around ΔE = 10. A small number of image colors are not matched and not shown on the map.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Here are some sample images, with the corresponding "usage" map beneath each, and some insights that can be gained from each. Any map color that is not used at least once is shown as "grayed out". Showing unused colors is important for a couple reasons: which colors are <i>not </i>used can be just as insightful as which colors <i>are </i>used, and the unused colors help visually position the used colors within the section.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjreYZ3vPA8c7iL4JPtlcG-YsEQU2WCIAJ1PcSm_9Iuz3b9nz9eHVHaj9fJtiAhPCeAfojN6lDeb3MNrZAWY93_RNzULlEfXU0xnkN6GrMdpii8uE7Qimox9_ejN2_gWgbudJgTe0vrREa_/s1600/IMG_4127_augmented.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjreYZ3vPA8c7iL4JPtlcG-YsEQU2WCIAJ1PcSm_9Iuz3b9nz9eHVHaj9fJtiAhPCeAfojN6lDeb3MNrZAWY93_RNzULlEfXU0xnkN6GrMdpii8uE7Qimox9_ejN2_gWgbudJgTe0vrREa_/s400/IMG_4127_augmented.JPG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9baECZ3eOd9bT-iHt9KFSWaz9p1FnD2ILioeMImdIzDcIoy3iFabrPAbR76DJIkyaPhKHAnFhfUKugcQOdcXHpMoufZ_aOCxNmAhfC-vz1xcIxlJQcRn7lRXBE2LCbbWt92nxLVeGG_EB/s1600/IMG_4127_augmented_usage_10_dE_2x_scale.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="78" data-original-width="672" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9baECZ3eOd9bT-iHt9KFSWaz9p1FnD2ILioeMImdIzDcIoy3iFabrPAbR76DJIkyaPhKHAnFhfUKugcQOdcXHpMoufZ_aOCxNmAhfC-vz1xcIxlJQcRn7lRXBE2LCbbWt92nxLVeGG_EB/s1600/IMG_4127_augmented_usage_10_dE_2x_scale.png" /></a></div>
<div style="text-align: left;">
</div>
<ul>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Good value range - uses the gamut relatively fully without saturating limits</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Saturated darks and highs, neutral mids</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Color contrast primarily coming from b (blue-yellow or vertical) axis, minimal usage of a (green-magenta) axis for color differentiation</span></li>
</ul>
<br />
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSByLfWnpnliqyM4RXys7tajX79CAWrElYTh3V688pHt_n1eJkGDxg3OkV4XojpdgLspCHXXw-lDZ9Copuy7nO5sAyKT0WWDCchqrH3wQRFawFCxMYHsapyXP196CY-swlcooktsJxFSl0/s1600/IMG_3326.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSByLfWnpnliqyM4RXys7tajX79CAWrElYTh3V688pHt_n1eJkGDxg3OkV4XojpdgLspCHXXw-lDZ9Copuy7nO5sAyKT0WWDCchqrH3wQRFawFCxMYHsapyXP196CY-swlcooktsJxFSl0/s400/IMG_3326.JPG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2fdaSGH8WOy6O1Z9n9KwPt47WNzyY7CXWGi12uW4Wb24apSZd24xNEToETnHYV0H4tAyokYEwrNE8lYn4YWdT1fbDw0cNNXNJcyPc4mDzAAjjhK5lbQOM61ZUs6aw_jl2oN1vT9-VAtRu/s1600/IMG_3326_usage_10_dE_2x_scale.png" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="78" data-original-width="672" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2fdaSGH8WOy6O1Z9n9KwPt47WNzyY7CXWGi12uW4Wb24apSZd24xNEToETnHYV0H4tAyokYEwrNE8lYn4YWdT1fbDw0cNNXNJcyPc4mDzAAjjhK5lbQOM61ZUs6aw_jl2oN1vT9-VAtRu/s1600/IMG_3326_usage_10_dE_2x_scale.png" /></a><br />
<div style="text-align: center;">
</div>
<ul>
<li style="text-align: left;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Nearly saturated on low end of value</span></li>
<li style="text-align: left;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Very warm palette - almost all values for b are positive</span></li>
<li style="text-align: left;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">High saturation throughout value range</span></li>
</ul>
<br />
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiseSGgTcpInVYGdn7vmyDx_RGv3WrDx4c53LQb5Rn6uW4pTGoGtwDl3v7PEanKzMB591JBldSq3fJzolCb1f35cL9L4BCr2CF4mKov5wsMqkwABOkn85RioQ6HxyvioETnLNdm9s3Gqojj/s1600/IMG_4062_augmented.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiseSGgTcpInVYGdn7vmyDx_RGv3WrDx4c53LQb5Rn6uW4pTGoGtwDl3v7PEanKzMB591JBldSq3fJzolCb1f35cL9L4BCr2CF4mKov5wsMqkwABOkn85RioQ6HxyvioETnLNdm9s3Gqojj/s400/IMG_4062_augmented.JPG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcIk4oa-SNPVzqeE2gc6nVWnpdL-v0EMbsJjT_pwSuycq_vPfRXVF6Er9YMawikCyGQZi8QsmLnUJs5VX2xokHRBXPa_2DneESje4REC6iPGe4AFvimAwTHTH5SF4w4gMuiD-e9vA87UMD/s1600/IMG_4062_augmented_usage_10_dE_2x_scale.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="78" data-original-width="672" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcIk4oa-SNPVzqeE2gc6nVWnpdL-v0EMbsJjT_pwSuycq_vPfRXVF6Er9YMawikCyGQZi8QsmLnUJs5VX2xokHRBXPa_2DneESje4REC6iPGe4AFvimAwTHTH5SF4w4gMuiD-e9vA87UMD/s1600/IMG_4062_augmented_usage_10_dE_2x_scale.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Value nearly saturated on both ends of range</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Fairly constant green-yellow hue over value range</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">More saturation along b than a</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Very warm temperature - all b values are positive, except in darks which are cooler</span></li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9lZcCYPzkw0STRtBBAnDJDeYAifMqc451rBRNrTiAp9N3vb15ZLxoiSRuTNTMmG4t9jsjnph2kpA4EiwmMUk2dDEgndmNYAdXkbMjdxmEW_WbId_LG6DXcEvyaZTQuegQ32LPckeDcSEs/s1600/IMG_2901.JPG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9lZcCYPzkw0STRtBBAnDJDeYAifMqc451rBRNrTiAp9N3vb15ZLxoiSRuTNTMmG4t9jsjnph2kpA4EiwmMUk2dDEgndmNYAdXkbMjdxmEW_WbId_LG6DXcEvyaZTQuegQ32LPckeDcSEs/s400/IMG_2901.JPG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHuVHr0K3qLW6GPiBEv-DVHhHExtDbH9O0ZnWB6odHcsKRvV66H1pe4xVcH_-wUt2OU80b8pj80wgUtm5DfiCxKtwP8PFQAlbFuV9HxT1ByOqt6iDkW8Dcktv9YbuE2j50tNCOVddICrA8/s1600/IMG_2901_usage_10_dE_2x_scale.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="78" data-original-width="672" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHuVHr0K3qLW6GPiBEv-DVHhHExtDbH9O0ZnWB6odHcsKRvV66H1pe4xVcH_-wUt2OU80b8pj80wgUtm5DfiCxKtwP8PFQAlbFuV9HxT1ByOqt6iDkW8Dcktv9YbuE2j50tNCOVddICrA8/s1600/IMG_2901_usage_10_dE_2x_scale.png" /></a></div>
<div style="text-align: left;">
</div>
<ul>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Very low saturation throughout image, clustering around neutral axis</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Low end of value range is saturated</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Image primarily based on value contrast</span></li>
<li><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Higher saturation at higher value (sky region)</span></li>
</ul>
<br />
<div style="text-align: center;">
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></div>
<div style="text-align: left;">
<b><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Results</span></b></div>
<div style="text-align: left;">
<b><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span></b></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Below are native-resolution (1 pixel per color) versions of my color map at various color resolutions for download. They are rendered in PNG format with a transparent background. These differ from the color maps shown in the introduc</span><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">tion, which were upsampled for web display.<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5GVx3BYjJrEPhdHDGuimj_QG_-hgFQJumAtaOJx1sCYAeUgDIxvBxIJnFuFdVue7My_H5vAelQNFVD-Yjwh6lpFc_1GTnxghJRbEcsXO6u7Q0y4ugVVgU0BCIog-CLGdqjmQuBZOkn1xj/s1600/color_gamut_Lab_541_colors_5_JND_11.5_dE_1x_scale_transparent.png"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5GVx3BYjJrEPhdHDGuimj_QG_-hgFQJumAtaOJx1sCYAeUgDIxvBxIJnFuFdVue7My_H5vAelQNFVD-Yjwh6lpFc_1GTnxghJRbEcsXO6u7Q0y4ugVVgU0BCIog-CLGdqjmQuBZOkn1xj/s1600/color_gamut_Lab_541_colors_5_JND_11.5_dE_1x_scale_transparent.png" /></a><br />5.0 JND, 541 colors<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigtmqwqqza4g6h2Xxn36B3kpl8AUgVxdUgytonXiZ8FyBlRFuDj63bmdMSlsEEETVW8CJ5Bm8LjPW0-80RJYblnFaynCCF79H3IEtWmxTNwqLa2T566KajkxpyGne92Mroxm_5R0rRgggy/s1600/color_gamut_Lab_1052_colors_4_JND_9.2_dE_1x_scale_transparent.png"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigtmqwqqza4g6h2Xxn36B3kpl8AUgVxdUgytonXiZ8FyBlRFuDj63bmdMSlsEEETVW8CJ5Bm8LjPW0-80RJYblnFaynCCF79H3IEtWmxTNwqLa2T566KajkxpyGne92Mroxm_5R0rRgggy/s1600/color_gamut_Lab_1052_colors_4_JND_9.2_dE_1x_scale_transparent.png"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigtmqwqqza4g6h2Xxn36B3kpl8AUgVxdUgytonXiZ8FyBlRFuDj63bmdMSlsEEETVW8CJ5Bm8LjPW0-80RJYblnFaynCCF79H3IEtWmxTNwqLa2T566KajkxpyGne92Mroxm_5R0rRgggy/s1600/color_gamut_Lab_1052_colors_4_JND_9.2_dE_1x_scale_transparent.png" /></a><br />4.0 JND, 1,052 colors</span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXZSfA4NTQ7ggp318zgNoi1Cp_S_KknzDZMPVqteR64dFMPt9p7nL8C-C1YBcwa-3DsUymQNgyJXnHz_Smawrjo0NDfIJ3iPFiNF8wqMSVEueXyH31uV_GXwLWRTFPZFCHG6YIk7n8XuqY/s1600/color_gamut_Lab_2509_colors_3_JND_6.9_dE_1x_scale_transparent.png"></a><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXZSfA4NTQ7ggp318zgNoi1Cp_S_KknzDZMPVqteR64dFMPt9p7nL8C-C1YBcwa-3DsUymQNgyJXnHz_Smawrjo0NDfIJ3iPFiNF8wqMSVEueXyH31uV_GXwLWRTFPZFCHG6YIk7n8XuqY/s1600/color_gamut_Lab_2509_colors_3_JND_6.9_dE_1x_scale_transparent.png"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXZSfA4NTQ7ggp318zgNoi1Cp_S_KknzDZMPVqteR64dFMPt9p7nL8C-C1YBcwa-3DsUymQNgyJXnHz_Smawrjo0NDfIJ3iPFiNF8wqMSVEueXyH31uV_GXwLWRTFPZFCHG6YIk7n8XuqY/s1600/color_gamut_Lab_2509_colors_3_JND_6.9_dE_1x_scale_transparent.png" /></a><br />3.0 JND, 2,509 colors<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKwIqZw4Oozkkstlv-YJgUDgXO9hRUToJoduizlmNggdVlos_kPACDf9HwOVnPINqJBiIzh2ewqIz-StCb5-RBbATr5DIBKth8CVWrTuQ2xO9VNGOYQfWx2FXfKYZZh9SvRT0zZ98KU0n1/s1600/color_gamut_Lab_8434_colors_2_JND_4.6_dE_1x_scale_transparent.png"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKwIqZw4Oozkkstlv-YJgUDgXO9hRUToJoduizlmNggdVlos_kPACDf9HwOVnPINqJBiIzh2ewqIz-StCb5-RBbATr5DIBKth8CVWrTuQ2xO9VNGOYQfWx2FXfKYZZh9SvRT0zZ98KU0n1/s1600/color_gamut_Lab_8434_colors_2_JND_4.6_dE_1x_scale_transparent.png"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKwIqZw4Oozkkstlv-YJgUDgXO9hRUToJoduizlmNggdVlos_kPACDf9HwOVnPINqJBiIzh2ewqIz-StCb5-RBbATr5DIBKth8CVWrTuQ2xO9VNGOYQfWx2FXfKYZZh9SvRT0zZ98KU0n1/s1600/color_gamut_Lab_8434_colors_2_JND_4.6_dE_1x_scale_transparent.png" /></a><br />2.0 JND, 8,434 colors<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo_GCBSC7pUX_A3OM9g0tm4L11WP3HeW_PJAAc3c-e3C4T1pIkr8c2y8MLQBrUFinFdrJ19hlYgncabqOJ23ONBTvb_o89ihBWq1WoXqpJ0bEdKppiQWLg5WIDwUD2Zew4n1wE2wjvCy-o/s1600/color_gamut_Lab_67455_colors_1_JND_2.3_dE_1x_scale_transparent.png"><br /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo_GCBSC7pUX_A3OM9g0tm4L11WP3HeW_PJAAc3c-e3C4T1pIkr8c2y8MLQBrUFinFdrJ19hlYgncabqOJ23ONBTvb_o89ihBWq1WoXqpJ0bEdKppiQWLg5WIDwUD2Zew4n1wE2wjvCy-o/s1600/color_gamut_Lab_67455_colors_1_JND_2.3_dE_1x_scale_transparent.png"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjo_GCBSC7pUX_A3OM9g0tm4L11WP3HeW_PJAAc3c-e3C4T1pIkr8c2y8MLQBrUFinFdrJ19hlYgncabqOJ23ONBTvb_o89ihBWq1WoXqpJ0bEdKppiQWLg5WIDwUD2Zew4n1wE2wjvCy-o/s640/color_gamut_Lab_67455_colors_1_JND_2.3_dE_1x_scale_transparent.png" /></a><br />1.0 JND, 67,455 colors<br /><br /><b>Appendix: Alternate Sub-Optimal Visualizations</b></span><br />
<br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Along the way to developing this approach, I explored many alternate ideas, some of which are shown and briefly discussed here in chronological order.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIxCl0n4UGWp_Ovczb1r4JY3h6PsdvDqh6ZsvPf4rCVu3n-bRXVetz860LZYune-t8JKSGdAnzAFndcVfQpxkak1-tkX9734I9anX2-A87cpxZyDdG13EeEoDXCGGv7FR7ov3Kcfkb9HxD/s1600/all_RGB_colors_section_channel_1_section_direction_1_sort_rows_Lab_4_ascend_sort_cols_RGB_2_ascend_512_px.png" style="margin-left: 1em; margin-right: 1em;"><span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivNDhJ0pTWu0dDOFJnIvv6SdC_K-zsHKyMD9J_E-ig1ihHl1_a1TprAaD63mdFD7Lx_mmfaNAwG7MoqqHQkmAbFPnyjhAnkE4AGSgSMSm3CRBvK14HcBLN8Hyy58XPK-OwDw5yRGpp-4Xr/s1600/all_RGB_colors_section_channel_1_section_direction_1_sort_rows_Lab_4_ascend_sort_cols_Lab_3_ascend_512_px.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivNDhJ0pTWu0dDOFJnIvv6SdC_K-zsHKyMD9J_E-ig1ihHl1_a1TprAaD63mdFD7Lx_mmfaNAwG7MoqqHQkmAbFPnyjhAnkE4AGSgSMSm3CRBvK14HcBLN8Hyy58XPK-OwDw5yRGpp-4Xr/s1600/all_RGB_colors_section_channel_1_section_direction_1_sort_rows_Lab_4_ascend_sort_cols_Lab_3_ascend_512_px.png" /></a></div>
<div style="text-align: center;">
<br /></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Generated by sorting rows and columns according to various color properties. Depending on the sort parameters, some pleasant results are possible but not very useful. The common pitfall is noise/discontinuity and trying to fit the irregular gamut into a regular square.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzqAff2feUFmxczpvDu_O_p2Zo0qyXPhbRzACnnYBEw2LSD-_VylV8Uq4VO36MwUSf65wkETufFOf7J_-GZTiaMZKRJlM-09KUbcLMUBZQJGQqQDQ1KskjXOC0ZdUVp7jdfvHkLKRFqrGV/s1600/color_gamut_non_square_test.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="242" data-original-width="1600" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzqAff2feUFmxczpvDu_O_p2Zo0qyXPhbRzACnnYBEw2LSD-_VylV8Uq4VO36MwUSf65wkETufFOf7J_-GZTiaMZKRJlM-09KUbcLMUBZQJGQqQDQ1KskjXOC0ZdUVp7jdfvHkLKRFqrGV/s640/color_gamut_non_square_test.png" width="640" /></a></div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">A histogram approach, with the x axis representing hue. This looks good, but doesn't hold up under closer inspection, as within a single hue "bin", there is no good method of sorting value and saturation along a single dimension. Again, noise is a problem, though it is better hidden here.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgASZycVb8iqg1djk2u5W364hQ-Iz9Ru9hVSnKySn0H002eXtTPc4L1XqNgPF6s0jJcLe9JscLtJGAfRWVY9G_qHJ-XSJhkUH-2Ozdbwoj3yfSq-miOEZHizOIwLrLJk8-dDUy4d4fRLkzz/s1600/test_res.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgASZycVb8iqg1djk2u5W364hQ-Iz9Ru9hVSnKySn0H002eXtTPc4L1XqNgPF6s0jJcLe9JscLtJGAfRWVY9G_qHJ-XSJhkUH-2Ozdbwoj3yfSq-miOEZHizOIwLrLJk8-dDUy4d4fRLkzz/s640/test_res.png" width="640" /></a></div>
<div style="text-align: center;">
<br /></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">A Mercator projection of the Lab gamut idealized on a spherical shell. The problem here is that saturation gets "left behind" by the geometric transforms, so it appears throughout the map as discontinuous sparse gray patches.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGrRml_0VTeOMNUUUPPArIwY-zM4ou6L2lqO_jIq5BNC0gD01Zp9oFkws5tWbMBGtY2fPiajRDDML9LiyLg8TtFbd5yk61Pj3qNH1yCkFs32SobN3tvbpWfItgZ36zoutGYq5O7Af9-j6z/s1600/color_gamut_convect_test.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1600" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGrRml_0VTeOMNUUUPPArIwY-zM4ou6L2lqO_jIq5BNC0gD01Zp9oFkws5tWbMBGtY2fPiajRDDML9LiyLg8TtFbd5yk61Pj3qNH1yCkFs32SobN3tvbpWfItgZ36zoutGYq5O7Af9-j6z/s640/color_gamut_convect_test.png" width="640" /></a></div>
<div style="text-align: center;">
<br /></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">A projection of the gamut point cloud onto the a-b plane using a particle simulation to represent a projecting, divergent force. It works well initially, but falls apart as it works outward due to "leftover" colors with highly discontinuous values.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfp_Oyzu5PqKAgKaW7g9LVB-mdcZsSU_oKNqBgltVWzgKZ_Zf4FlV81xjnMwdDZ81DMpJ1z6rShKqll_yvEfVWQbRQCsUr1OVrIchGpmVvKNyuEO7pxDLq62wqkDaipN_ETRedS7ovIR8v/s1600/color_gamut_67487_colors_2.3_dE_0.69_polyhedron_scale_300_dpi_4000_px.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfp_Oyzu5PqKAgKaW7g9LVB-mdcZsSU_oKNqBgltVWzgKZ_Zf4FlV81xjnMwdDZ81DMpJ1z6rShKqll_yvEfVWQbRQCsUr1OVrIchGpmVvKNyuEO7pxDLq62wqkDaipN_ETRedS7ovIR8v/s640/color_gamut_67487_colors_2.3_dE_0.69_polyhedron_scale_300_dpi_4000_px.png" width="640" /></a></div>
<div style="text-align: center;">
<br /></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">A compromise using a globe projection, wherein the color gamut is partitioned into "high" and "low" saturation hemispherical subsets which intersect at at the equator, exploiting the singularity at pure black for hemispherical continuity. This enables continuous encoding of hue and saturation, with 1-bit encoding of saturation. This approach could be extended to N "hemispheres" (here, N=2), but at the cost of sacrificing the intuitive globe framework.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj915_5uoWdQn7H0Uhb9BuXUsL22WYDAwCCmsHwLEcscdy0u3VbFeS9JyKCAD_x1RcVnrRaYy1A2-riRtyGDkiAajjIpCm7s1mp595T7ks3OcbY_hOfsjaSnmFhAV0SoQZdJZqHPgUw3rSl/s1600/pinwheel_test.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="647" data-original-width="664" height="622" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj915_5uoWdQn7H0Uhb9BuXUsL22WYDAwCCmsHwLEcscdy0u3VbFeS9JyKCAD_x1RcVnrRaYy1A2-riRtyGDkiAajjIpCm7s1mp595T7ks3OcbY_hOfsjaSnmFhAV0SoQZdJZqHPgUw3rSl/s640/pinwheel_test.png" width="640" /></a></div>
<div style="text-align: center;">
<br /></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">A "pinwheel" model wherein N circular sectors have similar hue, and within a sector, radius corresponds to saturation and angle corresponds to value. This is not a bad visualization, but is fairly discontinuous and non-uniform.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdPL9hwTT37iPK415snaW-5Lshh1dNHNFGRdSIYmIrhboUIRcmUe0xEUBHaisDqZQoU2vvflkA1_1yEVtjZ_5Sk-6o7QG2Zuyxulqg_hFvNBv-ctGKFCakwWuSBwDHIS97unhU6yEUsQZA/s1600/gravitation_test.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="699" data-original-width="652" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdPL9hwTT37iPK415snaW-5Lshh1dNHNFGRdSIYmIrhboUIRcmUe0xEUBHaisDqZQoU2vvflkA1_1yEVtjZ_5Sk-6o7QG2Zuyxulqg_hFvNBv-ctGKFCakwWuSBwDHIS97unhU6yEUsQZA/s640/gravitation_test.png" width="596" /></a></div>
<div style="text-align: center;">
<br /></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Another particle simulation with attractive, repulsive, and cohesive forces simulated based on physical and color distance between particles. This produces interesting animations and results, but the result ultimately is not that good, and the axes essentially have no meaning.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFqscktEVq28teTtKzYBE4ZbczRkLX__cwHJRMdA5Fz6wkmz-bLYOiWYICOVoyNtlh4sjkjpCBRQXqERdEABrv75fz1xqf5DBInC0dq0i9aOVC9yrG6rzTMMtOEm8JXyI_ouFL9FZhghfc/s1600/sobel_swap_test.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="228" data-original-width="447" height="326" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFqscktEVq28teTtKzYBE4ZbczRkLX__cwHJRMdA5Fz6wkmz-bLYOiWYICOVoyNtlh4sjkjpCBRQXqERdEABrv75fz1xqf5DBInC0dq0i9aOVC9yrG6rzTMMtOEm8JXyI_ouFL9FZhghfc/s640/sobel_swap_test.png" width="640" /></a></div>
<div style="text-align: center;">
<br /></div>
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">A test of using a Sobel edge detection filter as a cost function to be minimized by random pixel swaps. Again, this method encodes no color information with the axes, merely arranges colors, and the cost function is prone to exploitation.</span><br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrDVOP4LKqeWKArKOafftponhHDZfX8rDEUyYsjVxipy2CyoibU_EAZckMtnHXTsbm9txhv4JIKCgi1jQlY9di4r1gyLty5T2fIb5AgXfXthb1MdWvuaFFezoarFMPaNvAo5Si19zuCpOi/s1600/rainbow_smoke_test_004_upsampled.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="733" data-original-width="932" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrDVOP4LKqeWKArKOafftponhHDZfX8rDEUyYsjVxipy2CyoibU_EAZckMtnHXTsbm9txhv4JIKCgi1jQlY9di4r1gyLty5T2fIb5AgXfXthb1MdWvuaFFezoarFMPaNvAo5Si19zuCpOi/s320/rainbow_smoke_test_004_upsampled.PNG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNEozkoy47-HCRKYE1VPvPvNm1kQzQ4OKeniPilq40aNEIAO2Af8GV-bpIpbSdIKmtNPQC0TdsyLYRTCsjGJiFo-Q1Tkk7Or-QDz-G7FM8kkMwq2IzDUsC39Ten8L3HdgjiA529ULXxzJ0/s1600/rainbow_smoke_test_033_upsample.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="664" data-original-width="656" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNEozkoy47-HCRKYE1VPvPvNm1kQzQ4OKeniPilq40aNEIAO2Af8GV-bpIpbSdIKmtNPQC0TdsyLYRTCsjGJiFo-Q1Tkk7Or-QDz-G7FM8kkMwq2IzDUsC39Ten8L3HdgjiA529ULXxzJ0/s320/rainbow_smoke_test_033_upsample.png" width="316" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVG83jMFpTtVZVXtyva7P8pZVs_BLMBQTEhIX5lj03Tt1BQ6PZdWmYuvsGhtJTBt5uxl4X0bZeRvDPaiEl1XDUdCz2xn7JdYDG82iFEC-n_9eOiql5dhOuC8i-ksYmasARrrTWfPLizivF/s1600/rainbow_smoke_test_058_upsample.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="846" data-original-width="846" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjVG83jMFpTtVZVXtyva7P8pZVs_BLMBQTEhIX5lj03Tt1BQ6PZdWmYuvsGhtJTBt5uxl4X0bZeRvDPaiEl1XDUdCz2xn7JdYDG82iFEC-n_9eOiql5dhOuC8i-ksYmasARrrTWfPLizivF/s320/rainbow_smoke_test_058_upsample.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8M4xBBUMSG9ZBFNSNXQKwZJrKpkOspL1P3UbUax_12e9kOsfgLf_vkbp-qVBsxStdVgBw4MieuTMb1PAchGv-ppyW3KpKLq3FvO__RcjPkacxowCO4tnz990_AlTPILhbCVIFW_0QrvY_/s1600/spheres_without_grid_crop.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="840" data-original-width="814" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8M4xBBUMSG9ZBFNSNXQKwZJrKpkOspL1P3UbUax_12e9kOsfgLf_vkbp-qVBsxStdVgBw4MieuTMb1PAchGv-ppyW3KpKLq3FvO__RcjPkacxowCO4tnz990_AlTPILhbCVIFW_0QrvY_/s320/spheres_without_grid_crop.png" width="309" /></a></div>
<br />
<span face="" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">A few variations on the "<a href="http://rainbowsmoke.hu/home">rainbow smoke" algorithm</a> which starts with a sparsely seeded image, then grows it outward pixel by pixel using color difference minimization at the border. I experimented with various seeding approaches and was somewhat successful at encoding hue with angle, but again this merely amounts to color arrangement, which may look nice but doesn't encode meaningful information. It is also very computationally expensive.</span>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com1tag:blogger.com,1999:blog-3278537004721616095.post-64438235267253480272020-05-17T14:39:00.000-07:002020-05-18T10:04:20.267-07:00Color Navigation Map<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Overview</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In this article, I introduce a new and useful tool for practitioners of digital color called the <i>Color Navigation Map </i>(CNM). Inspired by geographical maps, the CNM displays a perceptually-uniform and -complete subset of the </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://en.wikipedia.org/wiki/RGB_color_model">RGB color gamut</a> in a single image, with colors arranged continuously, consistently, and intuitively. It </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">provides </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">persistent awareness of position within color space, so that it can be navigated, learned, and utilized more effectively.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3MZAwmF2AoEX2d6XxCg4dXqAMl2ZNg907AUioJFmFoGqtcqd7NucmZ5oaUSCxpJc0K-HYMrNsZeksD2HbYc4147p2x92FWeWTSZS6d1A2y8SlQKddXVa2Aml00MKCepgc2-WEH-CiUnlQ/s1600/color_gamut_67487_colors_2.3_dE_0.69_polyhedron_scale_300_dpi_4000_px.png" imageanchor="1" style="font-family: "helvetica neue", arial, helvetica, sans-serif; margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="800" data-original-width="1600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3MZAwmF2AoEX2d6XxCg4dXqAMl2ZNg907AUioJFmFoGqtcqd7NucmZ5oaUSCxpJc0K-HYMrNsZeksD2HbYc4147p2x92FWeWTSZS6d1A2y8SlQKddXVa2Aml00MKCepgc2-WEH-CiUnlQ/s640/color_gamut_67487_colors_2.3_dE_0.69_polyhedron_scale_300_dpi_4000_px.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Color Navigation Map (CNM): ~67,000 perceptually-uniform and -complete colors, spanning the full RGB gamut</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Technical Summary</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The CNM samples the full RGB color gamut <a href="https://en.wikipedia.org/wiki/Polyhedron">polyhedron</a> in <a href="https://en.wikipedia.org/wiki/CIELAB_color_space">Lab space</a> with a perceptually uniform discretization of 2.3 </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; text-align: center;">ΔE or 1.0 <a href="https://en.wikipedia.org/wiki/Color_difference#CIE76">JND</a> (just noticeable </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">differences). It uses <a href="https://en.wikipedia.org/wiki/CIELAB_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC">CIELCh</a> hue, saturation, and value to map colors within the intuitive <a href="https://en.wikipedia.org/wiki/Spherical_coordinate_system">spherical system</a> of meridians, hemispheres, and parallels. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The singularity at pure black is exploited to bifurcate the gamut into two continuous and equal hemispherical subsets of "high" and "low" saturation, by scaling the gamut polyhedron along its "a" and "b" axes. This approach </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">enables </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1-bit encoding of saturati</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">on as hemisphere, and continuous encoding of hue and value as azimuth and elevation. A continuous spline <a href="https://en.wikipedia.org/wiki/Histogram_equalization">histogram equalization</a> algorithm is used to evenly distribute hues between the full range of azimuth angles. The equal-area <a href="http://equal-earth.com/equal-earth-projection.html">Equal Earth map projection</a> is used to flatten the spherical coordinate system into 2D, and a <a href="https://en.wikipedia.org/wiki/Voronoi_diagram">Voronoi diagram</a> is used to convert the sparse points to a dense image. The CNM has constant hue along meridians, constant value along parallels, similar saturation in each hemisphere, and roughly equal representation for all hues.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJMq10uZzWk8rZyTok6x44vUF917e1vIfMp-TSVVc2TnjSHPQ4JNXiKSLkg0O9db5TjA9ZflbEWbGZRS44Xzoqef5OnxhQQxxRGWmz2wNBBYQMpcBKo8lrDr7giOc-G6reYJ0xXVrmoXEr/s1600/CNM_properties.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="683" data-original-width="1600" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJMq10uZzWk8rZyTok6x44vUF917e1vIfMp-TSVVc2TnjSHPQ4JNXiKSLkg0O9db5TjA9ZflbEWbGZRS44Xzoqef5OnxhQQxxRGWmz2wNBBYQMpcBKo8lrDr7giOc-G6reYJ0xXVrmoXEr/s640/CNM_properties.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">CNM annotated with key features</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Dimensionality and Lessons from Mapmaking</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fundamentally, digital color is 3D. Whether described in RGB, HSV, XYZ, Lab, or any number of other color spaces, all colors are defined by a unique triad of independent values. Meanwhile, screens are 2D. This inherent rank mismatch leads to significant awkwardness in working with digital color. Selecting a color is akin to leafing through a whole book to find a specific illustration, instead of simply picking it out from many illustrations hanging in gallery. Disorientation in color space is therefore very natural, and a key challenge to using color effectively.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Technically speaking, the task of continuously arranging all colors in 2D, with no gaps or exclusions, is not possible. However, mapmaking has shown that technical limitations need not preclude practical solutions: Earth's surface cannot be fully represented in 2D, yet map projections have successfully facilitated navigation for centuries. In terms of rank, color is more complex even than cartography <span style="background-color: white; color: #222222; font-size: 16px;">—</span> whereas an azimuth/elevation pair corresponds to a single value like altitude on a globe, in LCh space, any pair of properties corresponds to <i>multiple</i> values. This is like the difference between a solid spherical ball, and a hollow spherical shell.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Images Containing All Colors, and Their Limitations</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This project originated from <a href="http://www.brucelindbloom.com/">Bruce Lindbloom</a>'s "<a href="http://www.brucelindbloom.com/downloads/RGB16Million.png">An RGB Image Containing All Possible Colors</a>", which takes the RGB B value like a "page" index and creates 256 sub-images for each possible value.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP8BUEhzMJVzYlfQegdfqMi0IAncNT8eIz2Z_PoZhaLrKntogMyv3rKv_Ctl-NGonSAxSJr8Fydsc5y6qtinRS1DT7g4zoBOqU3GZL9i20H60f23hVgbEzgQ1e8ypM-CHvP7ENvPaDbiZ9/s1600/RGB16Million.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1600" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP8BUEhzMJVzYlfQegdfqMi0IAncNT8eIz2Z_PoZhaLrKntogMyv3rKv_Ctl-NGonSAxSJr8Fydsc5y6qtinRS1DT7g4zoBOqU3GZL9i20H60f23hVgbEzgQ1e8ypM-CHvP7ENvPaDbiZ9/s400/RGB16Million.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Bruce Lindbloom's "An RGB Image Containing All Possible Colors"</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I immediately appreciated the utility of the image, but wondered if the colors could arranged in a more </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">useful way. After some experimentation I concluded that some strategic relaxation of constraints would be needed make a truly useful map of all colors. Shown below are some of these experiments, generated by sorting the pixels of the Lindbloom image by various properties.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijgvWdiVLB_BYU6Hr6rpT9QGvq_PVWl5yUmroxPm7mmJtSuvihC7_Ag73z4Ke0DTqDM73y0cYEsXysbfJ4F62Gllc4bYWNC6V0cd7UzwOysFsFP-OtYt5E5Qu9H9-3ZrlkUfIlKLEv103b/s1600/all_RGB_colors_section_channel_1_section_direction_1_sort_rows_Lab_4_ascend_sort_cols_RGB_3_ascend_512_px.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijgvWdiVLB_BYU6Hr6rpT9QGvq_PVWl5yUmroxPm7mmJtSuvihC7_Ag73z4Ke0DTqDM73y0cYEsXysbfJ4F62Gllc4bYWNC6V0cd7UzwOysFsFP-OtYt5E5Qu9H9-3ZrlkUfIlKLEv103b/s400/all_RGB_colors_section_channel_1_section_direction_1_sort_rows_Lab_4_ascend_sort_cols_RGB_3_ascend_512_px.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Rows sorted by Lab hue, columns sorted by RGB B value</span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE_OFFPsv3mo9BpHaO2NwGEzbO7fgLwLmO3b4XwPqmX_POqHk6RytFdc-b7UTAxkJAfwcKAwj0nAvjUIt8vyo6avj4tPDseYNg4uNNRzenvC7tCuOGQUuyguVt9n4EydWD2x84-fNM2wt9/s1600/all_RGB_colors_section_channel_1_section_direction_1_sort_rows_HSV_2_ascend_sort_cols_Lab_4_ascend_512_px.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE_OFFPsv3mo9BpHaO2NwGEzbO7fgLwLmO3b4XwPqmX_POqHk6RytFdc-b7UTAxkJAfwcKAwj0nAvjUIt8vyo6avj4tPDseYNg4uNNRzenvC7tCuOGQUuyguVt9n4EydWD2x84-fNM2wt9/s400/all_RGB_colors_section_channel_1_section_direction_1_sort_rows_HSV_2_ascend_sort_cols_Lab_4_ascend_512_px.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Rows sorted by HSV saturation, columns sorted by Lab hue</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Although some macroscopic order exists, images created this way are plagued by high-frequency noise which at best creates the illusion of continuity, as if by dithering.</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A more recent open-ended competition called "<a href="https://codegolf.stackexchange.com/questions/22144/images-with-all-colors">Images With All Colors</a>" challenged coders to best arrange all RGB colors as single pixels as they saw fit, producing a number of interesting results:</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh3Oe2oV83aWIsc8UT8qH0qp9mmMigLqbZOE_PkQBkzekeBNG2Vh4rLQyX1yEtarjCclyxs3Utw7Ei1KlkYWJ2gE_SrtLgILTf-3C5fy9niY_ESYp798dyZQuViz_47qlW-ipM9y0OhHpP/s1600/MlIL8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhh3Oe2oV83aWIsc8UT8qH0qp9mmMigLqbZOE_PkQBkzekeBNG2Vh4rLQyX1yEtarjCclyxs3Utw7Ei1KlkYWJ2gE_SrtLgILTf-3C5fy9niY_ESYp798dyZQuViz_47qlW-ipM9y0OhHpP/s400/MlIL8.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"<a href="http://rainbowsmoke.hu/home">Rainbow Smoke</a>" by József Fejes</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig4No2iJ9xKnMf2nRWq8mk4ZNCEgNpVhbrC8hmlguAAJPfAXixNN8vDJjZ3trYtx74fcrGQa_HenpO30VmRPNFNjiSdz0oU2tryE3Wk-OEB74Bar3V0qKluHs-5FmTu-Zmm_jdHbDbC653/s1600/1msnf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="512" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig4No2iJ9xKnMf2nRWq8mk4ZNCEgNpVhbrC8hmlguAAJPfAXixNN8vDJjZ3trYtx74fcrGQa_HenpO30VmRPNFNjiSdz0oU2tryE3Wk-OEB74Bar3V0qKluHs-5FmTu-Zmm_jdHbDbC653/s400/1msnf.png" width="400" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"Tileable diamonds"</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">There is actually a website devoted specifically to this challenge, <a href="http://allrgb.com/">allRGB.com</a>, showing a number of different approaches and results.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjykvLUhYnCnvtMDmQ4trF1FDt3stvQSxeOzFKvjheIDrQl1LoMIHukdGcPnW7sgGFx9wKbb_P36iNOOyzto5F5r-BHeEJZ5dePSanTmiM8A-XiLh9jKcThiMxel0cwXY_mVNYRPjr-FnHa/s1600/allRGB_2020-05-17.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="919" data-original-width="1600" height="366" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjykvLUhYnCnvtMDmQ4trF1FDt3stvQSxeOzFKvjheIDrQl1LoMIHukdGcPnW7sgGFx9wKbb_P36iNOOyzto5F5r-BHeEJZ5dePSanTmiM8A-XiLh9jKcThiMxel0cwXY_mVNYRPjr-FnHa/s640/allRGB_2020-05-17.PNG" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="http://allrgb.com/">allRGB.com</a>, a website devoted to images containing all colors</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">However, due to inherent limitations, no image produced under these constraints has continuous, consistent, and intuitive placement of color.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">All mapmaking involves compromises and balancing competing priorities, and the "color mapping" problem is no different. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">After much of trial and error, I eventually developed a method that produces a result that is well-balanced in terms of my "</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">continuous, consistent, and intuitive" guiding principles. To clarify these:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>Continuous:</u> adjacent colors have minimal color difference</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>Consistent:</u> all colors are treated the same; strong alignment between colors with matching color properties</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>Intuitive:</u> color positions can be predicted from color properties, and vice versa; map is simple and requires minimal explanation</span></li>
</ul>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Method Summary</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Generate a uniform RGB color gamut. Only the boundary is of interest, so a resolution of about 25 values per channel, or 25^3 = ~15,000 total colors, is sufficient for convergence.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Calculate the polyhedral boundary of the RGB color gamut in Lab space. Note that the boundary is slightly concave, so a convex hull algorithm will provide slightly inaccurate results. MATLAB's built in </span><span style="font-family: "courier new" , "courier" , monospace;"><a href="https://www.mathworks.com/help/matlab/ref/boundary.html">boundary.m</a></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://www.mathworks.com/help/matlab/ref/boundary.html"> </a>works well for this, provided that a non-zero shrink factor is used to account for the slight concavity.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Uniformly sample the volume inside the polyhedron using a fixed ΔE of 2.3 in L, a, and b. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I use </span><a href="https://www.mathworks.com/matlabcentral/fileexchange/37856-inpolyhedron-are-points-inside-a-triangulated-volume"><span style="font-family: "courier new" , "courier" , monospace;">inpolyhedron.m</span></a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> for this purpose. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In the figures below, I show </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ΔE = 10 for the sake of illustration. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ΔE</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> value of </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2.3 corresponds to one "just noticeable difference" or JND, a reasonably fine discretization of the continuous Lab space. Finer or coarser values of </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ΔE can be used as needed.</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLpZaA5lFXrTIXT8N5F_eUEFo1iE79PImB31Z8snglebzoFMNsLCCHh_WL2FaquyLj_vfnAII46UkdH8ZFnFsCaPi0JGZvMIuis8tVRoaeEvAFK1ouaAlYHEdPcc7NBxeWAF-2_UN1qRQL/s1600/gamut_inside_boundary.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="574" data-original-width="577" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiLpZaA5lFXrTIXT8N5F_eUEFo1iE79PImB31Z8snglebzoFMNsLCCHh_WL2FaquyLj_vfnAII46UkdH8ZFnFsCaPi0JGZvMIuis8tVRoaeEvAFK1ouaAlYHEdPcc7NBxeWAF-2_UN1qRQL/s1600/gamut_inside_boundary.GIF" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Perceptually uniform colors sampled at </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ΔE = 10 </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">inside the RGB polyhedron in Lab space</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqhiDPqKMoGU5QL1NTeXOMPYP_LbFNhrVKdXZ5fUwKo8bQM9IM2BO-88Th3zvXZkXSJkuk8NqHmppiPnB_rafdTMMs4lePa5krluOuV3dHZU1hJjfwSgxBj5clq8A0YRMSS-VUrj71MLWO/s1600/Lab_gamut_ab_plane_view.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="459" data-original-width="470" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqhiDPqKMoGU5QL1NTeXOMPYP_LbFNhrVKdXZ5fUwKo8bQM9IM2BO-88Th3zvXZkXSJkuk8NqHmppiPnB_rafdTMMs4lePa5krluOuV3dHZU1hJjfwSgxBj5clq8A0YRMSS-VUrj71MLWO/s1600/Lab_gamut_ab_plane_view.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">View of ab plane for uniformly sampled colors</span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUNpwpkhGMrwvaDlA7eNGfeaTgd4U_c_AEMS0jCX3DEB14gI2SlslbWISPmGWpnzH1Blhzitf5UaLugzXd7YWZVD7BLot2P4QN9j2nD913JGkf_8TsFsMkR1Vt_Qr7HZEgcxQoNXFoPBgZ/s1600/dE_10_in_RGB_space.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="420" data-original-width="560" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUNpwpkhGMrwvaDlA7eNGfeaTgd4U_c_AEMS0jCX3DEB14gI2SlslbWISPmGWpnzH1Blhzitf5UaLugzXd7YWZVD7BLot2P4QN9j2nD913JGkf_8TsFsMkR1Vt_Qr7HZEgcxQoNXFoPBgZ/s1600/dE_10_in_RGB_space.GIF" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span><br />
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">
</span>
<br />
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Perceptually uniform colors sampled at ΔE = 10 in RGB space</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">
</span>
<br />
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">
Purge neutral colors, defined as having an LCh saturation < 1.0. This purges "true" neutrals, among them pure white and pure black. Because true neutrals satisfy </span><span style="font-family: "courier new" , "courier" , monospace;">a = b = 0</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">, and LCh hue is defined as </span><span style="font-family: "courier new" , "courier" , monospace;">atan2d(b,a)</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">, neutrals have an undefined hue and cannot be consistently placed in the map.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Linearly map LCh hue to azimuth angle, and LCh value to elevation.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fit a monotonically increasing <a href="https://en.wikipedia.org/wiki/Spline_(mathematics)">spline</a> to the <a href="https://en.wikipedia.org/wiki/Cumulative_distribution_function">cumulative distribution function (CDF)</a> of azimuth (hue) angle for continuous histogram equalization, resulting in a roughly even <a href="https://en.wikipedia.org/wiki/Probability_density_function">probability density function (PDF)</a>. This compensates for the significantly non-uniform distribution of hues within the gamut polyhedron.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUXVUjjgFbHLk-xlgKvxxLUBBaWdUy_LQXMSAyB6V5Ju__zK3j5mtAMs5EjVKIC_kLg7B-YciTqbLkVtFU6tO_VyjLJfsDyhHnPofs62Z_0A1Mvu7Onmw8oLT_M6LkA-VTmC1vNlyY4ffz/s1600/spline_equalization_plots.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="382" data-original-width="1041" height="234" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjUXVUjjgFbHLk-xlgKvxxLUBBaWdUy_LQXMSAyB6V5Ju__zK3j5mtAMs5EjVKIC_kLg7B-YciTqbLkVtFU6tO_VyjLJfsDyhHnPofs62Z_0A1Mvu7Onmw8oLT_M6LkA-VTmC1vNlyY4ffz/s640/spline_equalization_plots.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Continuous spline histogram equalization of azimuth (LCh hue)</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuezznePXBfS-vfyhkvSSrAbYZOGQds14oFa4EF8xO3cous_gIj7fGINtTOBaqfrHstQMUA_fHl7MnjKBDc0_-9GpTYjL9llL-sR2KZVMImqKHCdy0iN5JZEviancYASeiQAgB9f1mTTyg/s1600/top_view_before_after_histeq_comp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="334" data-original-width="819" height="261" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuezznePXBfS-vfyhkvSSrAbYZOGQds14oFa4EF8xO3cous_gIj7fGINtTOBaqfrHstQMUA_fHl7MnjKBDc0_-9GpTYjL9llL-sR2KZVMImqKHCdy0iN5JZEviancYASeiQAgB9f1mTTyg/s640/top_view_before_after_histeq_comp.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Top view of colors before (left) and after (right) azimuthal histogram equalization</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Scale the gamut polyhedron by 69% about the a and b axes to partition the gamut into two hemispherical subsets of roughly equal volume and color quantity. Colors outside the scaled polyhedron are assigned to the upper hemisphere; inside to lower. Applying no scaling to L maintains the common black/white singularities, such that both sub-gamuts converge to the same color at extreme high and low values, a necessary condition for inter-hemispherical/equatorial continuity.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIadPHu76rnoI8MW6rEGB_pZ3Ka5p7AK5Zo18uM8V9SlZcbQKqBMPeME1b1fbTlPO0fPGppSVw5BkPDYyJt_4owMNyHNmuUF91cLJHObkEn-HkeUbjiKAElNhAcZyUYBaz_sBlEA1-7y4S/s1600/polyhedron_boundary.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="521" data-original-width="560" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIadPHu76rnoI8MW6rEGB_pZ3Ka5p7AK5Zo18uM8V9SlZcbQKqBMPeME1b1fbTlPO0fPGppSVw5BkPDYyJt_4owMNyHNmuUF91cLJHObkEn-HkeUbjiKAElNhAcZyUYBaz_sBlEA1-7y4S/s1600/polyhedron_boundary.GIF" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Scaled polyhedron boundary for bifurcation of color gamut into hemispheres</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Invert elevation for the inner sub-gamut, i.e. allocate the less-saturated colors to the lower hemisphere.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXN-3R91d31glLyD7mX6EKABBQSlgyVrnwJ5Oo4faXkjiHqIDIuDo61vQMpn8GwP2866Q7dvrarJgxSSmOlucVnNe1ou7XswugyGPZs-asBlir0ity4CArUfuT0jUuvgqVtmSimiSSIiNO/s1600/sphere_sparse.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="486" data-original-width="560" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXN-3R91d31glLyD7mX6EKABBQSlgyVrnwJ5Oo4faXkjiHqIDIuDo61vQMpn8GwP2866Q7dvrarJgxSSmOlucVnNe1ou7XswugyGPZs-asBlir0ity4CArUfuT0jUuvgqVtmSimiSSIiNO/s1600/sphere_sparse.GIF" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Colors mapped to unit spherical surface by LCh hue, saturation, and value </span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Use the </span><a href="http://equal-earth.com/equal-earth-projection.html" style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">Equal Earth map projection</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> to flatten the spherical coordinate system into 2D. The choice of Equal Earth among other map projections was motivated by its equal-area constraint, symmetry, minimal distortion, illustrative shape, and ease of implementation.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhudvjAXY2L5nncaWRmhTfMywZegNtAFSo7wksJUA_2FVgWtWU-0-Fy1D_7_H7G7953vzY0Vai-x30BBLlhgyQPLYOjFb8PXHWcM6H4xD5k0vVh0wsb3S4E8Xxw5pRz3vaQUR0ZVa7w5itn/s1600/Proj_Illus1-4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="428" data-original-width="878" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhudvjAXY2L5nncaWRmhTfMywZegNtAFSo7wksJUA_2FVgWtWU-0-Fy1D_7_H7G7953vzY0Vai-x30BBLlhgyQPLYOjFb8PXHWcM6H4xD5k0vVh0wsb3S4E8Xxw5pRz3vaQUR0ZVa7w5itn/s640/Proj_Illus1-4.jpg" width="640" /></a></div>
<div style="text-align: center;">
<a href="http://equal-earth.com/equal-earth-projection.html" style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; text-align: start;">Equal Earth map projection</a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2HFYygDztlOOoItHwft5jjM-ccXtFMGwM-TU4i9ZlvXBHD8lHQvPJ-JrJITYysgkE5pp706PhVAiNwCvhyphenhyphenjKIfpmtluuLW3fXxPQP-h5aL_Asx-frCnMdkejCOPLhetzI97dId2AM4QqP/s1600/equal_earth_sparse.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="486" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2HFYygDztlOOoItHwft5jjM-ccXtFMGwM-TU4i9ZlvXBHD8lHQvPJ-JrJITYysgkE5pp706PhVAiNwCvhyphenhyphenjKIfpmtluuLW3fXxPQP-h5aL_Asx-frCnMdkejCOPLhetzI97dId2AM4QqP/s1600/equal_earth_sparse.png" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Map projection of colors on spherical surface to flat plane</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Create a Voronoi diagram for the map projection; fill cells using the closest color.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Overlay parallel and meridian lines as desired. Set area outside of map projection as transparent.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Properties of the CNM</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">By design, the CNM has several useful properties intended to make it as continuous, consistent, and intuitive as possible:</span><br />
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Meridians (vertical lines of constant azimuth/latitude) have constant LCh hue</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Parallels (horizontal lines of constant elevation/longitude) have constant LCh value</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Hemispheres have similar LCh saturation</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">LCh hues have roughly equal representation</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio05xM020KYItiGmr7hu_QH-N5D6P6RuG_W9mU2AzaRYwdDhwgMZ-EJHosoL24kvwDlvaLP6XiJEU282J0iLMBSbBi7XhbR0MitAMqDFgam1LX5vCq1wFW7vrwMhjjzxH4w3xB0sdRAJOu/s1600/channel_view_hue.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="338" data-original-width="644" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEio05xM020KYItiGmr7hu_QH-N5D6P6RuG_W9mU2AzaRYwdDhwgMZ-EJHosoL24kvwDlvaLP6XiJEU282J0iLMBSbBi7XhbR0MitAMqDFgam1LX5vCq1wFW7vrwMhjjzxH4w3xB0sdRAJOu/s1600/channel_view_hue.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeHByK5CXuKoKzQeb56-VNBqSdt5S2i3_U0WNfD-YFb34CBMtXItmWorVJcX2DRB9Q3f42J-rbGgWOAmpOEcGDTxNmRuwB90BUfr53G9NGv4FPFcS2YGjeROjdjyC0wo7i6QXpFrR77ecy/s1600/channel_view_val.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="343" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeHByK5CXuKoKzQeb56-VNBqSdt5S2i3_U0WNfD-YFb34CBMtXItmWorVJcX2DRB9Q3f42J-rbGgWOAmpOEcGDTxNmRuwB90BUfr53G9NGv4FPFcS2YGjeROjdjyC0wo7i6QXpFrR77ecy/s1600/channel_view_val.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvZgbjQ5l4-xS2th-sEpQZm7NklozqyWxYNvtv2XEZ9Q7Dhwdm43SxrU-gJvaK2xby9HXjGfhqjj8ck5hMJEntrkDim6V-IJfeJC0N80GZCx7TZxVapThLBLTrjqMcl1hVUirKjwnyW_nX/s1600/channel_view_sat.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="343" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvZgbjQ5l4-xS2th-sEpQZm7NklozqyWxYNvtv2XEZ9Q7Dhwdm43SxrU-gJvaK2xby9HXjGfhqjj8ck5hMJEntrkDim6V-IJfeJC0N80GZCx7TZxVapThLBLTrjqMcl1hVUirKjwnyW_nX/s1600/channel_view_sat.png" /></span></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Histogram equalization is deliberately not applied to the output CNM image, as the gamut polyhedron is itself not R/G/B balanced due to the perceptual non-uniformity of RGB space. As a consequence of the geometric mapping strategy, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">t</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">he CNM does not have equal area for each color contained, although the degree of non-uniformity is mitigated significantly by the use of azimuthal histogram equation and an equal-area map projection. Equality of area per color may be improved in future iterations, but probably cannot be solved completely without breaking more important CNM constraints.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<b><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">U</span></b><b style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">sing the CNM</b><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Because the CNM does not strictly contain all RGB colors, positioning oneself within it must be done by color difference minimization, rather than exact matching. Because an Lab discretization level of 2.3 </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ΔE or 1.0 JND was used, any arbitrary input color (e.g. from a photo) can be matched to within 1.0 JND of a point/color within the CNM.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In this demo, I select colors from a photo randomly, and they are matched and positioned on the CNM, providing persistent awareness of position within color space. Here I'm using CIE76 color difference for speed, but CIE94 or CIEDE2000 could be used for better accuracy on faster hardware and/or software.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Note that the GIF format used here for convenience is limited in terms of color depth, so some compression artifacts occur. Also, I've sped up the GIF for the sake of illustration.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBxmSaFOVE7fCLD2IJy3m6Kj0o_2dT8t10klByWyJJRtAmSSWCORQnH864bDVJxpcPQ79rP9oNQma5nL6XOtmNmEfdkNaACsHnNeyGjjchmiXZSn-LuIe6I4g927_v6AhAyvTv_RmfVTTR/s1600/color_match_demo_inline.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="501" data-original-width="700" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBxmSaFOVE7fCLD2IJy3m6Kj0o_2dT8t10klByWyJJRtAmSSWCORQnH864bDVJxpcPQ79rP9oNQma5nL6XOtmNmEfdkNaACsHnNeyGjjchmiXZSn-LuIe6I4g927_v6AhAyvTv_RmfVTTR/s1600/color_match_demo_inline.GIF" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Demo of matching photo colors against the CNM</span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The CNM can also serve as a perceptually complete and persistent palette of colors from which a user can freely select.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxaq3n3MCAd20uXyGwfUNZsevhvOlgA_brvgBsHUqKjbX6xuonK6rWdqFbXvkTPVhabavcYRPt2aSKcQpryqgWAD-rea0XM92JvKil8ED6gMNIE-tZp5Eti78kZ1NYum9rP3YOT-mMVfZa/s1600/color_pick_demo.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="296" data-original-width="738" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxaq3n3MCAd20uXyGwfUNZsevhvOlgA_brvgBsHUqKjbX6xuonK6rWdqFbXvkTPVhabavcYRPt2aSKcQpryqgWAD-rea0XM92JvKil8ED6gMNIE-tZp5Eti78kZ1NYum9rP3YOT-mMVfZa/s1600/color_pick_demo.gif" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Demo of picking colors from the CNM</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Compare the simplicity and persistence of this color selection process with the conventional approach found in <a href="https://www.gimp.org/">GIMP</a> and Photoshop:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjynOmvY887-LQg-BOjJBuRFDnSaZNPwXsQTkn2I4ze7hvfPrQxOvynCCI0zqMHz479-vjuuMaL5RWNxngGa4r3n-NGgD3oKXs6pDmh9E1XAKMEhhdX8kYS0ZCeZwaRwFzGdlCKTJVYeYOZ/s1600/color_picker_GIMP.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="345" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjynOmvY887-LQg-BOjJBuRFDnSaZNPwXsQTkn2I4ze7hvfPrQxOvynCCI0zqMHz479-vjuuMaL5RWNxngGa4r3n-NGgD3oKXs6pDmh9E1XAKMEhhdX8kYS0ZCeZwaRwFzGdlCKTJVYeYOZ/s1600/color_picker_GIMP.gif" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Conventional color picking in GIMP</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">To get to any single color in GIMP, you must first adjust a hue slider, then pick an x, y point to define saturation and value. At any single moment in time, you can only see a single hue. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Although the conventional approach offers much finer color resolution, it's much less intuitive, not persistent, and does not capture the highly relativistic aspect of color. Picking colors effectively requires awareness not just of the single color at hand, but also how it fits and interacts with all other colors in its scene. This aspect is simply missing from the conventional approach.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In a broader sense, as the name suggests, the CNM is designed for navigation; in other words, to be used as a compositional aid for painters, illustrators, designers, etc., who are interested in planning how their work will use the available gamut of colors and the associated relativistic effects to convey their ideas most effectively. This is analogous to how early explorers used geographical maps to plan their routes according to both the terrain and their goals.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I expect that other uses for the CNM may present themselves over time.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Other Variants</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Up to this point, I've been describing what I consider to be the "default" parameters of the CNM, best tailored for my personal use, but many are adjustable. In this section, I'll show some variants to motivate other uses.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSv-Kp7CeE45VvlySPB9W8psKsQO722WMjyONW7mZkzLYoCujEyh5togWDFsZgAIYVlHJLLX-NyKhsX0fn3U82wh0yG7Yj5VhMPML0KV3TVHPAoFeWNdctehCxny6CQ7nu7Wv7fIh9y2Xd/s1600/color_gamut_67487_colors_2.3_dE_0.69_polyhedron_scale_300_dpi_2000_px.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSv-Kp7CeE45VvlySPB9W8psKsQO722WMjyONW7mZkzLYoCujEyh5togWDFsZgAIYVlHJLLX-NyKhsX0fn3U82wh0yG7Yj5VhMPML0KV3TVHPAoFeWNdctehCxny6CQ7nu7Wv7fIh9y2Xd/s640/color_gamut_67487_colors_2.3_dE_0.69_polyhedron_scale_300_dpi_2000_px.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ΔE = 2.3, ~67,000 colors, w</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">hite equator</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here the value mapping is inverted, so that the equator is white and the poles are black. I decided against this configuration as the RGB gamut is significantly fuller around black than white, resulting in fewer equatorial gaps. Still, this configuration might be preferable in some cases.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5sqfI8ehZd2NIPOzV082dqRYXhw_lPYwy9Sjg4TOkIYiaVtqv7S4gEP4v_idbUsdb5l8MY6IyVQhsOCsxQ3np8X2BPFSdOT1P8Cgwg4vLMcmsSbhy-3tvmO_DfDDQFkakXjEAK9XRqWd6/s1600/color_gamut_820_colors_10_dE_0.69_polyhedron_scale_300_dpi_2000_px.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5sqfI8ehZd2NIPOzV082dqRYXhw_lPYwy9Sjg4TOkIYiaVtqv7S4gEP4v_idbUsdb5l8MY6IyVQhsOCsxQ3np8X2BPFSdOT1P8Cgwg4vLMcmsSbhy-3tvmO_DfDDQFkakXjEAK9XRqWd6/s640/color_gamut_820_colors_10_dE_0.69_polyhedron_scale_300_dpi_2000_px.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ΔE = 10.0, ~800 colors</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I also see utility in a full-domain yet low-resolution CNM. Here I've drawn the Voronoi boundaries in black to further accentuate the low resolution and coarse cell boundaries. It's much easier to choose between hundreds of colors instead of millions; in many cases the full resolution is not helpful, or even a hindrance.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil5K1f7agCRZGgsghIkMFwqXJEFtWviFiFdqgg7Cz20pY9gMLR_FLRanCvlxknvzFPQE6a3bhTgpD3RGekeqi_o2Xr64-ValrEqU1YJgKSkmTM8bWAuwKlpiq8wlEX8yJR_HSwNjNUUCbg/s1600/color_gamut_67487_colors_2.3_dE_0.69_polyhedron_scale_300_dpi_2000_px.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="1600" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil5K1f7agCRZGgsghIkMFwqXJEFtWviFiFdqgg7Cz20pY9gMLR_FLRanCvlxknvzFPQE6a3bhTgpD3RGekeqi_o2Xr64-ValrEqU1YJgKSkmTM8bWAuwKlpiq8wlEX8yJR_HSwNjNUUCbg/s640/color_gamut_67487_colors_2.3_dE_0.69_polyhedron_scale_300_dpi_2000_px.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ΔE = 2.3, ~67,000 colors, meridians every 45° and parallels every 22.5°</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Lines of constant elevation and/or latitude can also be overlaid to convey contours of constant property and suggest the shape and distortion of the map projection.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Source Code</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Coming soon to <a href="https://github.com/kindofdoon">my GitHub</a>.</span>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-89426419409451114802020-04-16T19:54:00.000-07:002020-04-18T14:35:12.109-07:00Oil Painting Color Calibration<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A simple, effective method and algorithm for low-cost DIY color calibration of oil painting photos. Uses r</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">eadily made neutrals of pure black, any number of grays, and pure white to automatically and efficiently set white balance and levels.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyxhrevVTegO0sTqZhU2LiiItSVl_TJ8nl0luqjIQ4syV-BgWiLY1sWXmIuZ5BMsUrtmbTmAYLJ0xyBtArIp985M4DKHt8YIofLvFGo5Jsa9lQ4yirC-LedrhpK7ftlbzxa-hQt87IUpJT/s1600/CONOPS.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyxhrevVTegO0sTqZhU2LiiItSVl_TJ8nl0luqjIQ4syV-BgWiLY1sWXmIuZ5BMsUrtmbTmAYLJ0xyBtArIp985M4DKHt8YIofLvFGo5Jsa9lQ4yirC-LedrhpK7ftlbzxa-hQt87IUpJT/s640/CONOPS.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /><b>Working Principle</b><br /><br /> Color arises from the interaction of light, surface reflectance, and an observer - see <a href="http://www.kindofdoon.com/2019/07/how-paints-mix.html">here</a> for more on how this </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">works. The amount and quality of light illuminating an object affects its perceived color. This is easy to overlook, however, because the human brain is extremely proficient at mentally normalizing for lighting so that perceived colors are consistent across different types of lighting. Ove</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">rcoming this remarkable ability is a central challenge of becoming a good painter! For example, you probably see a banana as simply "yellow", regardless of the lighting conditions that can actually cast it as beige, brown, or orange.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge1kqZh6ccij8MkUTWZl-WNUxtS9VrVS-NPHpuv2_idklNKqMT2L-O28_IeFurapIFfJEbJwv3Zd0fuStyZdy-BVPoDtETyPe4Y90nNuuregLPBhCnKe6mAkBimYAOVpfuPZPHYYRZG-aa/s1600/banana_colors.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="791" data-original-width="1269" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge1kqZh6ccij8MkUTWZl-WNUxtS9VrVS-NPHpuv2_idklNKqMT2L-O28_IeFurapIFfJEbJwv3Zd0fuStyZdy-BVPoDtETyPe4Y90nNuuregLPBhCnKe6mAkBimYAOVpfuPZPHYYRZG-aa/s640/banana_colors.png" width="640" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Bananas - yellow, or not?</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Cameras, on the hand, have no such ability. They record only the literal information of a scene, and in doing so make guesses about the n</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ature and amount of light present. These are often inaccurate, leading to white balance and levels adjustments being very common operations in photo retouching.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">White balance describes the quality of the light in the scene. Cameras often have predefined white balance settings for outdoors, indoors, shade, etc. If the setting is not specified, the camera is forced to guess the "color cast" that the lighting imparts on the scene, and adjust for it accordingly. A neutral light, one without a color cast, imparts no color of its own on the scene. Non-neutral light can have any color cast, but in everyday settings, the most common are yellowish/warm as with incandescent bulbs, and bluish/cool as with fluorescent bulbs.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Opinions differ on best methods for displaying paintings, and as a matter of taste, there is no right answer. I believe that a neutral light is preferable, for two key reasons:</span><br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Neutral light imparts no color cast, resulting in maximum color differentiability.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The most natural, familiar, and abundant of light sources, daylight, is approximately neutral.</span></li>
</ol>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">It follows that a neutral light incident on a neutral paint produces a neutral color. The algorithm outlined here enforces this constraint for any number of known neutrals, thereby correcting unwanted color cast. This is commonly called a white balance correction.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Since black and white are neutral, it's possible to not only use them for white balance, but also to use them for levels - in other words, defining which colors correspond to black and white, by remapping. By capturing black, white, and several neutrals in a single operation, you can elegantly set calibrated white balance and levels at the same time.</span><br />
<b style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;"><br /></b>
<b style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">Neutral</b><b><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">s Colors</span></b><br />
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A neutral is any color with zero saturation: black, white, and all shades of gray in between. </span><br />
<br />
<i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In Digital Color</span></i><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Neutrals satisfy the condition R=G=B in RGB color space. Since the space is 8-bit, there are 2^8 = 256 true neutrals possible; R=G=B=0 is pure black, and R=G=B=255 is pure white. A much larger number of near-neutrals also exist.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>In Oil Paint</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Neutrals can be achieved similarly by mixing between pure white and pure black. Unlike in digital color, an infinite number of neutral grays are possible between pure black and white.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Neutral Calibration Swatches</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The key to this method is to have known neutrals in the same frame, under the same lighting, as the painting being photographed. Conventionally, photographers purchase pre-made certified-neutral swatches, but out of pandemic-related necessity I opted to make my own. However, I later realized that there's actually substantial benefit in a DIY approach, because the calibration is then tailored to your specific palette; plus, mixing a value range is good general practice anyway, and produces a helpful chart you can refer back to later.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In theory, this method can work with as few as two neutrals (black and white), but having a number of intermediate neutrals between ensures that the white balance is correct over the full value range, not just at the limits.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Using what I had on h</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">and, I arbitrarily mixed six neutrals, 1</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">" each on a 6" panel, starting with pure Reeves ivory black and brightening progressively up to pure Winsor & Newton titanium white. Ideally the neutrals are equally spaced in terms of their value (lightness), but this is not strictly necessary. Similarly, the paints and mixtures thereof should be truly neutral, but exact neutrality in the scientific sense is not necessary. Working by eye is sufficient for both aspects.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEG9Yq_pWbI2ei5V7O0t0LT_8ut8ZQad6i2axkvzjegdLqhqbT8Jv-sEg0c1QifL1SVuQs5x0J9gowQyVMBoPbbsRuCJiakWIga68POFOIsjuVO7UnUZmLVRl0TJo2MurD6thgnn9vPybE/s1600/mixing_neutrals.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="595" data-original-width="1600" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEG9Yq_pWbI2ei5V7O0t0LT_8ut8ZQad6i2axkvzjegdLqhqbT8Jv-sEg0c1QifL1SVuQs5x0J9gowQyVMBoPbbsRuCJiakWIga68POFOIsjuVO7UnUZmLVRl0TJo2MurD6thgnn9vPybE/s640/mixing_neutrals.jpg" width="640" /></span></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mixing six neutrals on my palette</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj445fgPd5SvXKYY7nLjbo-g0WFiqx1GGqu1QNIh5DVlch7mN2D2BgjJpqxZSy-FAj8mSSkRkjWEjITB5KdTW6IpbUzN-Y0tJIHlUsjSXnvxK8-BYkf2PHx_bCJHg5e1C8PypR2UuB_BZOe/s1600/neutral_swatches_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="260" data-original-width="1590" height="104" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj445fgPd5SvXKYY7nLjbo-g0WFiqx1GGqu1QNIh5DVlch7mN2D2BgjJpqxZSy-FAj8mSSkRkjWEjITB5KdTW6IpbUzN-Y0tJIHlUsjSXnvxK8-BYkf2PHx_bCJHg5e1C8PypR2UuB_BZOe/s640/neutral_swatches_1.png" width="640" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">First attempt - too little spacing on dark side</span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNmnJVtD0bLdjU1QB7eaHWb3DODcyyeV3iLsLUhBNbtEirzm5Pzqw4phxtPDYebsBGUDL7lwgTFqwfLT4qyJFIe6PIUFVhtsgNyCuWxAvOWUgyJblsO-HK0rWgW9AwF_HwgUMz9bJVrhPK/s1600/neutral_swatches_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="260" data-original-width="1590" height="104" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNmnJVtD0bLdjU1QB7eaHWb3DODcyyeV3iLsLUhBNbtEirzm5Pzqw4phxtPDYebsBGUDL7lwgTFqwfLT4qyJFIe6PIUFVhtsgNyCuWxAvOWUgyJblsO-HK0rWgW9AwF_HwgUMz9bJVrhPK/s640/neutral_swatches_2.png" width="640" /></span></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Second attempt - better but still room for improvement</span></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Photographing the Painting</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The next step is photographing the work with the </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">neutral calibration swatches alongside it, at the same angle and under the same lighting</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">. This topic is covered in great detail in other sources, so I won't go into much depth here. In short, the keys to a good photo include bright, diffuse light, the lens axis being centered and perpendicular on the work to minimize perspective distortion, the ISO and shutter speed set as low as possible, and no saturation in the area of interest. My setup - shooting in my sunroom in indirect mid-afternoon light - is hardly ideal, but it works decently, and well enough to demonstrate this concept.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXricIubTNQLBqVisR0jDhwuNXVa6H4xPl42dlqUFzBjZ6uWmJKruirtyM1EsC6LpU14MMZraMhB_E_ZCmv1NQje8u_oa-WpLpQUHNiDidqFSCgX7ZDN6flAOMC2X4_SuDKrlrA1O_9QLj/s1600/IMG_0718.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1067" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXricIubTNQLBqVisR0jDhwuNXVa6H4xPl42dlqUFzBjZ6uWmJKruirtyM1EsC6LpU14MMZraMhB_E_ZCmv1NQje8u_oa-WpLpQUHNiDidqFSCgX7ZDN6flAOMC2X4_SuDKrlrA1O_9QLj/s640/IMG_0718.JPG" width="426" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Two-tripod sunroom photography setup</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Algorithm</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The photo is then passed into the algorithm.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Collect Neutrals</i></span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The algorithm requests that the user left-click any number of neutrals in their provided image, necessarily including black and white. After each selection, the algorithm sparsely samples a 1,000-pixel circular neighborhood around the selection, takes the midtone color as the mode from each channel, and ov</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">erlays it on the image for qualitative verification. When complete, the user right-clicks to proceed.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtiyemCT_iH1pBu8GGRl-5Na5sWlM0VuRgPRbvWCSOaFnSkbxGPQ5PYekK1NS-OvjkETtJ7bi8sSd7brKp_7qRGXv6ZGtzcnDiqU5tMo9sCRHwi4b523UyTbmfGwcyAf87s87Wg4rViSTY/s1600/neutral_input_labeled.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="135" data-original-width="707" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtiyemCT_iH1pBu8GGRl-5Na5sWlM0VuRgPRbvWCSOaFnSkbxGPQ5PYekK1NS-OvjkETtJ7bi8sSd7brKp_7qRGXv6ZGtzcnDiqU5tMo9sCRHwi4b523UyTbmfGwcyAf87s87Wg4rViSTY/s1600/neutral_input_labeled.PNG" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">All neutrals identified, sampled, and labeled</span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNMs35-BlUEjs8enjjE4dhuGodEOGDtRsW4ctz7nEF5XaZ9Ffg6BKH6ZlqF7Bph0_UnnImstlIeqtwfRg7wCWSGvGj0JefpnrloRMjdf7jwrwez-y0BeS53RtG5iLPfHxJ_2Y2rRjeVzL3/s1600/neutral_input_labeled_detail.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="286" data-original-width="277" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNMs35-BlUEjs8enjjE4dhuGodEOGDtRsW4ctz7nEF5XaZ9Ffg6BKH6ZlqF7Bph0_UnnImstlIeqtwfRg7wCWSGvGj0JefpnrloRMjdf7jwrwez-y0BeS53RtG5iLPfHxJ_2Y2rRjeVzL3/s1600/neutral_input_labeled_detail.PNG" /></span></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The solid color inside the circle is the RGB mode of the pixels inside its boundary</span></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Note that the color extracted by taking the mathematical mode represents the midtone; shadows and highlights are ignored. Taking an average would mix these values together, which results in non-physical and worse results.</span></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Show Neutrals on Histogram</span></i><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The algorithm shows a per-channel histogram for the original image, </span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">and for each neutral, shows where those R, G, B values occur on their respective histogram. This is helpful to get a qualitative feel for the nature and magnitude of the white balance correction needed. Here, we can see that there is a reddish cast on the image, since red RGB values always exceed the neutral grayscale value.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsBri9Ibe4Wx3oLU2M6qHMb8qeFgyONkrRPZdq1kpuCyNmy7ocoLkc06ImFNxKrGHRlmvPjYScSnOYcJv_INzrxCkPcgy_h7Q647IZku7U65pRZjE6sgkmPoeJN7of6vXwNHAYFHHbOhYM/s1600/demo_fig_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="647" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsBri9Ibe4Wx3oLU2M6qHMb8qeFgyONkrRPZdq1kpuCyNmy7ocoLkc06ImFNxKrGHRlmvPjYScSnOYcJv_INzrxCkPcgy_h7Q647IZku7U65pRZjE6sgkmPoeJN7of6vXwNHAYFHHbOhYM/s1600/demo_fig_2.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Extract Painting Frame</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The algorithm requests that the user left-click the interior corners of the painting, so that just the painting can</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> be exported. The user can right-click to skip this step. The selection is shown as four dashed lines.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDCmxtPrU0wXXs-ixoFcBSmw4GQ5eS0kzgRq0llAuSpKTZ96M_w5cT5A28U9Ys4tkrdLwn5rYWOlkiQhFOGZIsIyI-gItq5HfYCFeeQwfLIReHw_jfkq21t_UK_-w-4HaUZ6GqXRkMhJOr/s1600/demo_fig_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="925" data-original-width="1381" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDCmxtPrU0wXXs-ixoFcBSmw4GQ5eS0kzgRq0llAuSpKTZ96M_w5cT5A28U9Ys4tkrdLwn5rYWOlkiQhFOGZIsIyI-gItq5HfYCFeeQwfLIReHw_jfkq21t_UK_-w-4HaUZ6GqXRkMhJOr/s640/demo_fig_1.png" width="640" /></span></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Full set of inputs provided by the user: six neutrals and two corners - eight clicks total</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Generate White Balance Correction Curves</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For each provided neutral, the algorithm calculates the corresponding grayscale value using the standard luminosity weighting of 21% R, 72% green, 7% B. It then calculates the required gains for those RGB values to match the grayscale value. For example, RGB [123 130 145] has a grayscale value of dot([0.21 0.72 0.07], [123 130 145]) = 130, so the gains at R=123, G=130, and B=145 are [1.06 1.00 0.90], respectively. Repeating t</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">his for each neutral, the result is a set of white balance correction curves. Outside the extreme values provided, the closest adjacent value is held as an assumed constant, so that the values are defined over the full domain of 0 to 255.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw4cDUEPDYFXnHPXsV0DuDr7q7EuohyphenhyphenVahbytQdiDqk1SgrtdJmhUIvIl7jsShw5cYb7jDJCO7ZMUZObxIR85-ah6est5_CPuSWBLzU29frOkeCZeixa07OcFTAd7rlXyrztcvYF7A_xFs/s1600/demo_fig_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="417" data-original-width="486" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw4cDUEPDYFXnHPXsV0DuDr7q7EuohyphenhyphenVahbytQdiDqk1SgrtdJmhUIvIl7jsShw5cYb7jDJCO7ZMUZObxIR85-ah6est5_CPuSWBLzU29frOkeCZeixa07OcFTAd7rlXyrztcvYF7A_xFs/s1600/demo_fig_3.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2wI3IWlHpRQ-2VGTUW161gwrlj8msDKtSZ_WN4AZbPZWGmK7k3DbHD9MCKVeyZ0AEe_VrAAJTefyv7EfwaTJ77xAVTzRxblUNBI43zFDhQY3ZDUk_EhhwOpr0RC0Q0KkGs_03BxCzpMn_/s1600/white_balance_correction_gains.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span></a></div>
<i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></i>
<i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Apply White Balance Correction Curves</span></i><br />
<i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></i>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Using linear interpolation, the algorithm multiplies the entire image by the correction curves. For example, an input G value of 120 corresponds to a gain of 1.025, so the output G value is round(120 * 1.025) = 123, and so on for all pixels and color channels. For an ~18 megapixel image, the calculation time is a few seconds on my 2011 laptop.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Verify White Balance</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The white balance-corrected image is then displayed. The user can independently verify that the selected neutrals have been balanced correctly.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaI_dBjihb6f73kmxjMnekMEXSidl16T1cCFjnsH_xl6gN2G4VkrY16g9j5Z8B8GTU0nJRLt4g4-8qaVSUPie0ylvj-P3X8BGHJOk3jPNhmhSxKCqQ5YS8TOPjYRZjbVyDHq2N_dKWD2DI/s1600/demo_fig_4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="942" data-original-width="1381" height="436" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaI_dBjihb6f73kmxjMnekMEXSidl16T1cCFjnsH_xl6gN2G4VkrY16g9j5Z8B8GTU0nJRLt4g4-8qaVSUPie0ylvj-P3X8BGHJOk3jPNhmhSxKCqQ5YS8TOPjYRZjbVyDHq2N_dKWD2DI/s640/demo_fig_4.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Image after white balance correction</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For example, neutrality can be quickly verified in GIMP, by checking that R=G=B within a reasonable tolerance of about </span><span style="background-color: white;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">± 1%.</span></span><br />
<span style="background-color: white;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpv6MZpHI9mEEq9XMxdX497zZVtBAfSNgl82oLZFZ1Yh5Ho5JX68RHAcvwljDP3VM_9RY1HZoKBZ8yPOZDdHTC8CVCagnf_FJ6Mhm328t2HSoLqoeTgihCTJo-Vh4CvwIU6rLUSrLaM7sL/s1600/neutral_verification_2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="281" data-original-width="597" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpv6MZpHI9mEEq9XMxdX497zZVtBAfSNgl82oLZFZ1Yh5Ho5JX68RHAcvwljDP3VM_9RY1HZoKBZ8yPOZDdHTC8CVCagnf_FJ6Mhm328t2HSoLqoeTgihCTJo-Vh4CvwIU6rLUSrLaM7sL/s1600/neutral_verification_2.PNG" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">GIMP Color Picker showing nearly zero neutrality error between R, G, and B</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The neighborhoods of the input neutral indices are then re-sampled, and overlaid on the updated image histogram. The line segments connecting the R, G, and B values are now nearly vertical and coincident with the corresponding target grayscale values, indicating correct balance. Note that due to discretization and rounding, zeros begin appearing in the histogram; for visual clarity, I set these zeros to </span><span style="font-family: "courier new" , "courier" , monospace;">NaN</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> so that they appear as gaps rather than as spikes or divots.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAv0u1aZMukbzd9DkCofa031yP2yr-a-Fs8JVfDSsRzb4yYkbDBiZucqUu_w0NfyRrM0W_BGJXDxwy6nVzbHsjHul6p8MOyCwT6mjOsGNfKUDxQH3VpLPN4-_dGLaEYQ2XNHYukkeVw_c8/s1600/demo_fig_5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="645" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAv0u1aZMukbzd9DkCofa031yP2yr-a-Fs8JVfDSsRzb4yYkbDBiZucqUu_w0NfyRrM0W_BGJXDxwy6nVzbHsjHul6p8MOyCwT6mjOsGNfKUDxQH3VpLPN4-_dGLaEYQ2XNHYukkeVw_c8/s1600/demo_fig_5.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Crop and Adjust Levels</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Last, the image is cropped to the input painting frame, and the levels are adjusted. Here's it's necessary to make a judgement call on how "black" your black paint should appear to be, and so on for the white. I use 2.5% and 97.5% as my RGB value limits, but tastes will vary.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The darkest and lightest neutrals are taken as representing black and white, and their 1,000-pixel neighborhoods are again sampled, but this time for the minimum and maximum in each channel, rather than the mode. For this to work correctly, the input image must not saturate the 0% or 100% value limits.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The darkest color within the black neutral is mapped to 2.5%, and the lightest shade within the white neutral is mapped to 97.5%. All intermediate values between are mapped linearly. I use MATLAB's </span><span style="font-family: "courier new" , "courier" , monospace;">imadjust</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> function for convenience, but it could also be done in HSV or LAB color space using the V or L channels, respectively.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The histogram is shown one last time for the cropped and level-adjusted image.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijH4jQxbgNU5GI3yYCkQRIP_aQabNDBWX_O8pdKumqxyJtppyDgYC4BcdVXyaFIN9Kl3zMLmURw7Xb7t2deO4B3psn3q-s4wm5r6pKhJCRxXJYQ69T8bIByU64kXRdcLOXIQayn9DBGFDk/s1600/demo_fig_6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="645" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijH4jQxbgNU5GI3yYCkQRIP_aQabNDBWX_O8pdKumqxyJtppyDgYC4BcdVXyaFIN9Kl3zMLmURw7Xb7t2deO4B3psn3q-s4wm5r6pKhJCRxXJYQ69T8bIByU64kXRdcLOXIQayn9DBGFDk/s1600/demo_fig_6.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Note that due to the levels adjustment, the gaps open significantly. This is not desirable and leads to graininess, but in my view is a much better problem than inaccurate colors or levels. If the correction magnitude was less, these gaps would also be smaller. This is an area of future work for me. I expect that incorporating a remote shutter trigger, reducing the ISO and shutter speed, and shooting in RAW will improve the initial image quality and reduce the correction magnitude, improving the overall result.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Demo Gallery</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Below are some input/output examples shot under a variety of lighting conditions. These paintings are all unvarnished.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy4D7TKijuw2iJBhyB-HD1cCJsFi7I6dZuHLRNaFl-azj7FttOlPHQNtqEEnv4LYl1ULnP6yFsbGznQPIbuu-SzwEDxgsHWj9H1RNLJoXi9Gj44Rz20SawjQhbqoZiWMvzXKmT_Lf43VOi/s1600/IMG_0724.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy4D7TKijuw2iJBhyB-HD1cCJsFi7I6dZuHLRNaFl-azj7FttOlPHQNtqEEnv4LYl1ULnP6yFsbGznQPIbuu-SzwEDxgsHWj9H1RNLJoXi9Gj44Rz20SawjQhbqoZiWMvzXKmT_Lf43VOi/s320/IMG_0724.JPG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirNYExRL67G1TClNBBEZVvGKe8FEpzYqH5kjU5Xq72Ko0Y6wFoNb5d-HnB_M5ZapWi7fA-rIqrwdL8mWTfppWrTHaVy7Tvcp0f8dyZXGtoYsEMugF7g3epJqI8lIMUYrS_uh_wBjSm4bwE/s1600/IMG_0724_out.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirNYExRL67G1TClNBBEZVvGKe8FEpzYqH5kjU5Xq72Ko0Y6wFoNb5d-HnB_M5ZapWi7fA-rIqrwdL8mWTfppWrTHaVy7Tvcp0f8dyZXGtoYsEMugF7g3epJqI8lIMUYrS_uh_wBjSm4bwE/s640/IMG_0724_out.jpg" width="476" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOK9miaFy2JQBspetTER9rSYbs6A5zjBKUA_q4O8cZ-NVJF0EOSypCvwEsEhJiZrGH3VC_XjsSFLETYkBpnqaV77v08n6_T28pgRiarsCbCZBLG40kKkfMEsZzih8e1CkgzYEABpHpcIoY/s1600/IMG_0737.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOK9miaFy2JQBspetTER9rSYbs6A5zjBKUA_q4O8cZ-NVJF0EOSypCvwEsEhJiZrGH3VC_XjsSFLETYkBpnqaV77v08n6_T28pgRiarsCbCZBLG40kKkfMEsZzih8e1CkgzYEABpHpcIoY/s320/IMG_0737.JPG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigZTGhtW6mLvIJJ4KDqNx8jxSIoEFTAU_v8e8JqmvRKqsOHr5TZNei5JncyM1hmRBy-ruTcAR2kl4DZDPzMxTAuXWS2s9orqi4wHD-o2Wu3KbSpXlJqm_Lf7C6lXN_W6JxmMyYoIxha55R/s1600/IMG_0737_out.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigZTGhtW6mLvIJJ4KDqNx8jxSIoEFTAU_v8e8JqmvRKqsOHr5TZNei5JncyM1hmRBy-ruTcAR2kl4DZDPzMxTAuXWS2s9orqi4wHD-o2Wu3KbSpXlJqm_Lf7C6lXN_W6JxmMyYoIxha55R/s640/IMG_0737_out.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNC1U94UI3x516NP_qw4K4UXZSqRmU0w7c7jORI5Tp8Z2l3tqUzUaq62P9OXTeT85_aDmMVT9Ot3uq_pFGOXAYnwj41WCrJ_YRhEUugfFk0XfGnP5K326nOy9dj7El3So_-w896fB_bDxK/s1600/IMG_0593.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNC1U94UI3x516NP_qw4K4UXZSqRmU0w7c7jORI5Tp8Z2l3tqUzUaq62P9OXTeT85_aDmMVT9Ot3uq_pFGOXAYnwj41WCrJ_YRhEUugfFk0XfGnP5K326nOy9dj7El3So_-w896fB_bDxK/s320/IMG_0593.JPG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe7YmvoAd2s_YB0EAdulLI6QyfL-spwnrDCZL2mxO_l40hOSKfAU5bG9vt2VyGOjX8oQpYYVctGV3b7deM9Mg0YKIrsGh60B5B2ofvPOaDR3hvsA9Ucji_y0xz8iHwV6St3igsNthniaNe/s1600/IMG_0593_out.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="476" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe7YmvoAd2s_YB0EAdulLI6QyfL-spwnrDCZL2mxO_l40hOSKfAU5bG9vt2VyGOjX8oQpYYVctGV3b7deM9Mg0YKIrsGh60B5B2ofvPOaDR3hvsA9Ucji_y0xz8iHwV6St3igsNthniaNe/s640/IMG_0593_out.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5m2bijF1k_Jwg5F0SIQ2xv8ALdR-bzbZ8tg2kPAAr1SB0dsCavj2sb8Z0djJTQkIuuzbb1difThsAuWOBxpwQcqdyzFPwzCU-_aJrZIVpLdqD7NOUwm30AsAcwfXCqz_hlLyiwIwWsdh9/s1600/IMG_0615.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5m2bijF1k_Jwg5F0SIQ2xv8ALdR-bzbZ8tg2kPAAr1SB0dsCavj2sb8Z0djJTQkIuuzbb1difThsAuWOBxpwQcqdyzFPwzCU-_aJrZIVpLdqD7NOUwm30AsAcwfXCqz_hlLyiwIwWsdh9/s320/IMG_0615.JPG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOqIR5cUf_3fa8Sz0Mnd1-tgcVO1s7giDKmkVCl1YsX8NKBfIFJ1EJQNozdFbzjAHY3NxmdVLG05qbtyBULNfm64KqQUuIIm5gyra-hO8lxd3-U-OspK6HMNnvFgeHQn5EDEyb16zlT4h8/s1600/IMG_0615_out.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOqIR5cUf_3fa8Sz0Mnd1-tgcVO1s7giDKmkVCl1YsX8NKBfIFJ1EJQNozdFbzjAHY3NxmdVLG05qbtyBULNfm64KqQUuIIm5gyra-hO8lxd3-U-OspK6HMNnvFgeHQn5EDEyb16zlT4h8/s640/IMG_0615_out.jpg" width="480" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibVFe17C7A1NicBcDacCq2_vdT6tLb5Xx5eogaTFqVy4nh2pM0dpL2OH4wVmZc-0GoJc_2cux041CwMJ6DS9SbR_LceoW4uS0TZ0bz9z-TySe9YltoPHTl5sYfd3V_p8Z_DhxAdsn78Prj/s1600/IMG_0605.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibVFe17C7A1NicBcDacCq2_vdT6tLb5Xx5eogaTFqVy4nh2pM0dpL2OH4wVmZc-0GoJc_2cux041CwMJ6DS9SbR_LceoW4uS0TZ0bz9z-TySe9YltoPHTl5sYfd3V_p8Z_DhxAdsn78Prj/s320/IMG_0605.JPG" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdvlzBW6E-cIEQ5NspwiWrioFgKOuTr6TM37Yqtk39nSOz4V_rjCpBe2rKF7zUtInWLdkk0G3bEltQmvBE0773H0dV1nYsyM-J01_gz6vTpe5gbnZjMt4vwhQ2A66RCj_D8tyU6VhO5Axo/s1600/IMG_0605_out.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="478" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdvlzBW6E-cIEQ5NspwiWrioFgKOuTr6TM37Yqtk39nSOz4V_rjCpBe2rKF7zUtInWLdkk0G3bEltQmvBE0773H0dV1nYsyM-J01_gz6vTpe5gbnZjMt4vwhQ2A66RCj_D8tyU6VhO5Axo/s640/IMG_0605_out.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-5757651991805058862020-03-08T22:00:00.001-07:002020-03-21T15:31:57.658-07:00Prioritizing Color Over Value<i style="font-family: "helvetica neue", arial, helvetica, sans-serif;">A discussion on </i><i style="font-family: "helvetica neue", arial, helvetica, sans-serif;">value-priority vs. c</i><i style="font-family: "helvetica neue", arial, helvetica, sans-serif;">olor-priority in color theory and painting, and a quantitative method for shifting between them in digital photos.</i><br />
<i style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></i>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiP6r3DcPrTkENQM0gF1_NUlmt_a5-PCDJ7aoiwMNRezAVPeSES81xSTXBjbF_OWUiuklnW-oHShuMWVyqHwXToWwvPwJcgLoMjy0qie_luMK3eRYMH_PfUnELdxCIpKhLJJnTC-z7z7Yr/s1600/IMG_20190727_185613_comp_L_scl_0.7_L_off_18.6332_H_scl_1_H_off_0_S_scl_3.4171_S_off_0_labeled.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiP6r3DcPrTkENQM0gF1_NUlmt_a5-PCDJ7aoiwMNRezAVPeSES81xSTXBjbF_OWUiuklnW-oHShuMWVyqHwXToWwvPwJcgLoMjy0qie_luMK3eRYMH_PfUnELdxCIpKhLJJnTC-z7z7Yr/s640/IMG_20190727_185613_comp_L_scl_0.7_L_off_18.6332_H_scl_1_H_off_0_S_scl_3.4171_S_off_0_labeled.jpg" width="640" /></a></div>
<br />
<b style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">Motivation</b><br />
<b style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;"><br /></b>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As a painter, I work from both life and from photos. Both approaches have key advantages and drawbacks. Painting from life is the best method for accurately capturing a scene's colors, but is somewhat limited to static scenes. Painting from photos can capture dynamic scenes, but has limited color accuracy. As an engineer, I'm interested in unifying the approaches in a way that preserves the best aspects of each.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Let me start by defining my terminology:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Painting photo:</b> a photo of a painting that accurately matches the color of the physical painting</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Camera photo:</b> a photo straight from a camera without modification</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Reference photo:</b> a camera photo, augmented digitally for better use as a painting reference</span></li>
</ul>
<br />
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;"></b>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Because all these photo types reside within the same digital color gamut, as I'll show, nothing prevents a <u>reference photo</u> from having the same desirable characteristics as a <u>painting photo</u>. However, <u>camera photos</u> make for poor <u>references photos</u> due to their inaccurate and uninspiring portrayal of color. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Therefore, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I'm interested in how to turn </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>camera photos</u></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> into </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>reference photos</u></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> using image processing. You can think of this approach as an alternate path that parallels the traditional/academic process, both leading to the same end result.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghqVhO6Kx_VDE9rRs90tWOM_S1r4KgIDBGaDasfHpeUuJT-3QaslAwlUKgJLOgSOywbQR3O4YtjEwaQyUggs9SalFfZbjGfV5foODtc7jZac3NZEDZqcdEQ4Bz9FeqPIFgmiJ38MgFjkDG/s1600/flowchart.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="372" data-original-width="624" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghqVhO6Kx_VDE9rRs90tWOM_S1r4KgIDBGaDasfHpeUuJT-3QaslAwlUKgJLOgSOywbQR3O4YtjEwaQyUggs9SalFfZbjGfV5foODtc7jZac3NZEDZqcdEQ4Bz9FeqPIFgmiJ38MgFjkDG/s1600/flowchart.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I've previously written about two image processing techniques toward this goal - </span><a href="http://www.kindofdoon.com/2019/11/histogram-diffusion-image-filter.html" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Histogram Diffusion</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> for color differentiability, and </span><a href="http://www.kindofdoon.com/2020/01/3d-focal-point-median-blur.html" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">3D Focal Point Blur</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> for focal realism. In this article, I'll discuss another approach, inspired by artistic color theory.</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Background</b><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In his 2009 book </span><i style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;"><a href="https://www.amazon.com/Landscape-Painting-Essential-Concepts-Techniques/dp/0823032205/">Landscape Painting</a></i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">, <a href="https://mitchalbala.com/">Mitchell Albala</a> describes the concept of "color identity":</span><br />
<blockquote class="tr_bq">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"Extremes of value profoundly affect a color's ability to be read as color...A color's chromatic identity is most visible when its value is neither too dark nor too light b</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ut is in the middle-value range."</span></blockquote>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Albala illustrates this concept of "color identity" with a chart, reproduced below, showing various colors transitioning from very light (near-white) values to very dark (near-black) values. C</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">olors that are very light or very dark have nearly no perceptible "color". In other words, they rea</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">d almost as pure values, or grayscale. Another way to think of this is how "nameable" a color </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">is. This broad definition is what Albala means by "color identity".</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCqxU2-HIsb5XnwtedU9zTuRHpPry9Dqce9AiTLr1u_u08sOaQQ47cH_zkYKHKunaTQjqbCeQ90wZTOXVl8LxVMPyLmCriKfP_G74_4fYS1u5P4OaIWgaAZgAJd5DOOfYoX04VWzXTii9n/s1600/albala_color_chart_crop_levels.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="815" data-original-width="1037" height="502" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCqxU2-HIsb5XnwtedU9zTuRHpPry9Dqce9AiTLr1u_u08sOaQQ47cH_zkYKHKunaTQjqbCeQ90wZTOXVl8LxVMPyLmCriKfP_G74_4fYS1u5P4OaIWgaAZgAJd5DOOfYoX04VWzXTii9n/s640/albala_color_chart_crop_levels.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">To clarify the terminology:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Hue:</b> color, independent of lightness and intensity</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Saturation:</b> how vibrant, intense, or colorful a color is</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Value:</b> how light or dark a color is</span></li>
</ul>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Albala illustrates this concept by comparing two schools of landscape painting:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1: 17th century Dutch "Golden Age" landscapes are characterized by "value-priority", maximizing value contrast (sometimes called <i>chiaroscuro</i>) at the cost of low color identity.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtLepMb0Xo2IoAred7BJuTgFs0jf2_Ev7my5azD2LiSU_JtY2uImTZNyejs3Wv0VL43x0IYjVZB7qneoaIge_0wptjDz8N6ZeuLoJv-6t1QLpnU_4YP3DlNdLQclW7aRlMcrRUfA1I44vZ/s1600/hobbema_entrance_to_a_village_1665.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1095" data-original-width="1600" height="434" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtLepMb0Xo2IoAred7BJuTgFs0jf2_Ev7my5azD2LiSU_JtY2uImTZNyejs3Wv0VL43x0IYjVZB7qneoaIge_0wptjDz8N6ZeuLoJv-6t1QLpnU_4YP3DlNdLQclW7aRlMcrRUfA1I44vZ/s640/hobbema_entrance_to_a_village_1665.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Meindert Hobbema, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://www.metmuseum.org/art/collection/search/436652">Entrance to a Village</a>, c. 1665</span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGOrWzi0PbPNh3oySYR2F28SvS27pCRoPvmOybNwaHSQ5kVQ_yLjFYKC56QNiwFzWGkGwn0nprgwrKotuaGvxJ868XJTjjwfmqL5uFHRfXBNxzahKKS2PAjy23QRn5ryQ9joUqNPMo9X24/s1600/hobbema_entrance_histogram.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="134" data-original-width="369" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGOrWzi0PbPNh3oySYR2F28SvS27pCRoPvmOybNwaHSQ5kVQ_yLjFYKC56QNiwFzWGkGwn0nprgwrKotuaGvxJ868XJTjjwfmqL5uFHRfXBNxzahKKS2PAjy23QRn5ryQ9joUqNPMo9X24/s1600/hobbema_entrance_histogram.JPG" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I've copied the Levels histogram from <a href="https://www.gimp.org/">GIMP</a> (an open source Photoshop equivalent), a visualization for how the photo utilizes the value gamut. This painting </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">shows a strong bimodal (two-peak) distribution which creates a value-priority effect.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2: Impressionist landscapes are characterized by "color-priority", maximizing color identity at the cost of low value contrast.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjps9_RIHVTWYFdLLjAVi74FH_IsQMSUSnZAlVOWyUBls6N6K8lHYm61bqorrs1XdW1fpDN0-ljDqJaFdkZIIPq2hTFS9WMCsUbE8i_-Sr3OFYCNexycW5EM3blv603VrasirtaJUfKB6mI/s1600/monet_antibes_seen_from_las_salis_1888.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1270" data-original-width="1600" height="508" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjps9_RIHVTWYFdLLjAVi74FH_IsQMSUSnZAlVOWyUBls6N6K8lHYm61bqorrs1XdW1fpDN0-ljDqJaFdkZIIPq2hTFS9WMCsUbE8i_-Sr3OFYCNexycW5EM3blv603VrasirtaJUfKB6mI/s640/monet_antibes_seen_from_las_salis_1888.jpg" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Claude Monet, <i><a href="http://emuseum.toledomuseum.org/objects/54775">Antibes Seen from Las Salis</a></i>, 1888</span></div>
<div style="text-align: center;">
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWpLgCSPQUKndvxR056cCXbHRDZoXlZhdmzzsqS7J0TkdeBsF34YmOAOrb_2VY6OjQcEX9jDt50jHsH5qF6_q1zJS93SciqgPvX_YOW9quz8ngNPerZn_ijN9P0SrF0-OxtUpdHWQCDuRY/s1600/monet_antibes_histogram.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="133" data-original-width="367" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWpLgCSPQUKndvxR056cCXbHRDZoXlZhdmzzsqS7J0TkdeBsF34YmOAOrb_2VY6OjQcEX9jDt50jHsH5qF6_q1zJS93SciqgPvX_YOW9quz8ngNPerZn_ijN9P0SrF0-OxtUpdHWQCDuRY/s1600/monet_antibes_histogram.PNG" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The Levels histogram shows a clear difference: just one peak, so colors are much closer in terms of value, differentiated primarily by color, creating a color-priority effect.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
</div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">To simplify, you can think of these two schools as favoring differing regions of the color chart to get their ideas across:</span></div>
<div style="text-align: center;">
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUrjxKqNPfsRe1J6L9qAlWlrYiXBSPzZiE5rYjWcpRSyIqgV_q2SIZvG95UgGU-KOWxmDAwFFkZtsOpCqKcLhkzKm9i4TGsmeyvVGr4Xacv33qVtShJClqZgANB75HnYd2N-C3N7eQQLKI/s1600/color_diagram_by_school.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="542" data-original-width="603" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgUrjxKqNPfsRe1J6L9qAlWlrYiXBSPzZiE5rYjWcpRSyIqgV_q2SIZvG95UgGU-KOWxmDAwFFkZtsOpCqKcLhkzKm9i4TGsmeyvVGr4Xacv33qVtShJClqZgANB75HnYd2N-C3N7eQQLKI/s1600/color_diagram_by_school.PNG" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Which is more realistic? More aesthetically pleasing? More correct? These are fundamentally subjective questions, best left to personal taste. As Albala notes, "[both] successfully depict natural light", "[although] the Impressionist approach to color is perhaps more in tune with contemporary color sensibilities".<br /><br />My take is that neither image is particularly realistic, but I personally find the Impressio</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">nist approach much more pai</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">nterly and compelling, and closer to "correct".</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Albala has since expanded on this topic at his blog with a couple excellent articles:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://mitchalbala.com/how-value-is-used-to-heighten-the-effects-of-color-in-landscape-painting/">How Value is Used to Heighten the Effects of Color in Landscape Painting</a></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://mitchalbala.com/the-affect-of-value-on-color-identity-in-impressionist-painting/">The Affect of Value on Color Identity in Impressionist Painting</a></span></li>
</ul>
</div>
<div>
<b style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;"><br /></b></div>
<div>
<b style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">Quantifying Color Identity</b></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br />Digital color provides a quantitative framework to examine and enact Albala's view of color identity. But it first requires some careful consideration of color space nuance.</span><br /><i style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i style="font-family: "helvetica neue", arial, helvetica, sans-serif;">RGB Color Space</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Let's start at square one with <a href="https://en.wikipedia.org/wiki/SRGB">RGB color</a>, the standard for storing and displaying digital images. RGB color has three channels corresponding to red, green, and blue light, and within a channel, a pixel can take any of 256 values, 0-255. Therefore, there are 256^3 or ~16,700,000 colors available.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RGB's core purpose is telling monitors how to display color, and it's very effective for this. However, its utility in addressing color identity is very limited, because the intuitive properties of hue, saturation, value - the way we think about color - are all interdependent with respect to the axes of R, G, B.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>HSV Color Space</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Invented in the 1970s, the <a href="https://en.wikipedia.org/wiki/HSL_and_HSV">HSV</a> (hue, saturation, value) color space was designed to provide more intuitive framework for working with digital color. Whereas RGB is a cube, HSV is a cylinder; hue describes the angle, saturation the radius, and value the height. It's computationally easy to transform between RGB and HSV, which was initially a significant advantage, but largely moot in the current era. HSV's key shortcoming is that saturation and value are not actually independent - just close to it. This can be observed from a constant-hue chart, which corresponds to half of a cross section of the HSV cylinder. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here is H=130°, arbitrarily:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5hop6TEfYwDnkxMv9CVtBpqq40McUZxaUa93YoZOk6-HPfJPohKx29WfnX8QN-QosA2d0Y_maT09EboO56bgxVPYjUhd8xYU6kiYWXna4-NdEAWj87FSxo5KopOZL1mSqruFtZXM8at9J/s1600/HSV_chart.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="342" data-original-width="478" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5hop6TEfYwDnkxMv9CVtBpqq40McUZxaUa93YoZOk6-HPfJPohKx29WfnX8QN-QosA2d0Y_maT09EboO56bgxVPYjUhd8xYU6kiYWXna4-NdEAWj87FSxo5KopOZL1mSqruFtZXM8at9J/s1600/HSV_chart.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Columns theoretically have constant saturation, and rows theoretically have constant value. To test the latter, we can convert the chart to grayscale, either by explicitly switching the image mode or desaturating it completely. Both provide the same result:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi4WBMzCPd-qmo3bOPb4Ig-HsYBjRyaE6ohd-XR2h1dQw66MzAIODYG4MxRlx9N-IZdLOG7BQvTrGQFt6iwnkPynA44SSm_EXKiLvVhTNmCTzREE_CjLoJ6xF81a0_yI-2tzIcOioU0qv5/s1600/HSV_chart_grayscale_mode.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="342" data-original-width="478" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgi4WBMzCPd-qmo3bOPb4Ig-HsYBjRyaE6ohd-XR2h1dQw66MzAIODYG4MxRlx9N-IZdLOG7BQvTrGQFt6iwnkPynA44SSm_EXKiLvVhTNmCTzREE_CjLoJ6xF81a0_yI-2tzIcOioU0qv5/s1600/HSV_chart_grayscale_mode.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Examine the grayscale chart and you'll see upon close inspection a couple key shortcomings:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As you move horizontally within a row, value decreases (darkens) slightly. The actual disparity between min and max across rows is about 5%.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As you move vertically within a column, the rate at which value changes is not uniform. Note for example the steep gradient from 10-15% value.</span></li>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">While very subtle in this example, these issues significantly impede HSV's ability to address color identity.</span></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Lab Color Space</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The <a href="https://en.wikipedia.org/wiki/CIELAB_color_space">Lab color space</a>, invented in 1976, solves these problems with full independence of hue, saturation, and value, as well as perceptual uniformity. Like RGB, Lab is a 3D orthogonal color space:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">L corresponds to a color's value, or lightness/darkness</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">a corresponds to a theoretical green-magenta/red axis</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">b corresponds to a theoretical blue-yellow axis</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Whereas RGB is discretized 0-255, Lab is continuous and unlimited. Therefore, Lab can theoretically describe "imaginary" colors that cannot be displayed in RGB, or describe infinite colors between RGB discretizations. It is perceptually uniform, unlike RGB and HSV, meaning that Euclidean (straight-line) distance corresponds linearly to perceived color distance/difference in the human eye, which is a significantly non-linear sensor.</span></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Every color in RGB color space can be converted to Lab, and vice versa. Because the equations that perform this conversion are non-linear, the neat RGB cube becomes non-trivially deformed in Lab color space:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzvhiYdI3NduVOnJ6CPtwgMFIeDRUSIz_cPy7_AZUlPc-zQdIiW2xVp96LflKHkAISPVoegCdlIDlzNgJUVxYhhu2h58nT5vqXKZIK7wiNREChA3lNiXJ3ab9ENXxWAorevLmIhya9sD15/s1600/RGB_color_gamut_in_Lab_color_space_spin.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="384" data-original-width="700" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzvhiYdI3NduVOnJ6CPtwgMFIeDRUSIz_cPy7_AZUlPc-zQdIiW2xVp96LflKHkAISPVoegCdlIDlzNgJUVxYhhu2h58nT5vqXKZIK7wiNREChA3lNiXJ3ab9ENXxWAorevLmIhya9sD15/s1600/RGB_color_gamut_in_Lab_color_space_spin.GIF" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In this visualization, a uniform, dense point cloud is created inside the RGB cube, then converted to Lab, and its boundary is approximated using a concave hull algorithm. The mesh for each boundary is overlaid on the volume. The non-linearity of human vision causes the initially-uniform point cloud to be significantly non-uniform in Lab color space, which is reflected in its boundary mesh.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">These visualizations are very colorful - in fact, they could not be any more colorful, because their outer surfaces contain their most highly saturated colors. However, keep in mind that this visualization shows only the outer surfaces, which contain a small fraction of the complete color gamut. To view these less-colorful colors, you have to look inside these volumes. This can be achieved with a cross-section:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqm9IaSaCLmRwNksuRct6BfSsfrGmDp44fR3DjGlydVoCAXQ6b9bUs03xXeEJk8HycU0l_CnQLMlCOHlTMUFy9MDkF5Bvg3bXFHiTttqeA2jH368cSiEFcicWT5Yl2AER-atLfOvE_QtQU/s1600/RGB_color_gamut_in_Lab_color_space_section.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="384" data-original-width="700" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqm9IaSaCLmRwNksuRct6BfSsfrGmDp44fR3DjGlydVoCAXQ6b9bUs03xXeEJk8HycU0l_CnQLMlCOHlTMUFy9MDkF5Bvg3bXFHiTttqeA2jH368cSiEFcicWT5Yl2AER-atLfOvE_QtQU/s1600/RGB_color_gamut_in_Lab_color_space_section.GIF" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here, I section the RGB cube along its R axis arbitrarily, and the Lab volume along its L axis. On the Lab gamut, I overlay the color space's "neutral axis", which occurs where a=0 and b=0. In other words, all colors on this line have zero hue because they are pure shades of gray. Note that the neutral axis intersects pure black and pure white. H</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ue and saturation are defined simply as:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Hue is a color's angle from the neutral axis, </span><span style="font-family: "courier new" , "courier" , monospace;">atan2d(b,a)</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Saturation is a color's distance from the neutral axis, </span><span style="font-family: "courier new" , "courier" , monospace;">sqrt(a^2+b^2)</span></li>
</ul>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With this visualization, you can show that Lab has true value independence by converting any frame to grayscale:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqjJoOncqJEGH-cGKvFPO9uh24mq7MHUPLzM4jSgCT0KnODoDl6OqbGtCqn-Hi-u0-oR_weJPwbj5IKltjjyUIlPJ8yQUErtIly66BwS-q8MvT9tq6g_7l_rVmBQSLc0bgTCXXX5K8a3Xz/s1600/color_space_section_frame_grayscale.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="384" data-original-width="694" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqjJoOncqJEGH-cGKvFPO9uh24mq7MHUPLzM4jSgCT0KnODoDl6OqbGtCqn-Hi-u0-oR_weJPwbj5IKltjjyUIlPJ8yQUErtIly66BwS-q8MvT9tq6g_7l_rVmBQSLc0bgTCXXX5K8a3Xz/s1600/color_space_section_frame_grayscale.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Note that in Lab, there is only a single, constant shade of gray within the cross-section boundary - not so with RGB which has no such constraint.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This framework provides a basis for corroborating Albala's notion of color identity. Since the colors with the strongest color identity occur on the outer surface of the gamut volume, we can deduce that saturation is a proxy for color identity. Further, we can take the section area as a proxy for <i>color identity potential</i> at that value:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg9hf4wr3iBe2XHyWH4NAYeRd7YjBi6cfoTg7-C44T6KH1oretbEoAm0EoCgmQ-UuDNnplR89wTR7S8vZo69XDzjbQzHXfq2OdIp6MDLY3L7NrGMDHvCu39m4p56AIQje2r4H1LjBDZlY_/s1600/color_identity_as_function_of_value.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="383" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg9hf4wr3iBe2XHyWH4NAYeRd7YjBi6cfoTg7-C44T6KH1oretbEoAm0EoCgmQ-UuDNnplR89wTR7S8vZo69XDzjbQzHXfq2OdIp6MDLY3L7NrGMDHvCu39m4p56AIQje2r4H1LjBDZlY_/s1600/color_identity_as_function_of_value.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This is a general result for all hues; as you can see from the cross-section, different hues achieve maximum color identity at different L values. This can be compared with the color swatch chart from earlier:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbknjz-6VhWR39G03ZX2JRwuaSos3wh5s_fWKKK4RhS3a3yYS48td2xX8GTPWbyAtAJre1NAaOLjhJCR4OipGRFhgbudyLYUkIuwZ59bUH8gMsT4MnHOIj8yWj72Cd8Y1aTxPjKaG5zwUT/s1600/albala_chart_overlay_flipped.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="383" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbknjz-6VhWR39G03ZX2JRwuaSos3wh5s_fWKKK4RhS3a3yYS48td2xX8GTPWbyAtAJre1NAaOLjhJCR4OipGRFhgbudyLYUkIuwZ59bUH8gMsT4MnHOIj8yWj72Cd8Y1aTxPjKaG5zwUT/s1600/albala_chart_overlay_flipped.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here I've superimposed the earlier color swatch chart with the color identity potential plot. The swatches don't necessarily occur at the correct L values, so the result is merely suggestive, but the qualitative fit between the two is clearly strong.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Why Photos Tend Toward Value-Priority and Drab Colors</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Modern digital cameras in "automatic" mode are so adept in adjusting their settings under the hood that it's easy to think of their images as objective truth. However, much of this process is actually based on heuristics that are designed to provide decent results over a wide range of conditions. This is ideal for the typical consumer who simply wants to point and shoot with minimal fuss.</span><br />
<div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">However, for those who paint from photos, the automatic settings often provide seriously sub-optimal results - namely, they tend to minimize color identity. This is both deliberate and reasonable: creating a value-prioritized image is algorithmically easy and will usually look decent, whereas creating a color-prioritized image is not straightforward and will be prone to pitfalls. Allow me to illustrate:</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Suppose you are the camera's setting adjustment algorithm. You look out at the scene and see this distribution of light:</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVOtq9-q6emyADaNNrQ6fnxXHfwQY5GSV-Mp27znmIVijukn2LhNub5oXLkvC8a8F5ih1rtsggb6vRa3qu6w9v7Rhor-BudEHGMZ-lHhlZkrlzR6uZEWsnFnlA6c_DYQZ1iOCl-6P5HhO2/s1600/scaling_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="394" data-original-width="518" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVOtq9-q6emyADaNNrQ6fnxXHfwQY5GSV-Mp27znmIVijukn2LhNub5oXLkvC8a8F5ih1rtsggb6vRa3qu6w9v7Rhor-BudEHGMZ-lHhlZkrlzR6uZEWsnFnlA6c_DYQZ1iOCl-6P5HhO2/s1600/scaling_1.png" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Note that a scale and units are not provided; a camera is not measurement tool. You simply see that there are some darker regions, some midtones, and some lighter regions. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">So that the image can be saved and displayed, your job is to fit this distribution into a fixed bounding box:</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnRNUxTpihZYsWIk3q1u4mMcP0d0mUvd2SVQWXRCxffPCk6ewg6Ru5M8Paf95cTytkQMiyc0MllNillez9WjirbRUy0ZUx4VzT5XgydgKY2BX96FKJK8M6CZ_34h8ix0aprJJFyPm9v7Bg/s1600/scaling_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="432" data-original-width="521" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnRNUxTpihZYsWIk3q1u4mMcP0d0mUvd2SVQWXRCxffPCk6ewg6Ru5M8Paf95cTytkQMiyc0MllNillez9WjirbRUy0ZUx4VzT5XgydgKY2BX96FKJK8M6CZ_34h8ix0aprJJFyPm9v7Bg/s1600/scaling_2.png" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">How do you do this? Approaches vary by manufacturer, but one certainty is that you don't want to saturate any part of the spectrum. This would mean "pushing" any part of the distribution outside of the bounding box, resulting in pure white or pure black. For example:</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq8H6acSnB9KBfN19rKNDcDtmInNezYAcGbMc7NfoqDntKA1pgZbMDwIJoWsP-ywhQ_vOqNeoXEEl96cHfAteHxs4ELUFMlxV_EtEp3M5fvo2a84hLldS6nBvk353FeUQqDTD63wILIdpE/s1600/scaling_4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="432" data-original-width="521" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiq8H6acSnB9KBfN19rKNDcDtmInNezYAcGbMc7NfoqDntKA1pgZbMDwIJoWsP-ywhQ_vOqNeoXEEl96cHfAteHxs4ELUFMlxV_EtEp3M5fvo2a84hLldS6nBvk353FeUQqDTD63wILIdpE/s1600/scaling_4.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">No good - the lower end is saturated.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9L3T5uj0rznASlG85DTT17srmhEhUC8psMca5ARL9HM2jEfB78bSW1t_i9BfSyWLSSEsbvS-JQttoXZebznptjrhFErGlQiXbTZethxJbV3zT2kRt5zibxmfjpXa9zHwEN9L47XU29GXW/s1600/scaling_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="432" data-original-width="521" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg9L3T5uj0rznASlG85DTT17srmhEhUC8psMca5ARL9HM2jEfB78bSW1t_i9BfSyWLSSEsbvS-JQttoXZebznptjrhFErGlQiXbTZethxJbV3zT2kRt5zibxmfjpXa9zHwEN9L47XU29GXW/s1600/scaling_3.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">No good - the upper end is saturated.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoPkbWGyjetY87aP1u1McgwhXb18P-grIweH6t2SxhMrA2ngJ1nuMHNogwFD_9W1GUchom2SegsFyjcAcID7u18p3PXkB4lF_6SYR-z1GCxE8ZR6Z36h0dRb6HdufqVHQD4YzTIdigG7M8/s1600/scaling_5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="432" data-original-width="521" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoPkbWGyjetY87aP1u1McgwhXb18P-grIweH6t2SxhMrA2ngJ1nuMHNogwFD_9W1GUchom2SegsFyjcAcID7u18p3PXkB4lF_6SYR-z1GCxE8ZR6Z36h0dRb6HdufqVHQD4YzTIdigG7M8/s1600/scaling_5.png" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Maybe okay, but there's so much leftover space. What to do with it? You can shift the distribution left or right by as much as 25% without saturating. So which of these 50 different solutions is best? There's simply isn't a good, general-purpose, algorithmic way to make this decision. So what generally happens is that the algorithm simply scales and stretches the distribution so that it's just shy of saturation on both ends.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQCloVgciM1ZgPyMwUmWzUQsj3e2K7dEfe7GttzPrt-RAiVtN-xo5XVXIxMUrrJT7uafzY9qTJzVOGkDRCamSzpXHw_EeybLAoHLxAcRph5bay2jeYElVz548AeYWXBEA0pw91SUA-y1Pw/s1600/scaling_6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="432" data-original-width="521" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQCloVgciM1ZgPyMwUmWzUQsj3e2K7dEfe7GttzPrt-RAiVtN-xo5XVXIxMUrrJT7uafzY9qTJzVOGkDRCamSzpXHw_EeybLAoHLxAcRph5bay2jeYElVz548AeYWXBEA0pw91SUA-y1Pw/s1600/scaling_6.png" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This requires just a couple hard-coded parameters to work correctly, and is </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">simple, open-loop (requiring no feedback), and almost always produces decent results. Wide distributions are safer and easier to work with, because by design they fit neatly into the bounding box.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This distribution comes from a photo of mine from Yellowstone:</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaMHkK7xAd5LRn8lDo1UOITjBqc22MUiw07bE7kNATgdUGSiL0a1s3HE1wmNSxigp13uGszz-opXRJrrgTEIEyKdrrN9QY3z9gApOBq4__0btFXgooec4u5IskCFQxAh6kie1QLYoLiSJF/s1600/_IMG_3702.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhaMHkK7xAd5LRn8lDo1UOITjBqc22MUiw07bE7kNATgdUGSiL0a1s3HE1wmNSxigp13uGszz-opXRJrrgTEIEyKdrrN9QY3z9gApOBq4__0btFXgooec4u5IskCFQxAh6kie1QLYoLiSJF/s640/_IMG_3702.JPG" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Does the distribution or photo look familiar? In the sense of having a wide, bimodal (two-peak) distribution with few midtones, it's actually very similar to the drab Dutch landscape from earlier. This is no coincidence - the pictures were, in effect, recorded with a very similar process.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">So, digital photos have a tendency to be drab for the same reason that 17th century Dutch landscapes did. And by drab, I mean lacking in color identity. What can be done about this?</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>How to Shift From Value-Priority to Color-Priority</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The Lab color space works well for shifting photos from value-priority to color-priority, or vice versa, for the reasons discussed earlier. To summarize the process in geometric terms:</span><br />
<br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Store a photo as an RGB point cloud</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Convert the RGB point cloud to Lab color space</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Manipulate the Lab point cloud using linear transforms</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Convert the Lab point cloud back to RGB for display</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Repeat from Step #3 until satisfied with result</span></li>
</ol>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The linear transforms in Step #3 are simple. For each of the three properties of hue, saturation, and value, the linear transform is defined by an offset and scale which is applied globally to the entire point cloud. Continuing with the geometric analogy, these transforms as a whole enable you to move, stretch, compress, twist, and expand the point cloud in an intuitive and freeform way. It's easy to push parts of the point cloud outside the limited RGB gamut, so the Lab-to-RGB conversion process accounts for this by saturating, or limiting its input before conversion.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Because these adjustments are best done by eye, they require a good deal of tweaking to get right. To facilitate this, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I wrote a GUI to quickly get the settings right before exporting. Here's an overview:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbKe_XwIKdK3VWyhgRtNtOmlbpoy5ThQbuyKeMTu5XgBGPBwxxgZcbJnliVaXZNWhvWdTBg3b6K6ku51vuAtegfqdsuIZB91DTxfFRKXVn53dlYBy8gqxAvbNx_Jq17-9vcvSjHoNYpAi9/s1600/GUI_control_panel.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="542" data-original-width="466" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbKe_XwIKdK3VWyhgRtNtOmlbpoy5ThQbuyKeMTu5XgBGPBwxxgZcbJnliVaXZNWhvWdTBg3b6K6ku51vuAtegfqdsuIZB91DTxfFRKXVn53dlYBy8gqxAvbNx_Jq17-9vcvSjHoNYpAi9/s640/GUI_control_panel.PNG" width="548" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A control panel lets you define the scale and offset for lightness (i.e. value), hue, and saturation on sliding scales. There's also a slider to control the quality of the preview, and </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">buttons to restore defaults, compare before/after images, and to export the image at full resolution.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRboBAbCl_-BMEk2rRwCINvLJWEHQ_H7tAw784XlZsQ17Y9azg00rBDI_Dw1bzN9NqTstnVXcd9sdPP4XPMGJVqeFuQAOOIKLf5Sp5JjarX7JBsJURKKAF6Zc7vbpfRglIUir7xgc9d6LV/s1600/GUI_histograms.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="660" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiRboBAbCl_-BMEk2rRwCINvLJWEHQ_H7tAw784XlZsQ17Y9azg00rBDI_Dw1bzN9NqTstnVXcd9sdPP4XPMGJVqeFuQAOOIKLf5Sp5JjarX7JBsJURKKAF6Zc7vbpfRglIUir7xgc9d6LV/s1600/GUI_histograms.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A histogram panel shows the result of the scaling operations, before and after. This is most helpful for shifting value to where the desired level of color identity can be achieved. The functionality for scaling hue is fun to play with, because it can produce wild and impossible color palettes, but for my purposes I leave it as-is.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-oEXGANfntgBxykBeFwDF9JtKhuvELK8FQjbMsUCK5CQtnckiAJu624FGvGEoGj_yPMUptyBVxYszdVMo40uup9FvVGgPR8vFeL7aw9pYR3fNxt5O_A4WWDeJzlh2s7srenxHdba4Z_2R/s1600/GUI_preview.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="648" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-oEXGANfntgBxykBeFwDF9JtKhuvELK8FQjbMsUCK5CQtnckiAJu624FGvGEoGj_yPMUptyBVxYszdVMo40uup9FvVGgPR8vFeL7aw9pYR3fNxt5O_A4WWDeJzlh2s7srenxHdba4Z_2R/s1600/GUI_preview.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Lastly, there's a preview panel which shows a downsampled copy of the image with the transforms applied. An alphanumeric string across the top conveys the transform parameters, which are also appended to the filename on export.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">There's some skill and taste involved in manipulating photos with this technique. In general, I try to keep the peaks of the value histogram between 20 and 80%, outside of which there is minimal color identity. With the saturation scaling, the offset helps "push" neutrals outward for greater color identity, while the scale helps accentuate the already-vibrant regions of an image.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Demo Gallery</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here ar</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">e some photos that I've attempted to shift from value-priority to color-priority using this technique, all </span><span style="background-color: white;">taken with my </span><a href="https://en.wikipedia.org/wiki/Canon_EOS_300D">2003 Canon Rebel</a> without any prior modifications<span style="background-color: white;">. In each photo, the left half is the original and the right half is the result.</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgmvlFwQomLbdIis8x8bKW05uBJ8dVDs3yc4obZcKagzQkUGyzAt2qKu4b2OJ4j02hZSP4baqkcaPZUlGvOGzYC5CXY_srXOriZwRp1w94eMnN4G1UoTc7TqbFtLUvneUJyj-wqlxX0lzr/s1600/_IMG_3702_comp_L_scl_0.8794_L_off_2.5126_H_scl_1_H_off_0_S_scl_1.8593_S_off_6.5327.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgmvlFwQomLbdIis8x8bKW05uBJ8dVDs3yc4obZcKagzQkUGyzAt2qKu4b2OJ4j02hZSP4baqkcaPZUlGvOGzYC5CXY_srXOriZwRp1w94eMnN4G1UoTc7TqbFtLUvneUJyj-wqlxX0lzr/s640/_IMG_3702_comp_L_scl_0.8794_L_off_2.5126_H_scl_1_H_off_0_S_scl_1.8593_S_off_6.5327.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmAXa9HVUrDCr_kyZ1VnOfnNe9YG87j3S-VOYhmihMjPQr5-8Dc49-6FMKqquzRiM62vwlollZh_aTUEaVVQi962hACkV3A_gmj2RtfUnqXXQ96NQK9zwnnXEeyfCGVIx13cMuqQDVYLFK/s1600/IMG_3718_comp_L_scl_0.65_L_off_20_H_scl_1_H_off_0_S_scl_2.3111_S_off_0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmAXa9HVUrDCr_kyZ1VnOfnNe9YG87j3S-VOYhmihMjPQr5-8Dc49-6FMKqquzRiM62vwlollZh_aTUEaVVQi962hACkV3A_gmj2RtfUnqXXQ96NQK9zwnnXEeyfCGVIx13cMuqQDVYLFK/s640/IMG_3718_comp_L_scl_0.65_L_off_20_H_scl_1_H_off_0_S_scl_2.3111_S_off_0.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSNok-EkYGgs9bSiP5RWrV2q7SO-MSw1gsUhmeoPMTyZZqGItcDWBs0WHxjG5eAB5Rg_KhRsRa5pbwOz4z5E5yP9aHon3K_sPa86rhnhdyXqtpbwVnhKr1fP6mD4Oc3QeK15omEV_OoK4p/s1600/IMG_3758_comp_L_scl_0.90453_L_off_8.794_H_scl_1_H_off_0_S_scl_1.0553_S_off_9.6734.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSNok-EkYGgs9bSiP5RWrV2q7SO-MSw1gsUhmeoPMTyZZqGItcDWBs0WHxjG5eAB5Rg_KhRsRa5pbwOz4z5E5yP9aHon3K_sPa86rhnhdyXqtpbwVnhKr1fP6mD4Oc3QeK15omEV_OoK4p/s640/IMG_3758_comp_L_scl_0.90453_L_off_8.794_H_scl_1_H_off_0_S_scl_1.0553_S_off_9.6734.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinnBdb8xLp1MgRnO6AjLpnpVJHB3sN74gYDXBj8yHHigSOyA8ncKZKoai9PeClT7WOsyj0d3S-JnKFJRGw_eLKbJGLnLMLD0pMqaekGWLNWVDWPmsc1bg0B0hghX7S32s0qLbhN8ypHIDs/s1600/IMG_3778_comp_L_scl_0.80402_L_off_10.294_H_scl_1_H_off_0_S_scl_1.8593_S_off_0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinnBdb8xLp1MgRnO6AjLpnpVJHB3sN74gYDXBj8yHHigSOyA8ncKZKoai9PeClT7WOsyj0d3S-JnKFJRGw_eLKbJGLnLMLD0pMqaekGWLNWVDWPmsc1bg0B0hghX7S32s0qLbhN8ypHIDs/s640/IMG_3778_comp_L_scl_0.80402_L_off_10.294_H_scl_1_H_off_0_S_scl_1.8593_S_off_0.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO9taz02RVHzQE1j7eohac-pNnWKSQmQUXfTIOIbEsR61v3mHM4NGcsGG0hUj_96Ba9bFvjNanh1dFmw6zpCxSrtGRKN_BaVoex59jiqWI_FtNwDpJ5MdFB6UVC8z4R1SjyBui27tur0Iv/s1600/IMG_4127_comp_L_scl_0.85_L_off_10_H_scl_1_H_off_0_S_scl_1.6_S_off_2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiO9taz02RVHzQE1j7eohac-pNnWKSQmQUXfTIOIbEsR61v3mHM4NGcsGG0hUj_96Ba9bFvjNanh1dFmw6zpCxSrtGRKN_BaVoex59jiqWI_FtNwDpJ5MdFB6UVC8z4R1SjyBui27tur0Iv/s640/IMG_4127_comp_L_scl_0.85_L_off_10_H_scl_1_H_off_0_S_scl_1.6_S_off_2.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjCUEw22s-1T8Hk4XLiupLqUHR2MTFEHnq22mmVifaM_E_FjpdvL_uwKYvVAKt7PvM95Zw4nyO0k-SMz2CzKAMn2VeEni6h_Pt8AW075jsP20SkrW3K0pa9JYrKVzyeJ00wTpi6NVl7fFX/s1600/IMG_3434_comp_L_scl_0.75_L_off_18.603_H_scl_1_H_off_0_S_scl_1.3578_S_off_0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjCUEw22s-1T8Hk4XLiupLqUHR2MTFEHnq22mmVifaM_E_FjpdvL_uwKYvVAKt7PvM95Zw4nyO0k-SMz2CzKAMn2VeEni6h_Pt8AW075jsP20SkrW3K0pa9JYrKVzyeJ00wTpi6NVl7fFX/s640/IMG_3434_comp_L_scl_0.75_L_off_18.603_H_scl_1_H_off_0_S_scl_1.3578_S_off_0.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5kKidQm0EOFzdlJpNNT8O2cQwOsUO2oF-GYqF7EPRGuDtDIb2uOu4MBBWRMSRIJa_S-86UKySlDo4lk4K1WHhxZpJYFGr76GNqYrun8ksvJAfOpGokn8Ipzj3AOplXVsABRDGQmybLyGX/s1600/IMG_3779_comp_L_scl_0.65327_L_off_23.5778_H_scl_1_H_off_0_S_scl_2.1588_S_off_4.7739.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj5kKidQm0EOFzdlJpNNT8O2cQwOsUO2oF-GYqF7EPRGuDtDIb2uOu4MBBWRMSRIJa_S-86UKySlDo4lk4K1WHhxZpJYFGr76GNqYrun8ksvJAfOpGokn8Ipzj3AOplXVsABRDGQmybLyGX/s640/IMG_3779_comp_L_scl_0.65327_L_off_23.5778_H_scl_1_H_off_0_S_scl_2.1588_S_off_4.7739.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhruolVWMQ5R_wdxlzie0JSeSRhVQ0hNEwtjHQesF9_HQrsZkeqyJQLvmZWbEsPQZDimYyVIJo5Whl36HJMfS7fzdZp9q8ASK64im7TJqzzbDh9xE8Z1vdT2OiAdhLtfKadG6YwNQ-PcI9/s1600/IMG_3408_comp_L_scl_0.77865_L_off_13.6482_H_scl_1_H_off_0_S_scl_1.5578_S_off_0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjhruolVWMQ5R_wdxlzie0JSeSRhVQ0hNEwtjHQesF9_HQrsZkeqyJQLvmZWbEsPQZDimYyVIJo5Whl36HJMfS7fzdZp9q8ASK64im7TJqzzbDh9xE8Z1vdT2OiAdhLtfKadG6YwNQ-PcI9/s640/IMG_3408_comp_L_scl_0.77865_L_off_13.6482_H_scl_1_H_off_0_S_scl_1.5578_S_off_0.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil8yX4wl3vyZ1ePjAIVSPhim3TAWAYkImbcetb2I9e-G0Ps9Rtcp59gCPyLYcJQ4be3oQqddCnLQwy7K5c_gZGa9cFCTiYZ7dUGked-NdQbsD2oheUJS6_hfGIkyZFWd17iYF2LRxSWMMM/s1600/IMG_3361_comp_L_scl_0.75352_L_off_16.603_H_scl_1_H_off_0_S_scl_1.0548_S_off_6.407.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEil8yX4wl3vyZ1ePjAIVSPhim3TAWAYkImbcetb2I9e-G0Ps9Rtcp59gCPyLYcJQ4be3oQqddCnLQwy7K5c_gZGa9cFCTiYZ7dUGked-NdQbsD2oheUJS6_hfGIkyZFWd17iYF2LRxSWMMM/s640/IMG_3361_comp_L_scl_0.75352_L_off_16.603_H_scl_1_H_off_0_S_scl_1.0548_S_off_6.407.jpg" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitGGjTg9LfYG845SdK-xVmngBFeE34xMr_veAjwtZgxU-jAsbJgMQFWw57TZFbGuSOXBhoLf60acA1-ttSc2j5GC22dFb8400kjIs-_V2C7nKoqvBhQT4OmUhNkGrpW1RThcG8PlZfm0_B/s1600/IMG_2901_comp_L_scl_0.75_L_off_18_H_scl_1_H_off_0_S_scl_3.3668_S_off_3.8944.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitGGjTg9LfYG845SdK-xVmngBFeE34xMr_veAjwtZgxU-jAsbJgMQFWw57TZFbGuSOXBhoLf60acA1-ttSc2j5GC22dFb8400kjIs-_V2C7nKoqvBhQT4OmUhNkGrpW1RThcG8PlZfm0_B/s640/IMG_2901_comp_L_scl_0.75_L_off_18_H_scl_1_H_off_0_S_scl_3.3668_S_off_3.8944.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTN2MvaXmy3vRQ_YTnqmfLc7TOffrZleFBTqMZPpBAur_K_g3ZQrxKJwM_FK-yVkJnBHL4P5zBQ4zylPBmvvxVoOEInw3eKfWXL94C2ES60U76Fwby0HH-XWbUTUZM722FhTdwusrnMfYO/s1600/IMG_3283_comp_L_scl_0.7_L_off_18_H_scl_1_H_off_0_S_scl_1.7_S_off_3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTN2MvaXmy3vRQ_YTnqmfLc7TOffrZleFBTqMZPpBAur_K_g3ZQrxKJwM_FK-yVkJnBHL4P5zBQ4zylPBmvvxVoOEInw3eKfWXL94C2ES60U76Fwby0HH-XWbUTUZM722FhTdwusrnMfYO/s640/IMG_3283_comp_L_scl_0.7_L_off_18_H_scl_1_H_off_0_S_scl_1.7_S_off_3.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br />And to circle back to the original concept, here are a couple examples of shifting a painting's color gamut to align with a different school of painting:<br /><br /> Recasting a Dutch landscape</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> as an Impressionist painting:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTEfi5GY5bH4Rz7-1Te2L5KR6rgiwO4lhyphenhyphenTps7reaUrBzMrTVPxKWpXGDeFyCza8nL4uWXjL_smcyeanVySEbjhj7QeCnUqii9xhsz7yL1ucMyTmWWW5dX-wWzY-Wd9ib5EnpQzcHmz-yh/s1600/Meindert_Hobbema_001_comp_L_scl_1.2312_L_off_6.2814_H_scl_1_H_off_0_S_scl_2.7136_S_off_2.3869.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1186" data-original-width="1600" height="470" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTEfi5GY5bH4Rz7-1Te2L5KR6rgiwO4lhyphenhyphenTps7reaUrBzMrTVPxKWpXGDeFyCza8nL4uWXjL_smcyeanVySEbjhj7QeCnUqii9xhsz7yL1ucMyTmWWW5dX-wWzY-Wd9ib5EnpQzcHmz-yh/s640/Meindert_Hobbema_001_comp_L_scl_1.2312_L_off_6.2814_H_scl_1_H_off_0_S_scl_2.7136_S_off_2.3869.jpg" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Meindert Hobbema, <a href="https://www.nationalgallery.org.uk/paintings/meindert-hobbema-the-avenue-at-middelharnis">The Avenue at Middelharnis</a>, 1689</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Recasting an Impressionist painting as a Dutch landscape:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5kzA9e9MpZpLmvSakeonFM-6ptk-Os7FycILvgVTbMZVdYIOLkDQtwrmRr0f_s9TUrJcHHL2NaKycgd-WdvNX4Kj7-goxRVtZqTp5jwyoJ9SMbh9sWenI5e6CSWXozvSm_7lu8OWKgDBZ/s1600/1280px-Claude_Monet_-_Poppy_Field_-_Google_Art_Project_comp_L_scl_1.5327_L_off_-42.7438_H_scl_1_H_off_0_S_scl_0.75377_S_off_0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="977" data-original-width="1280" height="486" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5kzA9e9MpZpLmvSakeonFM-6ptk-Os7FycILvgVTbMZVdYIOLkDQtwrmRr0f_s9TUrJcHHL2NaKycgd-WdvNX4Kj7-goxRVtZqTp5jwyoJ9SMbh9sWenI5e6CSWXozvSm_7lu8OWKgDBZ/s640/1280px-Claude_Monet_-_Poppy_Field_-_Google_Art_Project_comp_L_scl_1.5327_L_off_-42.7438_H_scl_1_H_off_0_S_scl_0.75377_S_off_0.jpg" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Claude Monet, <a href="https://www.musee-orsay.fr/en/collections/works-in-focus/search/commentaire/commentaire_id/poppy-field-8951.html">Coquelicots [Poppy Field]</a>,</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> 1873</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Source Code</b></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Freely available on <a href="https://github.com/kindofdoon/Scale_Image_in_Lab_Color_Space">my GitHub</a>.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Acknowledgements</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; text-align: center;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; text-align: center;">Mitchell Albala provided corrections and suggestions for the Motivation and Background sections.</span></li>
</ul>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
</div>
</div>
</div>
</div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-546358365526096132020-02-15T13:15:00.000-08:002020-02-16T08:38:47.505-08:00Paint Palette to Color Gamut<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Overview</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In mid-2019, I published "<a href="http://www.kindofdoon.com/2019/07/how-paints-mix.html">How Paints Mix</a>", outlining a method for mathematical simulation of color in paint mixing. This method can be applied in two distinct ways:</span></div>
<div>
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Color Mixing:</i> Predict the digital color of an arbitrary mixture of primary paints.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Color Decomposition:</i> Decompose a digital color into a primary paint mixing recipe.</span></li>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">My original article focused heavily on <i>Mixing</i>, leaving <i>Decomposition</i> as an afterthought. In this article, I'll lay out a much-improved decomposition method that works by translating an analog paint palette to a digital color gamut.</span></div>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Decomposition by Random Optimization</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Previously, to decompose a digital color, I used a simple random optimization method:</span></div>
<div>
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">User provides a "target" digital color to decompose.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Start a timer.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Randomly generate a valid recipe and evaluate its color distance to the target.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">If the color distance is less than the previous best, save the result and reset the timer.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Repeat #3-4 until 3 seconds have elapsed since the last timer reset.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Return the best known solution.</span></li>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This algorithm is simple and works well enough, but has the drawbacks of being relatively slow (~5 seconds per decomposition), not repeatable, and not necessarily optimal.</span></div>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<b style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">Size of Solution Space</b></div>
<div>
<b style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;"><br /></b></div>
<div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I initially implemented random optimization because I estimated that the solution space of possible recipes for a given palette was far too large to search exhaustively. Considering my baseline values for painting:</span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Number of primary paints: 7</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Maximum number of ingredients per recipe: 4</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mixing precision: 5% or 1/20</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I reasoned that if any primary can have 21 possible values (0%, 5%, 10%,...100%), then the solution space could be as large as 21^7 or 1,800,000,000 recipes. While technically true that this represents an upper bound, this turns out to be an extremely inaccurate estimate.</span></div>
</div>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">When you account for the fact that recipes must sum to 100% and include no more than 4 ingredients with non-zero fractions, the solution space shrinks by an incredible 5 orders of magnitude to about 35,000 recipes. This solution space is then possible to generate and search exhaustively.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As a clerical note: I use the term "primary" loosely, to mean any paint in its pure, unmixed state, i.e. straight from the tube. Here are my primaries, all from Winsor & Newton's "<a href="https://www.winsornewton.com/na/shop/oil-colour/winton-oil-colour">Winton</a>" line of oil paints:</span></div>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY6cNwN9TFDmPxAJ4XFB6nWcoXwJ9f8j8NlUNpgC57d-KBOix3wn_mYv9ai8vtw9QBRUZPrixyO-guzM3lh8IxolCwP-GEYBS5HXQUPz29rUv_xZJ2yLOb9OveLeCD25fhKOxVNycO8nNh/s1600/primaries.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="124" data-original-width="808" height="98" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY6cNwN9TFDmPxAJ4XFB6nWcoXwJ9f8j8NlUNpgC57d-KBOix3wn_mYv9ai8vtw9QBRUZPrixyO-guzM3lh8IxolCwP-GEYBS5HXQUPz29rUv_xZJ2yLOb9OveLeCD25fhKOxVNycO8nNh/s640/primaries.png" width="640" /></a></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Creating a Cookbook</b></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Realizing that there is already a convenient term to describe an exhaustive collection of recipes, I began using the term "cookbook" to describe this database of colors. The main challenge of creating a cookbook is generating the set of all possible recipes. My method works as follows:</span></div>
<div>
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Generate an ingredient subset matrix. This is an n-choose-k aka <a href="https://en.wikipedia.org/wiki/Binomial_coefficient">binomial coefficient</a> problem. For 7 primaries and a 4 ingredient max, there are nchoosek(7,4) = 35 ingredient subsets, i.e. 35 unique ways of picking 4 ingredients from a set of 7 when order is irrelevant. This result looks like:</span></li>
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1 2 3 4] Row 1</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1 2 3 5] Row 2</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1 2 3 6] Row 3</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1 2 3 7] Row 4</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1 2 4 5] Row 5</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">...</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1 4 6 7] Row 19</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1 5 6 7] Row 20</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[2 3 4 5] Row 21</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[2 3 4 6] Row 22</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">...</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[3 4 6 7] Row 33</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[3 5 6 7] Row 34</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[4 5 6 7] Row 35 (end)</span></li>
</ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Generate a fraction vector representing the set of all permitted values for a single ingredient. For 5% precision, this result looks like:</span></li>
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 ... 0.90 0.95 1.00]</span></li>
</ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Generate a matrix for all possible 4-element permutations of the fraction vector, with repetition permitted. I use <a href="https://www.mathworks.com/matlabcentral/fileexchange/7147-permn">permn</a> for this purpose. This result looks like:</span></li>
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.00 0.00] Row 1</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.00 0.05] Row 2</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.00 0.10] Row 3</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">...</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.45 0.05 0.15 0.35] Row 83,861</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">...</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.45 0.85 0.10 0.10] Row 90,891</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">...</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1.00 1.00 1.00 0.95] Row 194,480</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1.00 1.00 1.00 1.00] Row 194,481 (end)</span></li>
</ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Delete all rows of the permutation matrix that do not sum to 1.00 or 100%. This winnows the list from 194,481 rows to 1,596 rows. This result looks like:</span></li>
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.00 1.00] Row 1</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.05 0.95] Row 2</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.10 0.90] Row 3</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">...</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.20 0.20 0.05 0.55] Row 796</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.20 0.20 0.10 0.50] Row 797</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.20 0.20 0.15 0.45] Row 798</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">...</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.95 0.00 0.05 0.00] Row 1,594</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.95 0.05 0.00 0.00] Row 1,595</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[1.00 0.00 0.00 0.00] Row 1,596 (end)</span></li>
</ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Create a recipe matrix by copying the permutation matrix for each row of the ingredient subset matrix. This result looks like:</span></li>
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.00 1.00 0.00 0.00 0.00] Row 1</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.05 0.95 0.00 0.00 0.00] Row 2</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.10 0.90 0.00 0.00 0.00] Row 3</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">...</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.05 0.00 0.25 0.00 0.00 0.10 0.60] Row 24,243</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.05 0.00 0.25 0.00 0.00 0.15 0.55] Row 24,244</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.05 0.00 0.25 0.00 0.00 0.20 0.50] Row 24,245</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">...</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.00 0.95 0.00 0.05 0.00] Row 55,858</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.00 0.95 0.05 0.00 0.00] Row 55,859</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">[0.00 0.00 0.00 1.00 0.00 0.00 0.00] Row 55,860 (end)</span></li>
</ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Eliminate duplicate rows. This reduces the row count from 55,860 to 35,651.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Simulate each recipe, recording its reflectance spectrum and color in XYZ, RGB, and Lab formats.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Return the completed cookbook, totaling 17.3 MB (or 2.4 MB if excluding reflectance spectra which are not strictly necessary). The entire process of generating the cookbook for this set of parameters takes about 18 seconds.</span></li>
</ol>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Decomposition by Cookbook</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With the cookbook complete, decomposition is very fast, accurate, and repeatable. A target color in RGB format is converted to Lab color space, its color distance to each cookbook recipe is evaluated, and the recipe with minimum color distance to the target is returned. This happens in about 0.04 seconds, permitting decomposition of about 24 colors per second, or ~125x the speed of random optimization.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">There are a few finer details required to make this process work optimally:</span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">If supplying target colors from an RGB image, the image's value domain must be aligned with the cookbook's value domain. In other words, the image must be scaled such that its pure black matches the darkest color in the cookbook, and so forth for the lightest. This assumes the palette can achieve a near-black and a near-white color. I use <a href="https://www.mathworks.com/help/images/ref/imadjust.html">imadjust</a> for this purpose, and it is functionally equivalent to a <a href="https://docs.gimp.org/2.10/en/gimp-tool-levels.html">Levels</a> adjustment in Photoshop/GIMP.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Lab colors must be derived in a consistent fashion between image and cookbook. In other words, since image colors can only be derived by RGB > XYZ > Lab, then the cookbook Lab colors should be derived by Reflectance > XYZ > RGB > XYZ > Lab, rather than Reflectance > XYZ > Lab. This is counter-intuitive but greatly improves color matching accuracy. I use Bruce Lindbloom's <a href="http://www.brucelindbloom.com/">color conversion equations</a> and an illuminant of <a href="https://en.wikipedia.org/wiki/Illuminant_D65">D65</a>.</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Other Uses for a Cookbook</b></span></div>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Although my initial interest in cookbooks was color decomposition, I realized that they had many other interesting and helpful applications. As a whole, they describe the complete color <a href="https://en.wikipedia.org/wiki/Gamut">gamut</a> (set of possible colors) for a given palette. What does this look like? How does it change as a function of which primaries are permitted? How does mixing precision affect it?</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Digital color is 3-dimensional, whether working on RGB, HSV, XYZ, or Lab color space. This makes visualizing it on a 2D monitor non-trivial. Here, I'll show two possible visualization methods, one theoretical and one applied.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Theoretical: Point Cloud Cross-Sections</i></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Each recipe corresponds to a single point in 3D color space, so a cookbook corresponds to a point cloud in 3D space. To fully view this, a cross-section plane can be swept through the point cloud at varying lightness (L) values, and shown from an isometric and front view. For the baseline parameter set:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnzuolKTkjL-t0wJLDbBXoGUbhs19CEvtT-7ifPWUKjszBVgPSXBlv5hNhrnDvqC96rMtpLr1hLIA7gyobC4MNMRZvyLNeKjQsC7pgX8fWQ5As_qDauZyEwLI-iNuA_jjYDYfEOs0BKhC1/s1600/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_4_frac_prec_20_fps_20_duration_3.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnzuolKTkjL-t0wJLDbBXoGUbhs19CEvtT-7ifPWUKjszBVgPSXBlv5hNhrnDvqC96rMtpLr1hLIA7gyobC4MNMRZvyLNeKjQsC7pgX8fWQ5As_qDauZyEwLI-iNuA_jjYDYfEOs0BKhC1/s640/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_4_frac_prec_20_fps_20_duration_3.GIF" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Notice that there is much higher recipe density at lower L (lightness) values. This is because oil primaries tend to be very dark to maximize their economy, and because paint mixes tend to darken more readily than lighten. To reduce the spatial gaps between recipes, especially on the lighter end of the color gamut, the </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">precision can be increased from 1/20 to 1/40:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuVZedCnGVa5fV7H0Ep8ScSNwS7xA6h3Rr4BUXTMBRUU4qjhu_1JYfztdyGcDkgDYGYCgkB2isQrmpr2zxXI6-bHj4SU7xbXijlmh5wsQTUXRGV2OfiJBJwkYYETsgwtO32_G2DQRL1uqI/s1600/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_4_frac_prec_40_fps_20_duration_3.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiuVZedCnGVa5fV7H0Ep8ScSNwS7xA6h3Rr4BUXTMBRUU4qjhu_1JYfztdyGcDkgDYGYCgkB2isQrmpr2zxXI6-bHj4SU7xbXijlmh5wsQTUXRGV2OfiJBJwkYYETsgwtO32_G2DQRL1uqI/s640/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_4_frac_prec_40_fps_20_duration_3.GIF" width="640" /></a></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In reality, paint mixing is continuous rather than discretized by a fixed precision, so the gaps between recipes in this scatter-plot visualization are an artifact of this simplifying assumption.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For the sake of curiosity, the cookbook may be calculated such that it allows only 2 ingredients per recipe.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoRqZgagprEWKXACZVZfwPt6bc0uxCaAQE9zVqZt31y6eHKjqzFuGIXarzGkFpiD_esY2liMlMnr-nl2PSPA47I7TuKOd-9_jV8ETcqLaWuBFSvzYhtAF_EukhyphenhyphenBr8U2pepVKdqz0_I6ti/s1600/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_2_frac_prec_1000_fps_20_duration_3.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoRqZgagprEWKXACZVZfwPt6bc0uxCaAQE9zVqZt31y6eHKjqzFuGIXarzGkFpiD_esY2liMlMnr-nl2PSPA47I7TuKOd-9_jV8ETcqLaWuBFSvzYhtAF_EukhyphenhyphenBr8U2pepVKdqz0_I6ti/s640/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_2_frac_prec_1000_fps_20_duration_3.GIF" width="640" /></a></div>
<div>
<br /></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here, distinct nodes representing pure yellow and pure white (the two brightest primaries) can be seen, with paths sweeping toward them from the other primaries. Blue can be seen transitioning through green on its way to yellow, and burnt sienna nearly maintains a=0 and b=0 as it transitions to white, a truly neutral gray.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Suppose the ingredient limit is increased from 2 to 3:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg7u1romEkmlTJB72NSHas4apf_PR7xgC3J1lkdQIfJjvG8de5um71GOYjZ7Pi27CB5KNNt1N53nUcD-0drVudaUHwb_rzlTKYUP60XCz6uwYX3YcBiZi_5X_HB6f-pO7chyTKQPSRnyRf/s1600/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_3_frac_prec_100_fps_20_duration_3.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg7u1romEkmlTJB72NSHas4apf_PR7xgC3J1lkdQIfJjvG8de5um71GOYjZ7Pi27CB5KNNt1N53nUcD-0drVudaUHwb_rzlTKYUP60XCz6uwYX3YcBiZi_5X_HB6f-pO7chyTKQPSRnyRf/s640/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_3_frac_prec_100_fps_20_duration_3.GIF" width="640" /></a></div>
<div>
<br /></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The color gamut fills in considerably, but there are still significant gaps. Overshooting the 4-ingredient baseline, the color gamut may be evaluated for 5-ingredient recipes:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjupRDhO0GjCFRMYvd6n2xbXFNSqcWrco47CMAMTvHywkvJQ-1N0Sl_1ovb-yn61rLyclwFga6M0haYZBpVxmnogKjTkk8L3Pt5YX1qR28lPXtPnow_HmyI15ag9ZgxjjydHZ0gTfHm9eYR/s1600/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_5_frac_prec_25_fps_20_duration_3.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjupRDhO0GjCFRMYvd6n2xbXFNSqcWrco47CMAMTvHywkvJQ-1N0Sl_1ovb-yn61rLyclwFga6M0haYZBpVxmnogKjTkk8L3Pt5YX1qR28lPXtPnow_HmyI15ag9ZgxjjydHZ0gTfHm9eYR/s640/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_sapgreen_ultramarineblue_titaniumwhite_ingred_max_5_frac_prec_25_fps_20_duration_3.GIF" width="640" /></a></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Notice that the 5-ingredient color gamut is not significantly different from the 4-ingredient color gamut. There is more complexity, but the result is effectively the same. This corroborates my initial intuition of 4 ingredients per recipe being the "sweet spot" of balancing accuracy with complexity. It's also in line with traditional oil painting wisdom that a recipe needs at most 3 primaries plus white, for 4 ingredients total.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Paring the palette down just to these essential primaries - yellow, red, blue, white:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiub1nQBBxk-VWHumiNNubLj4Glf62E_I_6vcVlnxUhkXtpJ3QwIK5aUtHpLMxib3v9Ed0_3WQMPdlIpT2XAf2XjLlm_x_XE8Ti9d3tIqf3EXHypzNbxqYvwAhQ1boTEkED3QxFyOPpRwcg/s1600/cookbook_cadmiumred_cadmiumyellow_ultramarineblue_titaniumwhite_ingred_max_4_frac_prec_75_fps_20_duration_3.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiub1nQBBxk-VWHumiNNubLj4Glf62E_I_6vcVlnxUhkXtpJ3QwIK5aUtHpLMxib3v9Ed0_3WQMPdlIpT2XAf2XjLlm_x_XE8Ti9d3tIqf3EXHypzNbxqYvwAhQ1boTEkED3QxFyOPpRwcg/s640/cookbook_cadmiumred_cadmiumyellow_ultramarineblue_titaniumwhite_ingred_max_4_frac_prec_75_fps_20_duration_3.GIF" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As expected, this color gamut has the same bounding box as with 7 primaries, and is nearly as full. This shows that the non-essential primaries - the browns and green - are not strictly necessary from a chromatic perspective, but practically helpful to have on hand.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Suppose that the palette includes only neutral or cool primaries:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiluyQlK8CZMeRrQk0oRLZWGAkhlveJG44OFAte8X31l77TdtDXSPRhNr_RRiR5Nf2HWDFiGVEN4RHBpGN-M8KlhyXHJKXlTxUgHtn480GkFrkJe9JyVASPGq9cVhYHD1HLivUcFXLpzZaB/s1600/cookbook_burntumber_sapgreen_ultramarineblue_titaniumwhite_ingred_max_4_frac_prec_50_fps_20_duration_3.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiluyQlK8CZMeRrQk0oRLZWGAkhlveJG44OFAte8X31l77TdtDXSPRhNr_RRiR5Nf2HWDFiGVEN4RHBpGN-M8KlhyXHJKXlTxUgHtn480GkFrkJe9JyVASPGq9cVhYHD1HLivUcFXLpzZaB/s640/cookbook_burntumber_sapgreen_ultramarineblue_titaniumwhite_ingred_max_4_frac_prec_50_fps_20_duration_3.GIF" width="640" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And similarly for neutral or warm primaries:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfSOU19i1uCAmofor1JviV5RIlHNzd_fBktY6eHiG8gJG87gqyK-ManGgOVbDVa6ig92_SsREzJP6aaWZRa4B2GC46N9kDrbjk5XP0Tpd1vHMAR9M4tOjg0SCQbfgJCHOqAkUj-JYHahdg/s1600/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_titaniumwhite_ingred_max_4_frac_prec_40_fps_20_duration_3.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="1200" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfSOU19i1uCAmofor1JviV5RIlHNzd_fBktY6eHiG8gJG87gqyK-ManGgOVbDVa6ig92_SsREzJP6aaWZRa4B2GC46N9kDrbjk5XP0Tpd1vHMAR9M4tOjg0SCQbfgJCHOqAkUj-JYHahdg/s640/cookbook_burntsienna_burntumber_cadmiumred_cadmiumyellow_titaniumwhite_ingred_max_4_frac_prec_40_fps_20_duration_3.GIF" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Applied: Image Fit</i></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Another way of visualizing a cookbook's color gamut is comparing it against a reference image. For paint mixing applications, this gives some intuition about how well a palette can recreate a provided image. Suppose this is the reference image:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTvVHCL2hVzatX-ekKiIulqLnQlg567mUDHQaCkTTLzAkpQQDcjKP6dqigpLU43SrroKr5BuWDV4V1gE1IaahkYWO83NMXvqoGcIwHY7-qVzI8aQvHDTgUy3m9NwCkwRXPM1885I87sAlm/s1600/silos_medium.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="615" data-original-width="922" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTvVHCL2hVzatX-ekKiIulqLnQlg567mUDHQaCkTTLzAkpQQDcjKP6dqigpLU43SrroKr5BuWDV4V1gE1IaahkYWO83NMXvqoGcIwHY7-qVzI8aQvHDTgUy3m9NwCkwRXPM1885I87sAlm/s640/silos_medium.jpg" width="640" /></a></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">By evaluating the minimum color distance between image and cookbook for each pixel, the palette can be tailored to the choice of image. Returning to the baseline parameter set of 7 primaries, 4 ingredients, and 5% precision, and downsampling the image for speed, the result is as follows:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfoFiLPvziTzkvLX6Z1GWsm8u5OmAHGEfIXvghRSikJ0v9wKiPNaUWW82a1RA4Xib7PwQXYP3XcWtjIXSjWI9svInnQOY1dtz-jsVHxnZqTm_I153sVvUHr6I4yFxC7YG_gvUIQBfULFrh/s1600/palette_fit_all.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="328" data-original-width="526" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfoFiLPvziTzkvLX6Z1GWsm8u5OmAHGEfIXvghRSikJ0v9wKiPNaUWW82a1RA4Xib7PwQXYP3XcWtjIXSjWI9svInnQOY1dtz-jsVHxnZqTm_I153sVvUHr6I4yFxC7YG_gvUIQBfULFrh/s1600/palette_fit_all.png" /></a></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Overall, the fit is very good - the maximum color error is ~1.7 JND, or just noticeable differences, and most of the image is below 1.0 JND. Unsurprisingly, the largest errors occur in the brightest region of the image. Suppose both browns - burnt sienna and burnt umber - are eliminated from the palette. The result is as follows:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5nQTjDbW75Uxqz-ebKQXFWQQyjkb60KUp1LJlI-ZaI6XPM7Wz0EjgnzhpFRutb3oJmZuSxmMhzEP6P3IAIHLI3d5kLIYRIOdAs37CEdlwf8MjyiFG0KValmnY85UMlrTks8X1HyFZg0Zx/s1600/palette_minus_browns.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="328" data-original-width="526" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5nQTjDbW75Uxqz-ebKQXFWQQyjkb60KUp1LJlI-ZaI6XPM7Wz0EjgnzhpFRutb3oJmZuSxmMhzEP6P3IAIHLI3d5kLIYRIOdAs37CEdlwf8MjyiFG0KValmnY85UMlrTks8X1HyFZg0Zx/s1600/palette_minus_browns.png" /></a></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The fit is noticeably worse, suggesting that we at least one of the browns should be retained. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Applying my artistic intuition, suppose that burnt umber is returned to the palette:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY21Aluu236m6_adnPb_yY-MSk89eI09cdruVN1VBdsuyleKj1MeY5c7NVEwKx1cefmVrH1XVUjECh8TcEY7FXTyIk_NpqCmxpytLZUWdnu03P5UrgH7Iw7lpVmU1AMo_TUPzJLHQIDXBp/s1600/palette_minus_burntsienna.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="328" data-original-width="526" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY21Aluu236m6_adnPb_yY-MSk89eI09cdruVN1VBdsuyleKj1MeY5c7NVEwKx1cefmVrH1XVUjECh8TcEY7FXTyIk_NpqCmxpytLZUWdnu03P5UrgH7Iw7lpVmU1AMo_TUPzJLHQIDXBp/s1600/palette_minus_burntsienna.png" /></a></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And this is good result. The maximum error is no higher than with the full palette, while the number of primaries has been reduced from 7 to 6, and correspondingly the cookbook recipe count has been reduced from 35,000 to 16,000. This result indicates that there is no need for burnt sienna in this particular image. Its elimination reduces the amount of paint required, and speeds up decomposition calculations by almost a factor of 2.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">These palette evaluations computationally expensive, hence the need for heavy downsampling. The results echo the traditional oil painting wisdom of using a limited palette consisting of chromatically orthogonal pigments. This method provides a quantitative rationale for this centuries-old technique.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Conclusion</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Cookbooks are an extremely powerful tool for color decomposition, and provide quantitative insight into the traditional oil painting concept of a limited palette.</span></div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-47540910326248198282020-01-26T13:25:00.000-08:002020-01-28T10:14:23.901-08:003D Focal Point Median Blur<b><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Summary</span></b><br />
<b><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></b>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This article presents a method for variably de-focusing a stereoscopic image in 3D space around a desired focal point. The goal is to better simulate a single moment of human vision, which is based on a focal <i>point</i> rather than a focal <i>plane</i> as with conventional photography.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBvnW_u9giAJtgzYvGRN_BTt7CiJSmY2mK_JI-K56bjZ544t0_1yeIzSBXgNPSC_-jNDTFttm-eUGmVZRJjeNcV2KCLE_IDz0vXpXt35FE1M_8fZgAgxTC1s2SRR98G_tL_R-ny4j3fwnM/s1600/frame1_frame2_frame3_anim.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="524" data-original-width="512" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBvnW_u9giAJtgzYvGRN_BTt7CiJSmY2mK_JI-K56bjZ544t0_1yeIzSBXgNPSC_-jNDTFttm-eUGmVZRJjeNcV2KCLE_IDz0vXpXt35FE1M_8fZgAgxTC1s2SRR98G_tL_R-ny4j3fwnM/s1600/frame1_frame2_frame3_anim.GIF" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Comparison of de-focusing methods </span><span style="background-color: white; color: #545454; font-family: "roboto" , "arial" , sans-serif; font-size: 14px; text-align: left;">— </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1: original, 2: 3D planar focus, 3: 3D point focus</span></div>
<br />
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Human Vision vs. Camera Vision</b><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Photographs are actually a fairly poor representation of how a person sees the world with their natural senses. This is often overlooked, however, because photographs have become so commonplace and integral that it's hard to even imagine an alternative. Similarly, the conventional 24 frames-per-second of movies looks "right", though not because it's actually realistic, but because we're used to it. I've <a href="http://www.kindofdoon.com/2019/11/histogram-diffusion-image-filter.html">previously discussed</a> how chromatic (color) realism can be augmented in some photos using histogram diffusion. In this article, I'll turn my attention to focal realism.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In a single moment, a camera focuses on a focal plane, i.e. the set of all points a certain distance from the lens. In reality, the notion of a "focal plane" is a convenient approximation and "focal sphere" would be more accurate, but the distinction is not important here. This contrasts with human vision, which focuses only on a single focal point at a time. As a simple experiment, try fixing your eyes on a convenient focal point, and "looking" at other parts of the image away from the focal point, without moving your eyes. You'll notice that the image becomes progressively more "vague" as you look farther from the focal point. This effect happens simultaneously and seamlessly in all three dimensions. The greater the distance between focal point and observed point, whether up-down, left-right, or front-back, the more vague the image becomes. In effect, we have permanent tunnel vision, and compensate with rapid eye movements, piecing a scene together from multiple glances. Similarly, you can think of a photograph as a superimposition of an infinite number of "glanced" images.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Realizing this, I became interested in how to make photos more focally realistic.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Enter Stereoscopic Photography</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">At a high level, my idea is simple: for each pixel in a given image, blur it in proportion to its 3D distance from a given focal point. Since conventional photography produces an insufficient 2D result, I turned to stereoscopic photography which produces pseudo-3D images.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Stereoscopic photography is based on "stereo pairs", a set of two 2D images taken at the same time with a small offset between the lenses, in position and sometimes angle. This is essentially the same process at work in human eyes. This is usually achieved by synchronizing two identical cameras, using a purpose-built stereo camera, or less commonly by using mirrors to split a single lens into two sub-lenses. In the absence of special equipment, a crude method involves moving left-right slightly between taking two photos with a single ordinary camera. For the purpose of this article, I'll sidestep the hardware aspect and demonstrate with existing stereo pairs.</span><br />
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Depth Mapping</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Stereoscopic depth mapping is the process of matching every pixel in the left image to its displaced position in the right image, and vice versa, to determine its distance from the lens. This provides a third spatial dimension to the image, conventionally called Z. While simple in theory, the practice is complex for several reasons:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Occlusions, or regions seen by one lens but not the other</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Lens axial misalignment </span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Differences in incident light between lenses</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Inexactness of pixel matching</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This technique also has subject limitations where pixels are not readily matched 1:1 between left/right images, such as surfaces that are featureless (clear blue sky), noisy (sand), reflective, or clear.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Rather than re-invent the wheel, I decided to use existing depth mapping software: <a href="http://3dstereophoto.blogspot.com/2016/02/epipolar-rectification-9b-er9b.html">Epipolar Rectification 9b (ER9b)</a> and <a href="http://3dstereophoto.blogspot.com/2014/05/depth-map-automatic-generator-5-dmag5.html">Depth Map Automatic Generator 5 (DMAG5)</a> courtesy of developer Ugo Capeto. Both are implementations of academic papers, dated 2008 and 2012. I wrote wrappers to use both within MATLAB.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ER9b performs sparse, high-confidence pixel matching to transform both images so that all matches occur along horizontal lines, thereby eliminating angular misalignment between lenses. In other words, the images are rectified to simulate idealized coplanarity of the lens axes. This is a prerequisite for effective depth mapping, as lens axial coplanarity is a key assumption in efficient depth mapping algorithms.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbz4ASl2_yD9WRG7guQIQ_eLMaXAAZu7KYrNXIVYj_9B4NkvbhbL3IAyOD5JLBjuMKeWDXir4l-PKl7loKb6VYVxQiPDqgOh9cp9ZKLMoJ0wx0agit-OloAKg2k0qapr_MnH63AF3nNIzI/s1600/good_match1_good_match2_compr.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="524" data-original-width="512" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbz4ASl2_yD9WRG7guQIQ_eLMaXAAZu7KYrNXIVYj_9B4NkvbhbL3IAyOD5JLBjuMKeWDXir4l-PKl7loKb6VYVxQiPDqgOh9cp9ZKLMoJ0wx0agit-OloAKg2k0qapr_MnH63AF3nNIzI/s1600/good_match1_good_match2_compr.GIF" /></a></div>
</div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Animation showing sparse high-confidence pixel matches; minimal rectification is necessary</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">DMAG5 takes as input a rectified stereo pair. It performs dense pixel matching, finds occlusions, and attempts to produce a physically realistic depth map for each image. Whereas ER9b requires no input parameters beyond the images themselves, DMAG5 requires roughly a dozen different parameters. These are fairly esoteric and in practice most can be left at their default values without affecting the result significantly. What is critical, however, is that the minimum and maximum disparity values (an output of ER9b) match the result of the rectification step, so that the depth map is correctly scaled. In practice, I've found that iteratively doubling/halving each parameter, keeping the helpful adjustments and reverting the unhelpful ones, is a decent if inelegant optimization method - a sort of poor man's gradient ascent method. This black-box approach is improved by making use of the built-in downsampling functionality to quickly evaluate parameters sets at low resolution before investing the computational time for the full resolution.</span></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiyoqTvSQFVtOyIk_A5NIsZlgZXG9ze32y4IoF4bqpi-Djj40O9FM90A_M0dEhNOmpLE1pmdbfiyTTQBzSfSsbezFrV0h0lOYtrf5qMF6j8c0KMpnG46hLHCwWHZ8mco6o4J_dMQkkSphc/s1600/pigeons_ER_dps_L.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="524" data-original-width="512" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiyoqTvSQFVtOyIk_A5NIsZlgZXG9ze32y4IoF4bqpi-Djj40O9FM90A_M0dEhNOmpLE1pmdbfiyTTQBzSfSsbezFrV0h0lOYtrf5qMF6j8c0KMpnG46hLHCwWHZ8mco6o4J_dMQkkSphc/s1600/pigeons_ER_dps_L.png" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Depth map for left image</span></div>
<div style="text-align: center;">
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
</div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Dither Upsampling</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">At this stage, a shortcoming of stereoscopic depth mapping emerges: its low resolution. Typical disparity ranges are between 20 and 70 pixels, roughly analogous to 5- or 6-bit color, which compares unfavorably to standard 8-bit color. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As a result, stereoscopic depth maps often show a "stairstep" effect where smooth transitions artificially show as jagged, similar in appearance to lines of constant elevation on topographical maps.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">It would be easy to increase the disparity range in hardware, but only at the cost of increasing the size of occluded regions. In practice, this doesn't seem to be feasible. I found Floyd-Steinberg dither upsampling to be an effective strategy to counteract the low-resolution artifacts, albeit at the cost of adding noise. However, this step was slow and turned out to not be necessary for my purposes, so I discarded it.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBM00w-pMfc2szo1psXOdUV2KWfi5-mkEoVlcAftzQj-bNYu1dN0JyOGFqecy2XtOkXJvt97zz9okO6dGgYiy-lsi6TpxEkvRhKrVqQYLMtZyshhDll-I6w0x-MR6AVMBRqHWxjqG3Xml4/s1600/dithering_comparison.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="784" data-original-width="1187" height="422" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBM00w-pMfc2szo1psXOdUV2KWfi5-mkEoVlcAftzQj-bNYu1dN0JyOGFqecy2XtOkXJvt97zz9okO6dGgYiy-lsi6TpxEkvRhKrVqQYLMtZyshhDll-I6w0x-MR6AVMBRqHWxjqG3Xml4/s640/dithering_comparison.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Comparison of depth map before/after dither upsampling</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Note that the dithered depth map appears noisier but smoother, and per the histograms more fully utilizes the available range of values in 8-bit color space.</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Blurring</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The last ste</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">p is blurring the image. Several inputs are required here:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Focal point - where the eyes are focused</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Depth-to-planar spatial ratio - how shallow or deep the image is</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Minim</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">um and maximum blur radius - how pronounced the blurring effect is</span></li>
</ul>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With these inputs defined, I measure the 3D distance from each pixel to the focal point, and map this linearly to the blur radius range. This results in a "radius map" which specifies the blur radius for each pixel. The stairsteps result from my simplifying assumption to only support whole-number blur radii, thereby obviating the need for sub-pixel calculations.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEYCgcUYw9VvGwtiO4xlcjZjUamH5W1R6zjgcHaiUwRa0xNLf4zIEJyicPPgcS-zMhhhF-755Ll0qsyZFT-T5sfkgqjF1irZsZJgYvfdoyeZ9d90_fntha_DemF6_JsjGBUUvB6E-zR1-t/s1600/pigeons_ER_L_radmap_downsampling_1_FP_57_x_77_DW_ratio_1_rad_min_0_rad_max_20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="524" data-original-width="512" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEYCgcUYw9VvGwtiO4xlcjZjUamH5W1R6zjgcHaiUwRa0xNLf4zIEJyicPPgcS-zMhhhF-755Ll0qsyZFT-T5sfkgqjF1irZsZJgYvfdoyeZ9d90_fntha_DemF6_JsjGBUUvB6E-zR1-t/s1600/pigeons_ER_L_radmap_downsampling_1_FP_57_x_77_DW_ratio_1_rad_min_0_rad_max_20.png" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Blur radius map with eyes focused on foreground facial features</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I initially default</span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ed to a Gaussian blur, but this didn't produce good results as the stairstep effect from the depth and radius maps persisted in the resulting image.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Instead, I used a median blur. Instead of setting each pixel's value as a normally-weighted average of its neighbors, the median blur sets each pixel's value as the unweighted median of its radial neighborhood. The median blur preserves edges, which is extremely beneficial in hiding the stairstep effect and smoothly transitioning between varying blur radii. Subjectively, the image also feels to be more similar to one seen out of the corner of one's eye, whereas a Gaussian blur feels more camera-like. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I used a circular neighborhood as it produced the best results, though square and diamond neighborhoods also exist.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Unlike typical fixed-size median filters, mine requires the radius to vary as a function of its position; instead of one kernel, there are many. For efficiency, I pre-calculate all the kernels necessary before starting the blur calculation, and recall them as needed. This is about 3x faster than generating a kernel from scratch at each pixel.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here are some sample result images, showing how the focal point can be moved to simulate looking at different parts of the scene. Note how the blur radius transitions seamlessly both within <i>and</i> between focal planes!</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4ckvzG76gzogOTyCAH4Bp6uCmw4yg_LFBvkbPzf1V2CSJYJsHhYlSyzjtTU8QjqXboaU206muO5-RZmz3KtIb-1pZucjB-fVRH2G4J-YGP1AAd5zIvWxyxxfWIiKBO-MNguRUaSGqRaBX/s1600/pigeons_ER_L_output_downsampling_1_FP_57_x_77_DW_ratio_1_rad_min_0_rad_max_15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="519" data-original-width="507" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4ckvzG76gzogOTyCAH4Bp6uCmw4yg_LFBvkbPzf1V2CSJYJsHhYlSyzjtTU8QjqXboaU206muO5-RZmz3KtIb-1pZucjB-fVRH2G4J-YGP1AAd5zIvWxyxxfWIiKBO-MNguRUaSGqRaBX/s1600/pigeons_ER_L_output_downsampling_1_FP_57_x_77_DW_ratio_1_rad_min_0_rad_max_15.png" /></a></div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX2ghpgBngNqyLboANS-VINrL6fIu8UZLAJk_difloChCA2p3zO8fPJCGrrWLOMQ2XAdnmGOIkvyaipeZiaOLaBbDqoQhKnJGFnDbazeuA-L2pkjoPRmdxGj0yKKxX6HPWj9B8mjBQyVVM/s1600/pigeons_ER_L_output_downsampling_1_FP_17_x_69_DW_ratio_1_rad_min_0_rad_max_15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="519" data-original-width="507" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhX2ghpgBngNqyLboANS-VINrL6fIu8UZLAJk_difloChCA2p3zO8fPJCGrrWLOMQ2XAdnmGOIkvyaipeZiaOLaBbDqoQhKnJGFnDbazeuA-L2pkjoPRmdxGj0yKKxX6HPWj9B8mjBQyVVM/s1600/pigeons_ER_L_output_downsampling_1_FP_17_x_69_DW_ratio_1_rad_min_0_rad_max_15.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIVX7IG1eExoohvWM6gsm9yq9H-WSZaN9GqtdnVmaj6riNSlaAiXpa6-ytTHzD12-efycLEUXHSdyBxRsFt8S-2gEWpwUZXupl_Vt8XWwQRZZpzOV_5CyL8rt6NGsJ6_BgW_2pp_ifkAhP/s1600/pigeons_ER_L_output_downsampling_1_FP_44_x_45_DW_ratio_1_rad_min_0_rad_max_15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="519" data-original-width="507" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIVX7IG1eExoohvWM6gsm9yq9H-WSZaN9GqtdnVmaj6riNSlaAiXpa6-ytTHzD12-efycLEUXHSdyBxRsFt8S-2gEWpwUZXupl_Vt8XWwQRZZpzOV_5CyL8rt6NGsJ6_BgW_2pp_ifkAhP/s1600/pigeons_ER_L_output_downsampling_1_FP_44_x_45_DW_ratio_1_rad_min_0_rad_max_15.png" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Demo Gallery</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Shown here are several additional images created using the process outlined above, to further demonstrate the effect. These represent "good" results; some images work better than others for a variety of reasons.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNENdUElvtkKen2QJ2hzP78a4H6n2A-2P_MdX0h2D0qaZndu1w43jdH8WlsZ_eJ7IiPk8itCr1SsEN61FQB31SHNw2RaQNmy3zX0CH2ieTwukMCKPZH74ZCAolP2LiPaz4WluRbHKkYwOP/s1600/plants_ER_L_compr_downsampling_1_FP_48_x_55_DW_ratio_1_rad_min_0_rad_max_25.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="722" data-original-width="1288" height="354" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNENdUElvtkKen2QJ2hzP78a4H6n2A-2P_MdX0h2D0qaZndu1w43jdH8WlsZ_eJ7IiPk8itCr1SsEN61FQB31SHNw2RaQNmy3zX0CH2ieTwukMCKPZH74ZCAolP2LiPaz4WluRbHKkYwOP/s640/plants_ER_L_compr_downsampling_1_FP_48_x_55_DW_ratio_1_rad_min_0_rad_max_25.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjmt9zxVKmOJL-cYHXlt1XTcSG7Ep4cEyYHyojEhUoI5mBEGPoZzXhfYDDRVWOqZJjCvoCFIv4RePfz8MjzZLNJmHFo2daYYlWelsY-u4xRERXKMhaOWPTru1jSovTzAZkbBX3A3NDu6qg/s1600/riverbank_ER_L_compr_downsampling_1_FP_27_x_61_DW_ratio_1_rad_min_0_rad_max_25.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="556" data-original-width="1600" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjmt9zxVKmOJL-cYHXlt1XTcSG7Ep4cEyYHyojEhUoI5mBEGPoZzXhfYDDRVWOqZJjCvoCFIv4RePfz8MjzZLNJmHFo2daYYlWelsY-u4xRERXKMhaOWPTru1jSovTzAZkbBX3A3NDu6qg/s640/riverbank_ER_L_compr_downsampling_1_FP_27_x_61_DW_ratio_1_rad_min_0_rad_max_25.png" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPftA6rXhgkonasjsrvQeiEvqkQ8ASl48DoMqjGvaXmuRvNFCraH3IXLqj5iDmt59Qwl3EnA7qGUWkywyiSxKSQKLbtfccKqLedVkikcLIVW7UpK8VyYeCHX-gUer1gaW22O8nNluXHjqZ/s1600/biker_ER_L_compr_downsampling_1_FP_49_x_78_DW_ratio_1_rad_min_0_rad_max_12.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="439" data-original-width="1004" height="274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPftA6rXhgkonasjsrvQeiEvqkQ8ASl48DoMqjGvaXmuRvNFCraH3IXLqj5iDmt59Qwl3EnA7qGUWkywyiSxKSQKLbtfccKqLedVkikcLIVW7UpK8VyYeCHX-gUer1gaW22O8nNluXHjqZ/s640/biker_ER_L_compr_downsampling_1_FP_49_x_78_DW_ratio_1_rad_min_0_rad_max_12.png" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhINxkelTHso0qSir8KrShFvdK9niPOJ9h6OYECHrJYQlAFx6937E0qn_nbYhWd0mFfAIRlBglDssGo8TJSbBwhr0HlWxSuvrCveDwLFuOPOaa-0eEwJdvnifYSBjKSCKV_6CUN92y8naxC/s1600/horses_ER_L_compr_downsampling_1_FP_71_x_82_DW_ratio_1_rad_min_0_rad_max_25.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="430" data-original-width="1600" height="170" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhINxkelTHso0qSir8KrShFvdK9niPOJ9h6OYECHrJYQlAFx6937E0qn_nbYhWd0mFfAIRlBglDssGo8TJSbBwhr0HlWxSuvrCveDwLFuOPOaa-0eEwJdvnifYSBjKSCKV_6CUN92y8naxC/s640/horses_ER_L_compr_downsampling_1_FP_71_x_82_DW_ratio_1_rad_min_0_rad_max_25.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgPWfPQyN5aCg5fxgDk3ltBSSfYJxi1_cDYTHa9JINUlgANnsYPbscbIVcwgRM70CXmAeStM5hUWpR2r3QZRZZth44M4Wt-_rk-TxaFjR21qDjqXKcT66CShJrhhhKwSXLdcLGqyKjMUkR/s1600/yacht_ER_L_compr_downsampling_1_FP_45_x_20_DW_ratio_1_rad_min_0_rad_max_25.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1016" height="450" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgPWfPQyN5aCg5fxgDk3ltBSSfYJxi1_cDYTHa9JINUlgANnsYPbscbIVcwgRM70CXmAeStM5hUWpR2r3QZRZZth44M4Wt-_rk-TxaFjR21qDjqXKcT66CShJrhhhKwSXLdcLGqyKjMUkR/s640/yacht_ER_L_compr_downsampling_1_FP_45_x_20_DW_ratio_1_rad_min_0_rad_max_25.png" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Depth Map Gallery</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Shown here are the depth maps corresponding to the images above.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjp5qKPRjDoepfqnb-21S26lJ0_bkb5Gl0Tyr7tGYsv76fAdmGnzpCyzoE1fEcOtUEbcEnzXDC9Jq3ACxrADG8fJ4vmuAK0a-oCFq-UmYhIOjHuzJ60330JHoXBNYIAmm-qILrSUsjp0D2o/s1600/plants_ER_dps_L.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="722" data-original-width="639" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjp5qKPRjDoepfqnb-21S26lJ0_bkb5Gl0Tyr7tGYsv76fAdmGnzpCyzoE1fEcOtUEbcEnzXDC9Jq3ACxrADG8fJ4vmuAK0a-oCFq-UmYhIOjHuzJ60330JHoXBNYIAmm-qILrSUsjp0D2o/s640/plants_ER_dps_L.png" width="565" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgT6rHbfBtW-NA2KOxLsUobvWbN4FsH8MYCfP1GvoGhf5W92aR8GilVMJMAa48UZvlkO3RyMhI9_RIOwUL4O6z7iYkA00lxdD0AfCxdSiuY-Bl6N1iixZHpl0_K2XWTDtfMUMiWZbu7zXS/s1600/riverbank_ER_dps_L.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="680" data-original-width="974" height="446" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgT6rHbfBtW-NA2KOxLsUobvWbN4FsH8MYCfP1GvoGhf5W92aR8GilVMJMAa48UZvlkO3RyMhI9_RIOwUL4O6z7iYkA00lxdD0AfCxdSiuY-Bl6N1iixZHpl0_K2XWTDtfMUMiWZbu7zXS/s640/riverbank_ER_dps_L.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi356gH-VEmmGr8F5nBXsy8QYWf5QAX7oapIJWMhCj3oNWKyAqH2DQpQQ6t59RsL-xAHvnqS4fPAlmSMEPH5xysIxMBQmbSmjMxtOBCtuljJcUxoeZxiV8lMh1veo6ORmsqT2lxqKUn6ezA/s1600/biker_ER_dps_L.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="439" data-original-width="497" height="564" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi356gH-VEmmGr8F5nBXsy8QYWf5QAX7oapIJWMhCj3oNWKyAqH2DQpQQ6t59RsL-xAHvnqS4fPAlmSMEPH5xysIxMBQmbSmjMxtOBCtuljJcUxoeZxiV8lMh1veo6ORmsqT2lxqKUn6ezA/s640/biker_ER_dps_L.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnsR3Wx5NZaBakqt54KixToRUxx0V27qdFZVPPCcwoeQ4SvkvfehV7YWnhOYgzDca40OIqAmbOqADprXAbWaQir7NxXcbkw6jLdzTGVhfX38mv7YxWhJn7t2bAWYBCAmih6imPI4FusxCc/s1600/horses_ER_dps_L.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="500" data-original-width="927" height="344" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnsR3Wx5NZaBakqt54KixToRUxx0V27qdFZVPPCcwoeQ4SvkvfehV7YWnhOYgzDca40OIqAmbOqADprXAbWaQir7NxXcbkw6jLdzTGVhfX38mv7YxWhJn7t2bAWYBCAmih6imPI4FusxCc/s640/horses_ER_dps_L.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbPSeXcIxa9GxgIFRll714vBhWqTxdSOT_NKf__1_uexdsiDZRCwwxEI9ioeIYp_mWXhsRTcm05OAzikYx8Ptfme6_r_szmE-725bJr3h3iPOXaQrl7wxlVinHmWHP8m-n3cMyctStxzpp/s1600/yacht_ER_dps_L.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="503" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbPSeXcIxa9GxgIFRll714vBhWqTxdSOT_NKf__1_uexdsiDZRCwwxEI9ioeIYp_mWXhsRTcm05OAzikYx8Ptfme6_r_szmE-725bJr3h3iPOXaQrl7wxlVinHmWHP8m-n3cMyctStxzpp/s640/yacht_ER_dps_L.png" width="446" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Acknowledgements</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="http://3dstereophoto.blogspot.com/">Ugo Capeto</a> develops and maintains excellent free depth-mapping software</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://www.flickr.com/photos/3dshoot/">3D Shoot</a> provided most of these stereoscopic images under a non-commercial license</span></li>
</ul>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Source Code</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "times new roman";"><br /></span></span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Freely available on <a href="https://github.com/kindofdoon/3D-Focal-Point-Median-Blur">my GitHub</a>.</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-25030245063469569102019-11-24T12:36:00.000-08:002019-11-25T06:58:30.191-08:00Authorship of "A Warning"<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2018's Anonymous, author of the infamous op-ed titled <a href="https://www.nytimes.com/2018/09/05/opinion/trump-white-house-anonymous-resistance.html"><i>I Am Part of the Resistance Inside the Trump Administration</i></a>, is back. Their latest publication is <i><a href="https://www.amazon.com/Warning/dp/1538718464/">A Warning</a></i>, a full-length book which builds on similar themes at much greater length. I previously attempted to deduce the author of the anonymous op-ed with forensic linguistics - see <a href="http://www.kindofdoon.com/2018/11/authorship-of-nyt-resistance-op-ed.html">here</a> and <a href="http://www.kindofdoon.com/2018/12/nyt-resistance-op-ed-part-2.html">here</a>. In this post, I'll revisit this analysis using the new information provided by <i>A Warning</i>. I'll also delve deeper into motive, means, timeline, and other signals. My interest in the authorship question is not political, but rather motivated by the challenge of trying to crack this topical, high-profile puzzle.</span><br />
<br />
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Text Similarity</b></span></div>
<div>
<br /></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The codebase I developed for <i>Resistance</i> estimates the authorship probabilities for a set of candidates by comparing attributable writing samples with target text of unknown origin. For each author, a matrix is developed representing <a href="https://en.wikipedia.org/wiki/Stochastic_matrix">Markov</a> word transition probabilities, as well as a vector distribution representing their overall word choice. These are then compared against the same elements for target text. This code is freely available on <a href="https://github.com/kindofdoon/nyt_resistance_op_ed">my GitHub</a>. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Re-running this code, substituting </span><i style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">Warning </i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">for </span><i style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">Resistance</i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">, produces this result.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ckyLEPKDxJdrfOmi1WLwLGxoc1Q5pEoLOoP0gbTeHXBOWI97IFltQxY_e4Cl2gppHs5J070v5zH-MU0s-GROln8Xs5jf7QJARLSJKj9av6ZBya99YQBbjysMP42tgrzPY5hfGUceCeOB/s1600/authorship_a_warning.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="733" data-original-width="689" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0ckyLEPKDxJdrfOmi1WLwLGxoc1Q5pEoLOoP0gbTeHXBOWI97IFltQxY_e4Cl2gppHs5J070v5zH-MU0s-GROln8Xs5jf7QJARLSJKj9av6ZBya99YQBbjysMP42tgrzPY5hfGUceCeOB/s1600/authorship_a_warning.png" /></a></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This result is consistent with the same plot for <i>Resistance</i>. In the Top 10, McMahon and Mnuchin replace Pompeo and Kushner; otherwise the set is unchanged.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifeoU4I9NQISqwOfu50QpheAq8SbsPQtuNRa-BkO7-UJ061uJT67xFcALLMSWg7w_iW98ASeoQpcdDIpCIq4tt8XjqqggVxHf3U66_0ACBc8Y1mgk84GDl-nQjmVNqMqUHXeLkmfp-jfKK/s1600/top_suspects_comparison.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="257" data-original-width="253" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifeoU4I9NQISqwOfu50QpheAq8SbsPQtuNRa-BkO7-UJ061uJT67xFcALLMSWg7w_iW98ASeoQpcdDIpCIq4tt8XjqqggVxHf3U66_0ACBc8Y1mgk84GDl-nQjmVNqMqUHXeLkmfp-jfKK/s1600/top_suspects_comparison.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Subjects</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I haven't read the book, but as a first approximation I extracted all its proper noun phrases and the number of their occurrences. I didn't find this initial result very informative but am including it for general interest.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXqUGwu8BmCA1hh6Zboggl5rWO8q-4uYs0GikvYNeKFYmc-o6r2QYS23S1B27oFCb2LyMSA4IvUZWfV_vnIIQyjP0_cP0No7uo3J9DCjFeGgi3iez4aw07SwL-6O852OaplKmMDURyR2_D/s1600/proper_nouns.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="935" data-original-width="657" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXqUGwu8BmCA1hh6Zboggl5rWO8q-4uYs0GikvYNeKFYmc-o6r2QYS23S1B27oFCb2LyMSA4IvUZWfV_vnIIQyjP0_cP0No7uo3J9DCjFeGgi3iez4aw07SwL-6O852OaplKmMDURyR2_D/s1600/proper_nouns.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Network Similarity</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I started by filtering the subjects to only include administration officials, looking for an indication of the author's position within the administration by proxy of who they discuss, and how often.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilRnWE0Hft9-M__VR1lfXSFGYsSKB59mINDUkoUqLyoDHjHddRF8pVv6pidMipG4Moux41E-aBmW5mPCWtiizXUjFULJwQ1-RXiOtuVzkWUoOrSYB3vcOwDepxwQbHeudXP0IqRJWprWeY/s1600/admin_officials.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="530" data-original-width="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilRnWE0Hft9-M__VR1lfXSFGYsSKB59mINDUkoUqLyoDHjHddRF8pVv6pidMipG4Moux41E-aBmW5mPCWtiizXUjFULJwQ1-RXiOtuVzkWUoOrSYB3vcOwDepxwQbHeudXP0IqRJWprWeY/s1600/admin_officials.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The top officials mentioned cover a wide swath of the administration, including policy, operations, economics, defense, diplomacy, and more. Presumably, the author wrote about these officials roughly in proportion to the quantity of their real-life interactions.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">To quantify this, I created a matrix gauging how likely certain officials are to have worked together. This enables a "network similarity" metric. To manage scope, I proceeded only with the top ten candidates from the text similarity metric. For completeness I added Bremberg, DeStefano, Stepien, and Ayers to the set, who lack published writing but have been <a href="https://www.businessinsider.com/all-clues-for-identity-anonymous-trump-official-a-warning-author-2019-11">recently suggested</a> as possible authors.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwriubpH8Z1LnAevAR4tTIROjWp0TLcI8m1yJzT11bx6M6c8KPYRawzxAGSWrEFyEt3Lw1TiMfIeOSX6VIgKyKCQD7-3yLMHhhbDNf7cYIjpkRwDpVE5Zm5IOHVvcInPpminhf6yr1BWsK/s1600/network_similarity.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="867" data-original-width="1025" height="540" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwriubpH8Z1LnAevAR4tTIROjWp0TLcI8m1yJzT11bx6M6c8KPYRawzxAGSWrEFyEt3Lw1TiMfIeOSX6VIgKyKCQD7-3yLMHhhbDNf7cYIjpkRwDpVE5Zm5IOHVvcInPpminhf6yr1BWsK/s640/network_similarity.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Pence emerges as the clear frontrunner from this metric, with the caveat that he is also higher in the hierarchy, so more likely to be connected to any given senior official.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Academic Background</span></b></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I then filtered by historical figures mentioned in the text, looking to probe the author's academic background.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiClrJoM7cQQ8qxuzaszRPU09Pglxg3Kq7OtN-YR8DH5bv5fy4cY1cAxnhKdaNdFGYRSA0enSV6TSVBfJ7_-0wARmZ_mjJ9J0TpxS3sGKR9jnRXKSqqdXqBGKvBkdq_yFmGMBQZWGgvIKJc/s1600/historical_figures.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="572" data-original-width="298" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiClrJoM7cQQ8qxuzaszRPU09Pglxg3Kq7OtN-YR8DH5bv5fy4cY1cAxnhKdaNdFGYRSA0enSV6TSVBfJ7_-0wARmZ_mjJ9J0TpxS3sGKR9jnRXKSqqdXqBGKvBkdq_yFmGMBQZWGgvIKJc/s1600/historical_figures.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">There is a cluster of notable outliers: Cicero, Cleon, Aristotle, and Diodotus, all political/philosophical figures from Ancient Greece and Rome. These esoteric figures suggest a classical academic background, perhaps including political science, history, and/or law.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Motive</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The book's purpose seems to be strengthening the case for impeachment and/or discouraging the 2020 re-election effort. Presumably, the author is to some extent self-interested, and would not advance these goals if they conflicted with their personal advancement. This suggests the author is not part of the president's inner circle and/or has already left office.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Warning</i>, like <i>Resistance</i>,<i> </i>has a strong moralistic tone, which suggests it was not authored by an anti-environmentalist (Wheeler, Perry), investment banker (Mnuchin), entertainment executive (McMahon), or political director (Stepien).</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Timeline</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Sources disagree as to whether the author is still active within the administration. As far as I know, this isn't directly addressed in the book. However, its many dated accounts, specifically from 2015 through 2019, suggest a surprisingly clear timeline. Most of book's accounts are retellings of publicly available new stories; others more usefully contain private information which, if true, would only be known to an insider. As examples:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><a href="https://www.theguardian.com/us-news/2018/jul/15/donald-trump-vladimir-putin-helsinki-russia-indictments">Public</a>:</i> "In a July 2018 interview, the president was asked to name America’s biggest global adversary."</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Private: </i>"Several departure timelines appeared to be converging in 2018, creating the possibility for a simultaneous walkout to prove our point about the president’s faltering administration."</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipdOyLtQr45cOx1EeJCOxsOiFpCnGe0LCXAtKEV7T0ox0Q4yOtphSUIg3pJ32oNUZsvYyWc04tVbefLjAIbEMiELiV-JAWROwGGICTPhq5KTCjJ9b0F5sx0Op7bXVTlCBy-sBQthqUhIJ-/s1600/implied_timeline.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="466" data-original-width="587" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipdOyLtQr45cOx1EeJCOxsOiFpCnGe0LCXAtKEV7T0ox0Q4yOtphSUIg3pJ32oNUZsvYyWc04tVbefLjAIbEMiELiV-JAWROwGGICTPhq5KTCjJ9b0F5sx0Op7bXVTlCBy-sBQthqUhIJ-/s1600/implied_timeline.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Charting the fraction of private dated accounts by year suggests that the author is no longer with the administration, as the latest private account they provide is dated 2018. This suggests a departure date of late 2018 to early 2019. Moreover, they also provide a significant number of private accounts from 2016 which are pre-inauguration, suggesting that the author worked on the transition team and possibly the campaign team as well.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Children</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The book opens with a dedication "[to] my children, and the forthcoming generation", implying that the author has at least two children. This suggests ruling out Hill and Bolton, who have one child each. The author says that they may eventually disclose their identity:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"Nor am I unprepared to attach my name to criticism...I may do so, in due course."</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I concluded that an author so apparently concerned with principled righteousness would not misrepresent the number of their children, for the sake of their posterity and pride.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Signal Synthesis</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">To synthesize these various signals, I counted the quantity of affirmative signals from each candidate.</span></div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk_AK6EjsUHo6xPjXojHQeDTSdHyyJjxNwI3XzNn39PMX96eo_xbWu5iH9tlEmMLhQVnwzvnTLSl0btST5OhzfIsIIiRSNrP6rQQV5zlZ1OB7tLql2rmsgJhkMMiFDqXDe1w1vjRYDmlI0/s1600/results_summary.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="597" data-original-width="1316" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk_AK6EjsUHo6xPjXojHQeDTSdHyyJjxNwI3XzNn39PMX96eo_xbWu5iH9tlEmMLhQVnwzvnTLSl0btST5OhzfIsIIiRSNrP6rQQV5zlZ1OB7tLql2rmsgJhkMMiFDqXDe1w1vjRYDmlI0/s640/results_summary.png" width="640" /></a></div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Topping the list is Ayers, Chief of Staff to the Vice President. Every signal points to his authorship, except text similarity which couldn't be evaluated due to a lack of publications. Notably, he's the only candidate to fit both timeline criteria. Circumstantially, the case is strong if incomplete.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">One tier lower is </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Pence. He stands to lose the most if the 2020 re-election effort is defeated, yet benefit the most if impeachment succeeds. </span><i style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Warning </i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">may be a high-risk/high-reward push to capture the presidency at the risk of losing the vice presidency. This Machiavellian strategy is very difficult to square with Pence's reputation for being straightforward and loyal. Further, he is still in office, which is incompatible with the departure date implied by the private accounts. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For these reasons, I consider Pence a false positive, and unlikely.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">One tier lower still are Hill, Bolton, and Sullivan. The first two are weak candidates as their timelines don't match the timeline implied by the private accounts. Further, they both have only a single child. Sullivan has three children, which fits, but lower text similarity, ranked near the bottom of frontrunners. I consider these candidates to be unlikely.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Continuing down the list, the remaining candidates have progressively more discrepancies, making them less likely still.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Conclusion</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Nick Ayers is the most likely candidate for the "Anonymous" behind both <i>Resistance</i> and <i>Warning</i>.</span></div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-22986198978116090212019-11-18T19:40:00.000-08:002019-11-22T07:27:36.413-08:00Histogram Diffusion Image Filter<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Summary</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">An overview of an experimental image processing algorithm that uses 1D heat diffusion and exact histogram matching </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">to augment the chromatic realism (i.e. the perceived color accuracy) of an RGB photo.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Background</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A dream of mine since childhood has been a camera that can capture the exact image seen by one's eyes. No such device yet exists, but this dream explains my interest in painting that developed later in life. It's my belief that painting has persisted in the modern world because it retains an essential advantage over photography: it is the superior medium for accurately representing images seen by eye - in other words, the human visual experience.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Photography has its place too, but its images are cheap and inhuman. Although it invariably captures forms with perfect accuracy, it is clumsy and narrow with hue, saturation, and value, the essential ingredients for describing color. Compounding this is its unnatural way of focusing on a plane, instead of a point as eyes do. In other words, a photo is like a superimposition of an infinite set of eye-images, each focused on a different point on the same focal plane. Photos are great for quickly capturing appearances, but not <i>how it feels to see</i>. Here, painting at its best is unsurpassed.</span></div>
<div>
<br /></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Despite the shortcomings of photography, it remains a powerful and useful tool for artists. An interest of mine is how photography can be used as a basis for painting, and how various technical approaches can be used to mitigate its shortcomings. In this article, I'll describe an image filter that may be useful for augmenting the chromatic realism of a reference image.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Hypothesis</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Over a series of walks through the local fall foliage recently, I was thinking about cognitive aspects of color perception. It stands to reason that the human eye is good at differentiating objects by subtle differences in color, as these were useful skills in improving the evolutionary fitness of our ancestors. The human eye has a limited bandwidth in terms of the wavelengths that it can perceive - roughly 350 to 850 nm. I reasoned that in general, an image would be maximally differentiable if these wavelengths were represented equally - in other words, if a histogram describing the frequencies of visible light was flat.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://en.wikipedia.org/wiki/Histogram_equalization">Histogram equalization</a> achieves this ideal of a flat histogram and maximum differentiability, but at the cost of realism. The problem is that most scenes don't actually have a flat histogram, so enforcing one causes unrealistic and harsh shifts in color.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJoD6Fl-YV_s2jGrQPj-pgNSiNlcylx9sSGtvtqQVFA_MaDO7qKzizZDeTt_Dc63e7LynDWK_VuMcWW0E1JHhZMRC9uy4SebELZEzwjKNl-yri4ZZXIaSlkPS8U5LKXxehNZI2ND9U01vF/s1600/_IMG_3202_naive.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJoD6Fl-YV_s2jGrQPj-pgNSiNlcylx9sSGtvtqQVFA_MaDO7qKzizZDeTt_Dc63e7LynDWK_VuMcWW0E1JHhZMRC9uy4SebELZEzwjKNl-yri4ZZXIaSlkPS8U5LKXxehNZI2ND9U01vF/s640/_IMG_3202_naive.JPG" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAPsZ8qztng-5gpQJWJrhXzls8ra2w0WG02cGe7lk88W8eVle_0yrHmp4wt7Hi2RBJNNog4Ikwv1QAd5gRlpDWpAkAJvfB-U-bVm9vvY7BLTWDtTGDLC4itzTv9BWubHHCInLEkguNnltu/s1600/IMG_4328_naive.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1067" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAPsZ8qztng-5gpQJWJrhXzls8ra2w0WG02cGe7lk88W8eVle_0yrHmp4wt7Hi2RBJNNog4Ikwv1QAd5gRlpDWpAkAJvfB-U-bVm9vvY7BLTWDtTGDLC4itzTv9BWubHHCInLEkguNnltu/s640/IMG_4328_naive.JPG" width="426" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Examples of "naive" histogram equalization applied independently to images' R, G, B channels</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I concluded that a flat histogram has "too much" differentiability, while a raw histogram has "too little", with neither feeling quite realistic. I wondered if some intermediate histogram would offer an ideal balance between the two extremes, and realized that 1D diffusion, as if by the heat equation, offered a solution for continuously interpolating between these extremes. This is because the steady-state solution for 1D diffusion is a flat line, while its initial condition may be any arbitrary vector of values. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The hypothesis then emerged:</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Diffusing an image's histogram, as if by the heat equation, can be used to augment its chromatic realism.</i></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Implementation</b></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The 1D heat equation states that the derivative of temperature with respect to time is proportional to its second derivative with respect to space, i.e. its curvature:</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYXj-SIycIlofx2xNFpxgAYm_M41kW6qWwVIcNAEaweT6j274rPrPmLjJpz6FlKxn8ldhIWsuwy5uFfOLQB7spKjCAKBcixSsu7ooz41dHWd8XyPBIo52GrCXRd_1w7gQMylKbmdO8jvlI/s1600/heat_equation.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="72" data-original-width="143" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYXj-SIycIlofx2xNFpxgAYm_M41kW6qWwVIcNAEaweT6j274rPrPmLjJpz6FlKxn8ldhIWsuwy5uFfOLQB7spKjCAKBcixSsu7ooz41dHWd8XyPBIo52GrCXRd_1w7gQMylKbmdO8jvlI/s1600/heat_equation.PNG" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br />For an initial condition of T, this can be solved easily using the <a href="https://en.wikipedia.org/wiki/Finite_difference_method">finite-difference method</a>. Applying this to images requires replacing temperature, T, with "level count", i.e. how often each value occurs within each channel. This step has no real dimensional basis, but is convenient and easy. Working in RGB color space, each channel can be operated on independently as if it was a grayscale image. T</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">hese arguments can also be generalized to alternate color spaces such as HSV.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Less trivial yet critically important is how boundary conditions are handled. The boundaries of an image's histogram represent its saturation points. It's best to avoid saturating an image when taking or editing a photo, as it causes a loss of information and an overall loss of realism. In the most severe cases, when all three channels are saturated, the resulting color is pure white or black, and no visual information is encoded. This commonly occurs as a result of over- or under-exposing an image. However, moderate saturation may be acceptable in some cases. I define "moderate saturation" as a channel's boundary values being 10% or less of its peak value.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">To permit diffusion while discouraging saturation, I enforce these constraints:</span></div>
<div style="text-align: left;">
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">If a boundary is ≤10% saturated, fix its value over time, i.e. set it as a <a href="https://en.wikipedia.org/wiki/Dirichlet_boundary_condition">Dirichlet boundary</a>.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">If a boundary is >10% saturated, insulate it so that it tends to drift downward over time, i.e. set it as a <a href="https://en.wikipedia.org/wiki/Neumann_boundary_condition">Neumann boundary</a>.</span></li>
</ul>
</div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">These constraints ensure, for typical images, that no additional saturation occurs as a result of the diffusion. The steady-state solutions of this equation with these boundary conditions are always straight lines, practically but not exactly flat, very much like canonical histogram equalization. In practice, best results are achieved well before reaching diffusive steady-state.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">To transform the image according to the diffused histograms, I used an existing </span><a href="https://www.mathworks.com/matlabcentral/fileexchange/26309-exact-histogram-equalization-and-specification" style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">exact histogram match algorithm</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">. This introduces a small amount of imperceptible noise to transition from a discrete-valued image to a continuously-valued image, which enables every pixel to be sorted in strictly ascending/descending order. The image can then be transformed so that it exactly produces the input histogram.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Results</b></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">All photos in this section were taken with my <a href="https://en.wikipedia.org/wiki/Canon_EOS_300D">2003 Canon Rebel</a>. No modifications were made prior to diffusing the histograms. The diffusion runtimes are equal between channels, but not between images - this was qualitatively fine-tuned by eye.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1XALGdyOIa33KQNp6vzIKeX9N3XdtR6eIICN_J9dLV4by7fdq6wxzwEZ39vVEiwImxQDxkBMB2Xcp_HQv99VSfRwq_-L6AI6JDY_5bH_sKlZQfWiFLqaZWXVRYCFS1mbAryzkKwIPFdHw/s1600/_IMG_2738_runtime_300_300_300_sat-thresh-prcnt_10_sample-spacing_4.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="650" data-original-width="650" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh1XALGdyOIa33KQNp6vzIKeX9N3XdtR6eIICN_J9dLV4by7fdq6wxzwEZ39vVEiwImxQDxkBMB2Xcp_HQv99VSfRwq_-L6AI6JDY_5bH_sKlZQfWiFLqaZWXVRYCFS1mbAryzkKwIPFdHw/s1600/_IMG_2738_runtime_300_300_300_sat-thresh-prcnt_10_sample-spacing_4.GIF" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilbTcNs4kLtW0TQynv_laiZ-SYJtYcBoyp_A-bxfElEUtcGTZVNNtRBIRp2lV7m3CUex8-x4caM_lST_eRvOb7XBWXTYIrgsDOzEDHznd4GxSkLs9h_VZCx9pS_X4ZSdb8dPNrOVNRCTZL/s1600/_IMG_2738_runtime_300_300_300_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEilbTcNs4kLtW0TQynv_laiZ-SYJtYcBoyp_A-bxfElEUtcGTZVNNtRBIRp2lV7m3CUex8-x4caM_lST_eRvOb7XBWXTYIrgsDOzEDHznd4GxSkLs9h_VZCx9pS_X4ZSdb8dPNrOVNRCTZL/s640/_IMG_2738_runtime_300_300_300_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This is a simple example to start with. The original's colors are very tightly clustered around a central value, so the histograms resemble bell curves and diffusion essentially amounts to a conventional horizontal scaling of the histogram.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXaVicjKW4IZsiyhs_Qj39nMThqTEh3dOHUOJF67GKRj8TmEuSaIbJzqQCfJIvL2C2j6qUXZagQ4ipiksb9FqE5yxxI1uzaVxcO1YolJt9l6OHAGHS5f_QBEmNZDlXcUlaJhpsgR5xQ-2/s1600/_IMG_3873_runtime_600_600_600_sat-thresh-prcnt_10_sample-spacing_4.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="650" data-original-width="650" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXXaVicjKW4IZsiyhs_Qj39nMThqTEh3dOHUOJF67GKRj8TmEuSaIbJzqQCfJIvL2C2j6qUXZagQ4ipiksb9FqE5yxxI1uzaVxcO1YolJt9l6OHAGHS5f_QBEmNZDlXcUlaJhpsgR5xQ-2/s1600/_IMG_3873_runtime_600_600_600_sat-thresh-prcnt_10_sample-spacing_4.GIF" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0UMR-41xhelZM9m8OLtpScezZ1rz-2gbIDqlRW-EBdjW8qsQSI6wx0kDbuBSrzvtscqHHx5YvNmtUXYuoo0HL__CMFnsQJqFKQoZUg8OXcnSrmqC5Rim5zhCkKacCoW5X6o1BxtJoB6-u/s1600/_IMG_3873_runtime_600_600_600_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0UMR-41xhelZM9m8OLtpScezZ1rz-2gbIDqlRW-EBdjW8qsQSI6wx0kDbuBSrzvtscqHHx5YvNmtUXYuoo0HL__CMFnsQJqFKQoZUg8OXcnSrmqC5Rim5zhCkKacCoW5X6o1BxtJoB6-u/s640/_IMG_3873_runtime_600_600_600_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In R (Red Channel) and G (Green Channel), fixing the left-hand boundary pushes the histogram to the right as it diffuses, brightening those channels and finding definition in the nearly-saturated shadows. In B (Blue Channel), the insulated left-hand boundary is allowed to drift downward, and the exact histogram matching algorithm injects noise, guessing at the actual values of these saturated pixels. This guesswork is well-hidden in the result, because B contributes almost nothing to a color's perceived value, i.e. its perceived brightness/darkness. This is due to a quirk of human vision which places disproportionate emphasis on the Green Channel.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAhU_LEeZI2R0t9WVJy33RgYWOXx06gu0l3hRPO4fgM8QDXTDXUCRQM1HWFlgInbJhpByU0oOKJfY0Ni6D99JShGFmwx5TJhL86R3khfi6iWkdZtX1DUE3MUZMp1NS5xYQdCDhDWf3jEMY/s1600/_IMG_3488_runtime_150_150_150_sat-thresh-prcnt_10_sample-spacing_4.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="650" data-original-width="650" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAhU_LEeZI2R0t9WVJy33RgYWOXx06gu0l3hRPO4fgM8QDXTDXUCRQM1HWFlgInbJhpByU0oOKJfY0Ni6D99JShGFmwx5TJhL86R3khfi6iWkdZtX1DUE3MUZMp1NS5xYQdCDhDWf3jEMY/s1600/_IMG_3488_runtime_150_150_150_sat-thresh-prcnt_10_sample-spacing_4.GIF" /></a></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVbBEmxjSJRUdc1KiAPayPM8i2zBezkC0cvuxcU86BhHvEzCZuTYE9TmTRtXn8uOgyXnXjg1W6UPWwqRSSUZzSuCBzMP4mkeuOCxUABXWLHfH5yo00Wvju9LyXmy_u1nBoEtgnYo_Vleqg/s1600/_IMG_3488_runtime_150_150_150_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVbBEmxjSJRUdc1KiAPayPM8i2zBezkC0cvuxcU86BhHvEzCZuTYE9TmTRtXn8uOgyXnXjg1W6UPWwqRSSUZzSuCBzMP4mkeuOCxUABXWLHfH5yo00Wvju9LyXmy_u1nBoEtgnYo_Vleqg/s640/_IMG_3488_runtime_150_150_150_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Like with the desert mountain photo, but without the haze, diffusion essentially scales the histogram horizontally, accentuating the greener spots, and highlighting some contrasting patches of pale-copper/salmon soil. Note that diffusion enables augmentation of the Blue Channel where histogram scaling is infeasible due to near-saturation.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg04QuD7g53NaaFpj9zTW5_OADZFRypnJrQ43WNTEA0bk6JQYFCWay2JIzuNysc0FEXCtqEMJmON0hjRP-VrY7DjUbDVC5AOpzRx1YLwhin0_hSb7mXb7KflsEyrMLj8iFfl5U2kzDyGjPk/s1600/IMG_4344_runtime_500_500_500_sat-thresh-prcnt_10_sample-spacing_4.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="650" data-original-width="650" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg04QuD7g53NaaFpj9zTW5_OADZFRypnJrQ43WNTEA0bk6JQYFCWay2JIzuNysc0FEXCtqEMJmON0hjRP-VrY7DjUbDVC5AOpzRx1YLwhin0_hSb7mXb7KflsEyrMLj8iFfl5U2kzDyGjPk/s1600/IMG_4344_runtime_500_500_500_sat-thresh-prcnt_10_sample-spacing_4.GIF" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-IQ7wRrqAbOprusWaeqsf8xmId4hYXiTjf58IUnwTMUi6j6Qz9v_RnWI6FZnJh6O28G26K6Gf7RrBlKddiBBPCFqVb0pgs-L8alwfGP7JMcjq7t7GRqQm5M16WHFyfSDt0dBU3xms9bgD/s1600/IMG_4344_runtime_500_500_500_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-IQ7wRrqAbOprusWaeqsf8xmId4hYXiTjf58IUnwTMUi6j6Qz9v_RnWI6FZnJh6O28G26K6Gf7RrBlKddiBBPCFqVb0pgs-L8alwfGP7JMcjq7t7GRqQm5M16WHFyfSDt0dBU3xms9bgD/s640/IMG_4344_runtime_500_500_500_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This image is more bi-modal in nature, due to the clustering around both sky and and ground. Because the original image covers the available gamut relatively fully, conventional histogram scaling cannot be used. However, diffusion encourages fuller use of the mid-range gamut between these two clusters, reducing the warm glow and the increasing the overall contrast, especially in the ground cover and clouds. A curious and persistent bug occurs here - sparse regions of tree foliage set against the sky turn whitish, as if snow-covered.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQZDSfYzau8yRwzXLLWCTuSyeFcs4AdpADzp2VgZxwXnTiZscj9Ltomg6IXkzz3Jnz8Oh06egwU1XlykYysQ96HQXbpBf0F41OIbDcuybwt_6w8HWg2cLLMzeJQgWmke_SVKpDpxT6ZyHn/s1600/IMG_4328_runtime_200_200_200_sat-thresh-prcnt_10_sample-spacing_4.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="650" data-original-width="650" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQZDSfYzau8yRwzXLLWCTuSyeFcs4AdpADzp2VgZxwXnTiZscj9Ltomg6IXkzz3Jnz8Oh06egwU1XlykYysQ96HQXbpBf0F41OIbDcuybwt_6w8HWg2cLLMzeJQgWmke_SVKpDpxT6ZyHn/s1600/IMG_4328_runtime_200_200_200_sat-thresh-prcnt_10_sample-spacing_4.GIF" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh67ub36Fnda_EOehjD8lqKCChyphenhyphensQANozbpKT9f6rK2Fyp1Jv7ckkFzUyT18I6LHqoOjcQQeeH2uU131F_didJrXfA_s9_Ow8eVfS1sIs2XyCy2as-krm6y0eaHvV-flgSXJ2YAeKWhYPKi/s1600/IMG_4328_runtime_200_200_200_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1600" data-original-width="1067" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh67ub36Fnda_EOehjD8lqKCChyphenhyphensQANozbpKT9f6rK2Fyp1Jv7ckkFzUyT18I6LHqoOjcQQeeH2uU131F_didJrXfA_s9_Ow8eVfS1sIs2XyCy2as-krm6y0eaHvV-flgSXJ2YAeKWhYPKi/s640/IMG_4328_runtime_200_200_200_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" width="426" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Another example of an initially well-utilized color gamut that can be augmented by diffusion.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM-ZdzBOoVha7pwWk5peB7q4WeNN1SfWY_lNEmT2krrKzKat6gsFy7pklBwTS0joTCdTEiRp3C2ZhWjhKFVRXWgUZspjQYm0YaQe7Ir3up9UVlUahTD0fwvD4_a-OOiS7hTUI4kjVxeYE_/s1600/_IMG_3767_runtime_500_500_500_sat-thresh-prcnt_10_sample-spacing_4.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="650" data-original-width="650" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM-ZdzBOoVha7pwWk5peB7q4WeNN1SfWY_lNEmT2krrKzKat6gsFy7pklBwTS0joTCdTEiRp3C2ZhWjhKFVRXWgUZspjQYm0YaQe7Ir3up9UVlUahTD0fwvD4_a-OOiS7hTUI4kjVxeYE_/s1600/_IMG_3767_runtime_500_500_500_sat-thresh-prcnt_10_sample-spacing_4.GIF" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJleW9aSQwm74zvfhx8qt0isBeAvuaUiLoYo_QvVOrbFoJkPeWIoqFFVoUZ-Y82yAMghtv2hBJ5pIA5aw-CSPuemSAr1DjKtD2AJkf1m_RTYQL9Wm1-UbxRWmaydUEQOM7JhoqQGChw1O6/s1600/_IMG_3767_runtime_500_500_500_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJleW9aSQwm74zvfhx8qt0isBeAvuaUiLoYo_QvVOrbFoJkPeWIoqFFVoUZ-Y82yAMghtv2hBJ5pIA5aw-CSPuemSAr1DjKtD2AJkf1m_RTYQL9Wm1-UbxRWmaydUEQOM7JhoqQGChw1O6/s640/_IMG_3767_runtime_500_500_500_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">An especially good result wherein R and G are both fixed, while B is insulated on the low end. The fog is thinned and the underlying colors are better illuminated.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSgxPlzN4Ub3SmYLVAZDLyI3SIGjxNA-WxM6upuh_BPwYEznw32hNUILB4OHAI3YgzOK6cxKY4fc45b_JjaHlgpQRr90ezAuekMTQYPa6-eU5trxXVwGeJs4uJrwpG2kx3aJtuyFd_Edew/s1600/IMG_3119_runtime_200_200_200_sat-thresh-prcnt_10_sample-spacing_4.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="650" data-original-width="650" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSgxPlzN4Ub3SmYLVAZDLyI3SIGjxNA-WxM6upuh_BPwYEznw32hNUILB4OHAI3YgzOK6cxKY4fc45b_JjaHlgpQRr90ezAuekMTQYPa6-eU5trxXVwGeJs4uJrwpG2kx3aJtuyFd_Edew/s1600/IMG_3119_runtime_200_200_200_sat-thresh-prcnt_10_sample-spacing_4.GIF" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIY0IdUaZp2dQmdZZKcZHTuyQB7_6QHZV9DP9C4S5C0dej8Xpm05OG8FoS28Ru9p6LuTD7FTTE-_Shn_0-eVcog4wUdPLANY4v0G_eRGZBCVMbs67TgRLOkyOEZGiRt2vQEItZlJjReFSs/s1600/IMG_3119_runtime_200_200_200_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1067" data-original-width="1600" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIY0IdUaZp2dQmdZZKcZHTuyQB7_6QHZV9DP9C4S5C0dej8Xpm05OG8FoS28Ru9p6LuTD7FTTE-_Shn_0-eVcog4wUdPLANY4v0G_eRGZBCVMbs67TgRLOkyOEZGiRt2vQEItZlJjReFSs/s640/IMG_3119_runtime_200_200_200_sat-thresh-prcnt_10_sample-spacing_1_comp.JPG" width="640" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Another bimodal gamut where scaling is inappropriate due to near-saturation on the low end initially. Diffusion preserves the means of each cluster, while diffusing them individually to find subtle hues in the sky and better distinguish rock from greenery.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Conclusions</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Histogram diffusion is a potentially useful image processing filter for augmenting chromatic realism. It especially provides an advantage over conventional histogram scaling for images that are one or more of:</span><br />
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Bi- or multi-modal</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Nearly-saturated initially, making histogram scaling infeasible</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Strongly dissimilar between color channels, requiring per-channel treatment</span></li>
</ul>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Initial experiments applying this same methodology to HSV color space did not seem to produce significantly different/better results, but more exploration could be done in this and other color spaces.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Source Code</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Freely available on <a href="https://github.com/kindofdoon/histogram_diffusion_image_filter">my GitHub</a> in MATLAB.</span></div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-11992972956977926502019-07-21T18:36:00.000-07:002020-04-17T07:42:25.123-07:00How Paints Mix<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Summary</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For augmented realism in artistic painting, this article summarizes mathematical methods to characterize any palette of primary paints and decompose any digital color into an analog paint mix recipe, using Kubelka-Munk theory, Schmid color charts, and visible-light spectroscopy.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Motivation</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ever eloquent, Lucian Freud best </span><a href="https://www.youtube.com/watch?v=6LaQ9d0iFuU#t=3m24s" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">expressed</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> the importance of color real</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ism in painting:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"...[When] colors work, I think of them as the color of life, rather than colored."</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br />Famously dogged and penetrating in style, Freud labored over ever</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">y stro</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ke, working and reworking his canvases over long sessions even into old age. His eye was a perceptive color comparator, restless until the canvas felt as true as the scene. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Similarly, Rembrandt wrote that his paintings sought to achieve "</span><span style="text-align: center;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">the greatest and most natural movement".</span></span><br />
<div>
<div style="text-align: center;">
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Venerated by Freud, Rembrandt, and all great painters, realism is the strongest unifying principle across painting's long and diverse history.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-v6wXnSammD-Rg0kQwvCEq-DGq3R-YuSTTKifJxC9gK3TWnpVivHKTxRtBfNAUrJd4sNiwsyfEF7dajN5B2BJ3ct3viNpuiAe3KcAv2SK8tvk_bVzT4w5gZFzkc6jyYksKZSB9xl_zRim/s1600/rembrandt_1628.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><img border="0" data-original-height="945" data-original-width="833" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-v6wXnSammD-Rg0kQwvCEq-DGq3R-YuSTTKifJxC9gK3TWnpVivHKTxRtBfNAUrJd4sNiwsyfEF7dajN5B2BJ3ct3viNpuiAe3KcAv2SK8tvk_bVzT4w5gZFzkc6jyYksKZSB9xl_zRim/s400/rembrandt_1628.PNG" width="350" /></span></a></div>
<div class="separator" style="clear: both;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Rembrandt, 1628</span></div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; margin-left: 1em; margin-right: 1em;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg8NrWjplshKrj9fdH8I6K3HOzy1P2UpUBXSZ1t2SVITh01kzNnZWFa3OhzTlkVpn6082iq2gpiXXY3hMGyebmQ_CRjC_CL6hvKKurCjGCLr0hNSxVv46lbuA1Urx3w7MY4zvpV325QXxG/s1600/freud_1985.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1415" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhg8NrWjplshKrj9fdH8I6K3HOzy1P2UpUBXSZ1t2SVITh01kzNnZWFa3OhzTlkVpn6082iq2gpiXXY3hMGyebmQ_CRjC_CL6hvKKurCjGCLr0hNSxVv46lbuA1Urx3w7MY4zvpV325QXxG/s400/freud_1985.jpg" width="352" /></a></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Freud, 1985</span></div>
</div>
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">When I started painting, I was confounded by the skill of color matching, the </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">the act of mixing primary paints together to create colors that match those observed by the eye. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">It requires both </span><i style="font-family: "helvetica neue", arial, helvetica, sans-serif;">seeing</i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> colors accurately and </span><i style="font-family: "helvetica neue", arial, helvetica, sans-serif;">knowing </i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">how to mix them from primary paints. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I've seen painters who can color match with astonishing ease and accuracy, but I can only stand apart and admire their skill</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">. I still find it confounding, though with experience I've developed a decent working knowledge.<br /><br /> Godfrey Reggio said this of his 1982 film Koyaanisqatsi, one of my favorites:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"...[Our] language is in a state of vast humiliation. It no longer describes the world in which we live."</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /> Try to describe</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> the spectrum of real-world colors in words and you'll quickly see that Reggio's axiom neatly encapsulates what makes color, with its </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">intangible, experiential, and subtle nature, so hard to describe. B</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">y extension, this also makes color matching very difficult. But, as the great masterpieces in oil painting's rich history show, it's not out of reach - it's just very hard.</span><br />
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br />Frustrated with my lack of talent at color matching, and with the clumsy old-fashioned models for color mixing, I began to wonder if </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">there was a cleaner, mathematical way of describing paint and color. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I reasoned that since e</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">very painting can be represented as a digital picture, and since e</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">very constituent pixel has a well-defined digital color, any painting can be represented mathematically. Put another way, every digital picture can be represented as a painting.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">My focus then became developing the critical link between physical color (i.e. paint) and digital color (i.e. pictures). </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Less abstractly, I sought to develop an algorithm that could decompose any digital color </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">into an analog mixing recipe. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This algorithm, and path to developing it, is the subject of this article.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Early Missteps in Digital Color</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Having some prior experience in digital image processing, I initially expected that the problem could be solved purely in a digital color space - simply quantify the colors of the primary paints, then mixtures thereof should be simple weighted averages. However, this approach do</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">esn't work, as a quick counterexample shows:</span><br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Blue and yellow mix to make green.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Blue and yellow may be represented in RGB as [0 0 255] and [255 255 0].</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The average of [0 0 255] and [255 255 0] is [128 128 128].</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">[128 128 128] is gray.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Gray is not green.</span></li>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Converting to alternate color spaces before averaging provides similarly erroneous results: Lab predicts a pale pink, and XYZ predicts periwinkle. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I also tried <a href="http://www.tannerhelland.com/4660/dithering-eleven-algorithms-source-code/">dithering</a> swatches of the target color using primary paints as the set of permitted colors, as if to simulate pigment particles with pixels. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Initially encouraged by the fact that this method produced different results than a naive average that were also plausible and visually interesting, I eventually conceded that it didn't work after some simple experiments disproved its accuracy.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMvxyRfXHkD8FXFuZ9RMGZTMnF4TRUACrgAA7l_JGKP35eU794RudxEB1ERN-WwpWoAOAdL9Coztta6dSN2jrxRChxHVSow5LlcvMUopY5bj95h8wHV7JCR-O5R7j8h4M9KQTx7l2c0sEs/s1600/dither_test.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="226" data-original-width="405" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMvxyRfXHkD8FXFuZ9RMGZTMnF4TRUACrgAA7l_JGKP35eU794RudxEB1ERN-WwpWoAOAdL9Coztta6dSN2jrxRChxHVSow5LlcvMUopY5bj95h8wHV7JCR-O5R7j8h4M9KQTx7l2c0sEs/s1600/dither_test.png" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Interesting but unsuccessful experiment at color decomposition using dithering</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">These methods all fail due to their neglect of the microscopic optics at play in actual paint films, which cannot be captured by reductive digital imaging due to the irreversibility of the color perception causal chain.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Enter Kubelka-Munk</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">After some more research, I learned that this is actually a semi-solved problem, with the theoretical foundation having been laid in 1931 by German scientists/engineers Kubelka and Munk. Later researchers extended their framework by developing practical methods of using it, especially starting in the 1980s with the advent of personal computers. Kubelka-Munk theory (K-M) remains important to many industries, especially the manufacture of coatings, films, and paints. It applies to both translucent and opaque media, although as an <i>alla prima</i> oil painter, I'm only interested in the simpler opaque case.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K-M posits that diffuse light incident on a paint surface is either reflected (R) off the surface, absorbed (K) by the paint pigment itself, or scattered (S) through the surface to other pigment particles. Further, it posits that R, K, and S are all functions of light wavelength.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRGQxtviReCizquo6qII7222lLdWjYG0UuiEpm6WjTHZgN2EAkkHHkd7DnIB2OJBcZVp2s_jZLLxe8SITXlWi7KQH2u2cXADLunCZ8lh0sPF_dXJ63LlzdY_EBT_HysmNBaAb0TfiY89zx/s1600/RKS.PNG" imageanchor="1" style="font-family: "Times New Roman"; margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="369" data-original-width="612" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjRGQxtviReCizquo6qII7222lLdWjYG0UuiEpm6WjTHZgN2EAkkHHkd7DnIB2OJBcZVp2s_jZLLxe8SITXlWi7KQH2u2cXADLunCZ8lh0sPF_dXJ63LlzdY_EBT_HysmNBaAb0TfiY89zx/s1600/RKS.PNG" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Diagram of reflectance, absorption, and scattering in a pigment-based paint film</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K-M provides the following equation relating R, K, and S for an opaque film:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIt7AjOjCOuTUDZVZyDnr7JXtxol9vpZgI9phqTzgGutc0eRhMczJmL4zGB4Gb7Z1Io9v8_zS5tLV98OBFc4AHbf8XHcHxT6tJrWr2GTo5SA-CVPSbyg04esZ-4Ie1M3cVxAgMSya2SJhL/s1600/R+equals.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="61" data-original-width="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIt7AjOjCOuTUDZVZyDnr7JXtxol9vpZgI9phqTzgGutc0eRhMczJmL4zGB4Gb7Z1Io9v8_zS5tLV98OBFc4AHbf8XHcHxT6tJrWr2GTo5SA-CVPSbyg04esZ-4Ie1M3cVxAgMSya2SJhL/s1600/R+equals.PNG" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">which may be rearranged to solve for K/S:</span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE9OiLrMQV58VMH6PHA1joyAp1wIAKeIvLZkQ6J1EHMlaeor7hZ2PLsmSGz09QonL8s_XMJd5UE2_cwjrC6EUaRHHTVRuK4Kn1oxeXX8Crx3_TJpAeaEALDJDaE3Mn40IoFKKh6QLreqUw/s1600/KS+equals.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="57" data-original-width="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE9OiLrMQV58VMH6PHA1joyAp1wIAKeIvLZkQ6J1EHMlaeor7hZ2PLsmSGz09QonL8s_XMJd5UE2_cwjrC6EUaRHHTVRuK4Kn1oxeXX8Crx3_TJpAeaEALDJDaE3Mn40IoFKKh6QLreqUw/s1600/KS+equals.PNG" /></a></div>
<div style="text-align: center;">
<br /></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K-M also holds that paint mixtures can be described as weighted averages of the constituent K and S values:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnd0MyPOuEWO7VeXHGTtV4Hvdk36xWsZ_uykZ2_UfmfqPv8ONIO3y-vco4jzUWaLNbSRU2bLg4zwVW_FpXy7P-pkbLi7qWB5fTzocid_Mc1wOpM1Jvprjj-d32IYQ4vxYNpXOtxFWs_Vpe/s1600/KS+mix.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="106" data-original-width="121" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnd0MyPOuEWO7VeXHGTtV4Hvdk36xWsZ_uykZ2_UfmfqPv8ONIO3y-vco4jzUWaLNbSRU2bLg4zwVW_FpXy7P-pkbLi7qWB5fTzocid_Mc1wOpM1Jvprjj-d32IYQ4vxYNpXOtxFWs_Vpe/s1600/KS+mix.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">where the subscript i denotes the paint index, and c denotes the dry pigment mass fraction in the mixture. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This turns out to be the extent of math needed from K-M. More math is needed, though, to actually make use of these essential equations.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Light, Reflectance, and Color</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Intuitively, paint has no observable color unless illuminated, and further, its perceived color changes depending on its illuminant - whether bright/dark, warm/cool, etc. Therefore, to begin modeling color, an illuminant is needed. Conveniently, several standard illuminants were defined starting in 1931 by the CIE (International Commission on Illumination), coincidentally the same year as K-M's publication. Due to its ubiquity, I chose CIE D65, representing "average [outdoor] midday light in Western/Northern Europe". Outdoor lighting is broad-spectrum, bright, and relatively temperature-neutral, often considered optimal for lighting and photographing paintings.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDjxONsghwUwZ9_ltNn72-ehv1ANz80kuU1fmeRfCrURT3hZEa48kpZxqwy4tao0tO0zYqX56D1x3loexYpKjg-nifgzwHXPtJSDEjTav5oFaW_KZPi99wEEyjGevBOSAQiitgX_NXSFXQ/s1600/d65.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="533" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDjxONsghwUwZ9_ltNn72-ehv1ANz80kuU1fmeRfCrURT3hZEa48kpZxqwy4tao0tO0zYqX56D1x3loexYpKjg-nifgzwHXPtJSDEjTav5oFaW_KZPi99wEEyjGevBOSAQiitgX_NXSFXQ/s1600/d65.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Next, paint reflectance spectra are needed. This is the same quantity as the R in K-M, and it is similarly defined as the normalized diffuse reflection as a function of wavelength.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbM4OghdIwe5SjPS8hwFc3TW3-bw6mgSAAWd3dTUVSrw4K2IbjFoEmY_BKjkW7hTEk-dC_Z-HNPt-tvQUPsNu5eBu_I2Rb8hXuUKmkPILo2ro09w3pDdLyxxzSPkM8Zwe9js0yJNgj1m1b/s1600/R+example.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="331" data-original-width="616" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbM4OghdIwe5SjPS8hwFc3TW3-bw6mgSAAWd3dTUVSrw4K2IbjFoEmY_BKjkW7hTEk-dC_Z-HNPt-tvQUPsNu5eBu_I2Rb8hXuUKmkPILo2ro09w3pDdLyxxzSPkM8Zwe9js0yJNgj1m1b/s1600/R+example.PNG" /></a></span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Reflectance spectra for red, white, and a red/white mixture from literature</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The interplay between illuminant and reflectance creates color. However, unlike illuminants and reflectance, color doesn't actually exist in an absolute, quantifiable sense. For example, the fact that 475 nm light looks "blue" or that 700 nm light looks "red" is a perceptual abstraction of the human brain, not an universal truth. Further, perception of color varies between individuals and species, and is best understood as an inherently personal characteristic. Nevertheless, CIE further provides a "standard observer" function which quantifies the perceptual sensitivity of the <i>average</i> human eye to light, again as a function of wavelength.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE7fdL64j2FV5z8a31vquIUylShNuUj5lFXrTTNGd_lyWBIDu44EX0Tlaak_eWYUMF27930cvTiWLQXMy9Bf2dviH0rVAiHE79xKCR2aSdHNzrqFN5bn9vxYhhfMIPEZITeC1HmCdniIpv/s1600/CIE_observer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="532" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjE7fdL64j2FV5z8a31vquIUylShNuUj5lFXrTTNGd_lyWBIDu44EX0Tlaak_eWYUMF27930cvTiWLQXMy9Bf2dviH0rVAiHE79xKCR2aSdHNzrqFN5bn9vxYhhfMIPEZITeC1HmCdniIpv/s1600/CIE_observer.png" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The CIE standard observer is comprised of three independent functions corresponding to the three types of cone cells in the human eye, which specialize in short-, medium-, and long-wavelength light. It's </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">worth noting that human vision is significantly non-uniform. We are probably most sensitive to regions of color that were most evolutionarily advantageous to our ancient ancestors. Regardless, this is an important point for later discussion on color matching.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With these three pieces in place - illuminant, reflectance, and observer - color may be calculated essentially as their dot product. This provides color in the XYZ, or tristimulus format, representing the overall signal delivered to the eye. XYZ can then be converted to RGB for display on a digital screen, or to Lab for calculating color difference. For best results, I calculate all color differences in Lab space, which by design is perceptually uniform per the observer functions, unlike RGB space.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In this framework, color may be thought of as the checksum of the underlying spectral data, in that it provides an simplified summary of the underlying spectral data. This framework also shows how perception of color is inherently reductive, i.e. an infinite number of reflectance curves may produce the same perceived color, or put another way, a reflectance curve cannot be derived from a perceived color.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Characterizing Paints</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The last and most difficult part of the color mixing problem is characterizing paints - specifically, the determination of their K and S spectra. A few aspects make this step challenging:</span><br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K and S cannot be measured directly, only calculated indirectly through mix tests.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K and S vary significantly with wavelength and are not well-approximated as constant.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K and S cannot be determined without a spectrophotometer.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K and S are easily overfitted if the number of mix tests is too small.</span></li>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Each of these aspects was hard-learned through various failed attempts to devise new, simpler methods for cracking this sub-problem. As far as I can tell, there is no easy, elegant method for this step, despite my best efforts. It simply requires a lot of mixing and number crunching.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">One approach (Haase, Meyer) is to assume an ideal white, i.e. K=0 and S=1, then tint (i.e. mix with white) one's primaries and measure the reflectance. Algebra can then be used to calculate K and S for the pure primary. I tried this method for 5 and 10% tints (i.e. 95 and 90% white), and it provided excellent results for primary/white mixes, but did not generalize well for primary/primary mixes. I concluded that K and S had been overfitted.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A much better approach (</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Walowit, McCarthy, and Berns</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">) is to build up a large database of color mixes, including both recipes and corresponding reflectance spectra, then use the <a href="https://en.wikipedia.org/wiki/Linear_least_squares">linear least-squares</a> (LLS) method to find error-minimizing K and S values at each wavelength. The authors begin with K-M's proportional weighting of K and S in mixes:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVA6gEcU0o47OPRaLvYcJUx6AIXilvjqYsIn64JQKS8mdG9yHvKspoVIDrAD0JmEnI4iQexNEEnrEJUGgdEuMGjJ_c927BNDBJ8ADiNYXmq4m4oMaKwrbfQJt5Bn1G7WaS2a3Wq8AXJkO1/s1600/WMB_1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="113" data-original-width="206" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVA6gEcU0o47OPRaLvYcJUx6AIXilvjqYsIn64JQKS8mdG9yHvKspoVIDrAD0JmEnI4iQexNEEnrEJUGgdEuMGjJ_c927BNDBJ8ADiNYXmq4m4oMaKwrbfQJt5Bn1G7WaS2a3Wq8AXJkO1/s1600/WMB_1.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">which can be cross-multiplied and expressed as:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgM-Ej7otaizw7dsYxwqvP7gan2DbHdIvoR3-Lq_JOhxdI4v3bPcfXAOHygAgVjmcqXZ8_UTxv9boVKFshk_vteqc-1sNkusXvEjJ56-4Le1fudBwNkvANzB97xbh_ZYkyo_bk-f3UHFBR/s1600/WMB_2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="67" data-original-width="335" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgM-Ej7otaizw7dsYxwqvP7gan2DbHdIvoR3-Lq_JOhxdI4v3bPcfXAOHygAgVjmcqXZ8_UTxv9boVKFshk_vteqc-1sNkusXvEjJ56-4Le1fudBwNkvANzB97xbh_ZYkyo_bk-f3UHFBR/s1600/WMB_2.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This can then be expressed in terms of the LLS formulation of:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3Fu4eshLrMXaxzOt1dYIN_mPtHXz2d5sQPtOpncvMtRPPDbFnBbjaAgm7zKAxakIldgnKtct6PfmEFpAIQdU64jaOqgN8Nfv11DogEVGkjCVbUw2mcR5bf5MrdRUELuXFqKf-5afi4QAk/s1600/WMB_3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="33" data-original-width="104" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3Fu4eshLrMXaxzOt1dYIN_mPtHXz2d5sQPtOpncvMtRPPDbFnBbjaAgm7zKAxakIldgnKtct6PfmEFpAIQdU64jaOqgN8Nfv11DogEVGkjCVbUw2mcR5bf5MrdRUELuXFqKf-5afi4QAk/s1600/WMB_3.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">which can be neatly solved for B, containing K and S values for every primary:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBFkpb5wF3iZ7OtyRGdJF-q5FcWC7DYj0T87HvEiUBoCTt5nR_fkjCyIwQy1CSg-pkZ39aQwrsIaBDRVZ58AaW_vArM9LwzrRPOeae7lIkf2jQ-E7Yr9doJ2DdV1J2gwxhgVsMSKJ19yBM/s1600/WMB_4.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="42" data-original-width="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBFkpb5wF3iZ7OtyRGdJF-q5FcWC7DYj0T87HvEiUBoCTt5nR_fkjCyIwQy1CSg-pkZ39aQwrsIaBDRVZ58AaW_vArM9LwzrRPOeae7lIkf2jQ-E7Yr9doJ2DdV1J2gwxhgVsMSKJ19yBM/s1600/WMB_4.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This method is very flexible and can accommodate any number of primaries, mixes, and recipe ingredients. A full derivation may be found in the Appendix.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">However, the authors do not offer guidance on </span><i style="font-family: "helvetica neue", arial, helvetica, sans-serif;">which </i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">recipes to mix to sample uniformly over a palette's color gamut. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For this, I looked back to the art world and discovered <a href="https://lisadaviddailypaintings.wordpress.com/2019/02/28/two-kinds-of-people/">Schmid color charts</a>, which use a methodical approach to mix virtually all colors possible for an arbitrary set of primaries. Every primary is mixed with every other primary, in both a dominant and non-dominant capacity, at varying levels of tinting (whiteness/brightness). Schmid's convention is that every primary/primary pair be mixed at five levels of tinting. However, since I also needed to measure the exact mass breakdown for each recipe (while Schmid doesn't), I realized that I would need to reduce resolution to make the scope manageable. I eventually settled on three tinting levels per primary/</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">primary pair.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I then carefully set my standard palette using my prior </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">painting experience. These primaries cannot produce any arbitrary color, but they are naturalistic and cover the full gamut for the images that I paint. I chose my most essential and favorite paints, all from Winsor & Newton's "Winton" line:</span></div>
<div>
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">titanium white</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">cadmium yellow</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">cadmium red</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">burnt sienna</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">burnt umber</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">sap green</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ultramarine blue</span></li>
</ol>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I set the dominant primary as 75%, and the non-dominant primary at 25%. I set my tinting levels at 0, 45, and 90% white. I set a mass target for each mixed paint volume at 3.00 g, with each ingredient subject to a +/- 0.02 g tolerance. This provided more than enough paint to thickly cover a 2 x 2" canvas board swatch without too much waste.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With this, it was simply a matter of sitting down and working through all the mixes required - 109 in total. Each sample took about 5 minutes to create.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKptQN5WZ6ReZW6yU5RN0BIx_ko3d6hoGEb_TJhzl0gMVj76OwkD2XiN0kX8AXYgsljUuZMMH-JmYOqYMWO8tPFJYl7vkFOqMIzh3Q9TYIeIfF8vGBmkAgXa22bBqWl4nCT3kvS9Kj1K6-/s1600/mixing_purple_paint.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="304" data-original-width="540" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKptQN5WZ6ReZW6yU5RN0BIx_ko3d6hoGEb_TJhzl0gMVj76OwkD2XiN0kX8AXYgsljUuZMMH-JmYOqYMWO8tPFJYl7vkFOqMIzh3Q9TYIeIfF8vGBmkAgXa22bBqWl4nCT3kvS9Kj1K6-/s1600/mixing_purple_paint.gif" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mixing 45% titanium white, 41% ultramarine blue, 14% cadmium red with a palette knife</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuoP_EsKaPkqsYwfCSxAT6wbObs2XUJMvzOaPFZZVlPRjENuqt3G5hejgO9X29EqPh0AJyPNiZAwn-chJd5VNAqLjAyVGNktrGBqG8VnCbfPwT4k46ms90TmWOSmUoKjsowGzBmPod9n8t/s1600/purple_paint.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="312" data-original-width="540" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuoP_EsKaPkqsYwfCSxAT6wbObs2XUJMvzOaPFZZVlPRjENuqt3G5hejgO9X29EqPh0AJyPNiZAwn-chJd5VNAqLjAyVGNktrGBqG8VnCbfPwT4k46ms90TmWOSmUoKjsowGzBmPod9n8t/s1600/purple_paint.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fully-mixed purple paint</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With the amount of effort this ended up taking, about a full weekend, I decided that I ought to frame the results.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx2q3-1BegZ-MfMb9Noasrn9j2g7iOoC_4S5UeEu_bZwADkN4NHvAexl2nYsI_H0crdpxjD7gJDIi9oxH-Ok0wN4QVHeWlvRMqaii_PVK7Hr_ilpj4kw3QWxMXua2WOuQauYyohtsVv3Hg/s1600/schmid_framed.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1233" data-original-width="1600" height="492" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgx2q3-1BegZ-MfMb9Noasrn9j2g7iOoC_4S5UeEu_bZwADkN4NHvAexl2nYsI_H0crdpxjD7gJDIi9oxH-Ok0wN4QVHeWlvRMqaii_PVK7Hr_ilpj4kw3QWxMXua2WOuQauYyohtsVv3Hg/s640/schmid_framed.jpg" width="640" /></a></div>
</div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Schmid color chart for my selected primary paints</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For measuring the reflectance of each swatch, I pursued a few different paths until ultimately finding and purchasing the <a href="http://variableinc.com/spectro.html">Spectro 1</a>, a fantastic new spectrophotometer aimed between the consumer and industrial levels. It overall offered the exact functionality I needed at a great price, and this project would not have been possible without it.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQM2MLIBJW4i3OGm5I5sG_e5azUDmrm4-sSZ6mf03_yW2zDqYzi_oN9HSdWvSgupIy24hLWDUnULtjMYSZwwx63kWBk6WRKZaYa7YfZPJZ4nTbmOulm6tsy-7kIxPHa6ntAgOnAVtEW5mA/s1600/spectro_1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="295" data-original-width="613" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQM2MLIBJW4i3OGm5I5sG_e5azUDmrm4-sSZ6mf03_yW2zDqYzi_oN9HSdWvSgupIy24hLWDUnULtjMYSZwwx63kWBk6WRKZaYa7YfZPJZ4nTbmOulm6tsy-7kIxPHa6ntAgOnAVtEW5mA/s1600/spectro_1.PNG" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Spectro 1, a fantastic new <span style="text-align: start;">spectrophotometer </span>that is about the size of a pill bottle</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With the swatches mixed, dried, and scanned, I was now able to use the LLS method, combined with my measured recipes, to calculate K and S spectra for all my paints. Implemented as described in the original paper, this method provided disappointing results when comparing the measured and simulated Schmid chart, both visually and numerically. To compare colors, I used <a href="https://en.wikipedia.org/wiki/Color_difference#CIE76">CIE76</a>, which is essentially Euclidean distance in Lab space, normalized to a "just noticeable difference" of 2.3 ΔE.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBIYUUVS72QOG6FBn_675JDsDABXTopG_dsS9nN0hFYi290oLV6k8MjMa3PNR-iIxzxGMtb3vxLPI-a1czAbOV3Rz6ZaR69UILGctchdjo7nTjsaEmgh1e8ybtvsX0LAlOUqCqNuVlesDz/s1600/schmid_naive.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1084" data-original-width="1012" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBIYUUVS72QOG6FBn_675JDsDABXTopG_dsS9nN0hFYi290oLV6k8MjMa3PNR-iIxzxGMtb3vxLPI-a1czAbOV3Rz6ZaR69UILGctchdjo7nTjsaEmgh1e8ybtvsX0LAlOUqCqNuVlesDz/s640/schmid_naive.png" width="592" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Disappointing results for a naive implementation of the LLS method; left=measured, right=simulated</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A problem with this approach is that its results are not constrained by K-M, and consequently its fitted K and S values violate K-M and cause unintended color shifts. To resolve this, I applied an additional least-squares optimization:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Given K and S, find K* and S* such that:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "courier new" , "courier" , monospace;">error = c_1(K-K*)^2 + c_2(S-S*)^2</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> is minimized, and</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">K*/S* = (1-R)^2 / (2R)</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">, i.e. K-M is enforced</span></li>
</ul>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">where c_1 and c_2 are fractional weights. This is solved numerically by specifying a range and resolution for S*, then deriving K* for each and calculating the corresponding error. This is performed at each wavelength for each paint. To optimize the values of c_1 and c_2, I defined bounds for c_1 as 0 to 1, and </span><span style="font-family: "courier new" , "courier" , monospace;">c_2 = 1-c_1</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">. For each pair of weights c_1 and c_2, I optimized K* and S* using the above method, then calculated the average color prediction error against the Schmid chart.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzVWO7prj_M_iZ-ZmGkC_y-i-vMlEKB_g4f4ghwnxdv3ZPb9haPs84a3i3r__eact9NdWtXq7MGvyHPWrXSfFnPIbDJ4c-xgHEtrw26d1rUPJkRMTJzbustJCqBO_vEIfYbu-GO4qZtIDh/s1600/LS_full.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="410" data-original-width="487" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzVWO7prj_M_iZ-ZmGkC_y-i-vMlEKB_g4f4ghwnxdv3ZPb9haPs84a3i3r__eact9NdWtXq7MGvyHPWrXSfFnPIbDJ4c-xgHEtrw26d1rUPJkRMTJzbustJCqBO_vEIfYbu-GO4qZtIDh/s1600/LS_full.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Optimization result for full K* weight domain, 0-100%</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ9-gmaoN1jIkvcUCF3g64USYdYs8vc6u7a-6tn4OayOgBya7SZa1AiUuTcW4n28NokmAppl4LP4GUSBCrVgDgDztxHlNR1Y1S0gZVS646QqbI0w3KIDpRFroIIxvxYj_h9Kmd0Sy2j54l/s1600/LS_zoom.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="410" data-original-width="523" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZ9-gmaoN1jIkvcUCF3g64USYdYs8vc6u7a-6tn4OayOgBya7SZa1AiUuTcW4n28NokmAppl4LP4GUSBCrVgDgDztxHlNR1Y1S0gZVS646QqbI0w3KIDpRFroIIxvxYj_h9Kmd0Sy2j54l/s1600/LS_zoom.png" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Optimization result for K* weight domain near minimum, 2-4%</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Repeating this for an array of c_1 values, it becomes clear that the optimal solution is to heavily weight S (in this case, c_1 = 0.027), nearly to the point of discarding K and defining it per K-M as a function of R and S. Incidentally, this method is much simpler and nearly as good, with an average color error that is only about 4% higher for my dataset.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With K*, S*, and c_1 optimized, the color predictions become very accurate - on average, 1.535 JND for the full dataset. In other words, the average color difference is just noticeable, and if you squint (a classic artist's trick) </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">at the comparison chart, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">the seams between the colors practically disappear.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJkNfvY3MTQNoU_h4GsZvl8UCN4qvien-733iV27X6sTvyFX-RfaGomT2na-SNnZE9aTxun6CwD1EwQl2uea4xxbxt9uo0K1LADRz1lAahsNNp6uhkBxYuUIKpwGKcyobJ2hN_TKlm9eHb/s1600/schmid_1-535_JND.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1084" data-original-width="1012" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJkNfvY3MTQNoU_h4GsZvl8UCN4qvien-733iV27X6sTvyFX-RfaGomT2na-SNnZE9aTxun6CwD1EwQl2uea4xxbxt9uo0K1LADRz1lAahsNNp6uhkBxYuUIKpwGKcyobJ2hN_TKlm9eHb/s640/schmid_1-535_JND.png" width="592" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Final result with LLS and optimized enforcement of K-M</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">; left=measured, right=simulated</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Cross-Validation</b></span><br />
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Aware of the risk of overfitting K and S with too few samples, I cross-validated using the holdout method. To do this, I randomly and repeatedly partitioned the full dataset into "fit" and "test" subsets, calculated K and S using only the "fit" subset, then tested the resulting model against the "test" subset. For expedience, I kept c_1 as 0.027, which is sub-optimal and conservative from the perspective of cross-validation.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-9mMIBRmckiW15fN-w8zokZGtTWCTmBowW3pf8itRsyPQGEZlr5GLeInVkv5BGguznO-6cO2zxxnnIx07hK5wdkxRAVCcyROEX59Yyo7nGDyVYDbmjaVaGBRi-X2BJ0pkQqK7fExT0HOu/s1600/cross_validation_1-535.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="420" data-original-width="505" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-9mMIBRmckiW15fN-w8zokZGtTWCTmBowW3pf8itRsyPQGEZlr5GLeInVkv5BGguznO-6cO2zxxnnIx07hK5wdkxRAVCcyROEX59Yyo7nGDyVYDbmjaVaGBRi-X2BJ0pkQqK7fExT0HOu/s1600/cross_validation_1-535.png" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Holdout cross-validation showing stability of average color error with decreasing data</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The relative flatness of the trial-average line, even up to 50% withheld, confirms that these methods and spectra are well-generalized and not overfitted. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">It also suggests that the number of swatches mixed could have been reduced with minimal penalty to the model's accuracy. A useful metric here is mixes per primary. One source (Baxter, Wendt, Lin) shows 71 mixes per 11 primaries, or 6.5 mixes/primary, with relatively poor color matching. My 109 mixes per 7 primaries, or 15.6 mixes/primary, has better results, though is much more time-consuming. More mix data, provided it is well-distributed over the color gamut, will only improve results, although with diminishing returns as K and S converge.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Decomposing Colors</b><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Once K and S are known with confidence, decomposing colors into recipes is relatively trivial. A brute-force optimization function can simply simulate thousands of random recipes and select that which minimizes error to the target. The result can then be stated in the convenient and familiar format of "parts" for ease of use on a palette. To make the results useful, a few constraints are needed. These are baseline values I consider reasonable from painting experience:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Maximum number of ingredients: 3-4</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Minimum fraction per ingredient: 5%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fraction resolution: 5%</span></li>
</ul>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Before decomposing digital colors, it's necessary to first scale the image's value (i.e. lightness/darkness) range to match that of the palette. This ensures that all colors are producible by enforcing that the darkest image color corresponds to the darkest color in the Schmid chart, and so on for the lightest. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This is analogous to a "Levels" adjustment in Photosh</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">op or <a href="https://docs.gimp.org/2.10/en/gimp-tool-levels.html">GIMP</a>. This is necessary due to Illuminant D65's intense outdoor brightness which un-saturates even the darkest paint mixes that appear nearly black when indoors.</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOw6ErVLwVjE0kGi8BS8tBy7xXQ-WjDhMs02NCJ3O9637jHQBSbd2DPb19qtnEnUWbwd916PWZ9lDldjiUD3TIqPWplh41OWSLkOnMJtTssX_M6qhGAP3NZQc5cwiBA8Swtqjkk5ZcabIt/s1600/rembrandt_scale_comparison.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="629" data-original-width="555" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOw6ErVLwVjE0kGi8BS8tBy7xXQ-WjDhMs02NCJ3O9637jHQBSbd2DPb19qtnEnUWbwd916PWZ9lDldjiUD3TIqPWplh41OWSLkOnMJtTssX_M6qhGAP3NZQc5cwiBA8Swtqjkk5ZcabIt/s640/rembrandt_scale_comparison.png" width="564" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span><br />
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Value scaling comparison; left: original/indoor, right: re-scaled/outdoor</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">
</span>
<br />
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Dem</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">o: Decomposing Existing Paintings</span></b></span><br />
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Rembrandt's pigment choices and working methods are subjects of academic study in and of themselves, but for the sake of illustration let's suppose that Rembrandt used my well-characterized palette of seven primaries. The color of any pixel in the image may then be decomposed into an error-minimized recipe for mixing. An ingredient quantity limit of three is imposed. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Representative samples are shown below.</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> </span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgG9kS8872p0O8I8FYt3pUfClT-alZIUlHEU88JQLhWx03HB0kAGHiu2-pVoOEe1_hcC3g6OTfVaUbZVslsef8NYg3RC6f9vV-YfwHLCB_T8WS-A1cuH_rg03Y3ItwnaiyN4XPjAz-XwFbR/s1600/rembrandt_demo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="801" data-original-width="1306" height="390" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgG9kS8872p0O8I8FYt3pUfClT-alZIUlHEU88JQLhWx03HB0kAGHiu2-pVoOEe1_hcC3g6OTfVaUbZVslsef8NYg3RC6f9vV-YfwHLCB_T8WS-A1cuH_rg03Y3ItwnaiyN4XPjAz-XwFbR/s640/rembrandt_demo.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Color decomposition demo on a Rembrandt self-portrait</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This painting is fairly monochromatic, and accordingly its recipes are dominated by burnt umber, titanium white, and cadmium yellow. Ultramarine blue, cadmium red, and sap green make only minor appearances. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Burnt sienna is not used at all, suggesting that it is not needed for this particular painting.</span></div>
<div style="text-align: left;">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuKZLT7h6697FRCrx2FjKVYhjQsYiTbgHK7NbiDk_IgWqLt-M9iq5SzI8H37luDr3rkrUsno0HYuN_dPMpEY1m_qfEKNw2pqPfZ6tFaBvDBaSTeZXcg-IrvXlmi4Pz4qcvB6-8cGYVSD3-/s1600/monet_demo.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="803" data-original-width="1578" height="324" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuKZLT7h6697FRCrx2FjKVYhjQsYiTbgHK7NbiDk_IgWqLt-M9iq5SzI8H37luDr3rkrUsno0HYuN_dPMpEY1m_qfEKNw2pqPfZ6tFaBvDBaSTeZXcg-IrvXlmi4Pz4qcvB6-8cGYVSD3-/s640/monet_demo.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Color decomposition demo on Monet's <i>Impression, Sunrise</i></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here's another demo on Monet's <i>Impression, Sunrise</i>, which crystallized the Impressionism movement. I've increased the ingredient quantity limit from three to four, and so the recipes become more complex and accurate. Monet uses titanium white heavily to create the pastel hues associated with aerial perspective and marine fog. Every paint is represented, although cadmium yellow is nearly absent. Cadmium red is reserved for the intense morning sun, and burnt sienna is de-emphasized in favor of the cooler burnt umber. The darkest colors are still about 20% white, so Monet is remarkably restrained in his use of darks.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Demoing on photos of existing paintings provides an intuitive and instructive result, but this method </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">works equally well <i>in reverse</i> with ordi</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">nary photographs. It could also be used to determine the </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">best primaries for a given image, or estimate the primary paint volumes required to minimize waste.<br /><br /><b> Demo: Creating New Paintings</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b>Working in reverse, any digital image may be translated into an oil painting. In these examples, all mixi</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ng recipes were generated </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">using brute-force color decomposition against a reference image. Unlike the Schmid color mixes which were precisely weighed, these recipe </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ingredients were measured by eye in the "parts" format, since weighing so many mixes would be impractical and un-painterly. Also, the error introduced from measuring recipes by eye opens the door to a degree of randomness and spontaneity that all great paintings possess.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Initial surveys of the reference images indicated that certain primaries were not necessary, so they were omitted from the palette. Since color decomposition is is done by random brute-force iteration, eliminating unnecessary primaries improves both the repeatability and quality of solutions. It also reduces paint waste and mixing complexity. This corroborates the traditional wisdom of the "limited palette" often advocated by art educators.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtJ2HewBYWXKZqlKq5a-Ke_-BuDJexAVafj7yN7XIW8G8L9PoVUplBGO1U_AsYSiYEzo30j3shUyDkkwsk8RP4a4NrIGyEr2WDvof1rwQ6Xcz8Bxqy21UaHCAXQuwb1BbSixxDnPnfCCXp/s1600/IMG_0605_out.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1196" data-original-width="1600" height="478" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtJ2HewBYWXKZqlKq5a-Ke_-BuDJexAVafj7yN7XIW8G8L9PoVUplBGO1U_AsYSiYEzo30j3shUyDkkwsk8RP4a4NrIGyEr2WDvof1rwQ6Xcz8Bxqy21UaHCAXQuwb1BbSixxDnPnfCCXp/s640/IMG_0605_out.jpg" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Still life; sap green and cadmium red omitted</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3C7mBP-dXAd_i0zrnAGx_oweQL1P2n2kRX2eN4LHUOvk8Yf1YolOyt4g7emClLHhEL8AaSezv9vHNWhUZ-aQ7Jh948UaV93w1_1VQfrkEi-v7guYMAqBV-uU4pSwokTl8h99JiqLBaUcT/s1600/IMG_0724_out.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1193" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3C7mBP-dXAd_i0zrnAGx_oweQL1P2n2kRX2eN4LHUOvk8Yf1YolOyt4g7emClLHhEL8AaSezv9vHNWhUZ-aQ7Jh948UaV93w1_1VQfrkEi-v7guYMAqBV-uU4pSwokTl8h99JiqLBaUcT/s640/IMG_0724_out.jpg" width="476" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Landscape; burnt sienna omitted</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Conclusions</b></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This article summarized some color science that is relevant to paintings, and methods for characterizing paint color mixing properties and decomposing colors into mixing recipes. All of this is carried out to the highest level of accuracy possible with a hobbyist's means. The resulting framework provides a new tool for creating accurate, engaging paintings, or decomposing existing paintings to better understand the artist's methods. Additional applications may include art restoration, forgery detection, and art education. My primary interest is to use this framework to develop color mixing intuition and support the creation of new paintings.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Acknowledgements</b></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Orion Taylor suggested the K* and S* </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">optimization which improved color prediction accuracy by 4%.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Drew Hmiel advised on spectroscopy aspects.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Bunny Harvey sparked my interest in painting and instilled the importance of color matching.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Serena Tolar clarified the terminology for color-measuring instruments.</span></li>
</ul>
</div>
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Appendix</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB2z_xZBm8FRA4YgrVMHT-8wKW-jIsptmPX2utBRhV9HpcmzbPaXQnwgyCovVLlAsoYtaDqultNbNioRyT2Aj39iAWZZgIF4Wd-pmYU_wUyxqnVcKb2Q-ebBU5F3ltgdw2UfnGOESgZPQW/s1600/WMB_equations.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="908" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB2z_xZBm8FRA4YgrVMHT-8wKW-jIsptmPX2utBRhV9HpcmzbPaXQnwgyCovVLlAsoYtaDqultNbNioRyT2Aj39iAWZZgIF4Wd-pmYU_wUyxqnVcKb2Q-ebBU5F3ltgdw2UfnGOESgZPQW/s640/WMB_equations.png" width="362" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Derivation of LLS method for finding K and S values, per </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Walowit, McCarthy, and Berns</span></div>
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></b>
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Sources</b><br />
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"<a href="http://www.heathershrewsbury.com/dreu2010/wp-content/uploads/2010/07/ModelingPigmentedMaterialsForRealisticImageSynthesis.pdf">Mode</a></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="http://www.heathershrewsbury.com/dreu2010/wp-content/uploads/2010/07/ModelingPigmentedMaterialsForRealisticImageSynthesis.pdf">ling Pigmented Materials for Realistic Image Synthesis</a>", Chet S. Haase and Gary W. Meyer, 1992.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Provides a good introduction to K-M, although their method for finding K and S causes overfitting.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"<a href="http://www.brucelindbloom.com/index.html?Eqn_Spect_to_XYZ.html">Useful Color Equations</a>", Bruce Lindbloom.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Provides all necessary equations for converting between XYZ, Lab, and RGB color spaces.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="http://cvrl.ioo.ucl.ac.uk/index.htm">Colour & Vision Research Laboratory</a>, Institute of Opthamology.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Provides observer and illuminant functions.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"<a href="http://gamma.cs.unc.edu/IMPASTO/publications/Baxter-IMPaSTo_Web-NPAR04.pdf">IMPaSTo: A Realistic, Interactive Model for Paint</a>", Baxter, Wendt, Lin, 2004.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Summarizes the linear least-squares method for finding K and S spectra.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"<a href="http://www.babelcolor.com/index_htm_files/A%20review%20of%20RGB%20color%20spaces.pdf">A Review of RGB Color Spaces</a>", Danny Pascale, BabelColor, 2003.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Provides some quantities for working with RGB color spaces.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"<a href="https://onlinelibrary.wiley.com/doi/pdf/10.1002/col.5080120609">An Algorithm for the Optimization of Kubelka-Munk Absorption and Scattering Coefficients</a>", Walowit, Mc</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Carthy, and B</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">erns, 1</span>987.<br />Provides a detailed walkthrough of the LLS method as applied to K-M.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="background-color: white; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">“</span><a href="https://www.richardschmid.com/ProductDetails.asp?ProductCode=SKUAP" style="text-decoration: none;"><span style="background-color: white; color: blue; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;">Alla Prima II</span></a></span><span style="background-color: white; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">”, Richard</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> Schmid, 2013.</span></span></span></div>
<div dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;">
<span style="background-color: white; color: black; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Describes the “Schmid Color Chart” method for use by painters.</span></span></div>
</div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com8tag:blogger.com,1999:blog-3278537004721616095.post-67245090459596991592019-03-20T20:46:00.000-07:002019-07-22T18:17:09.856-07:00March Madness 2019<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Last year I went into significant depth in developing <a href="http://www.kindofdoon.com/2018/03/predicting-march-madness-with-elo.html">a method for optimizing March Madness brackets</a>. I'm now focused on other projects, but since the code is easily reused, I decided to run it again this year. Aside from some under-the-hood improvements, I used the same method, incorporating one tweak from <a href="http://www.kindofdoon.com/2018/08/predicting-baseballs-postseason.html">my baseball prediction model</a>: accounting for home field advantage. This lumps together the effect of players, referees, and fans collectively tilting the odds slightly in favor of the home team. In the 2018-2019 NCAA season, the win rate for home teams was 51.22%, so the home field confers a 1.22% win probability advantage to the home team. While minor, this does slightly affect bracket outcomes this year as deep as the Final Four. This also demonstrates how famously unpredictable this tournament is, as a small tweak can ripple outward with significant effects. For the sake of expedience, I skipped bracket polling and used the "centrist" parameter set from last year.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here's a view of the regular season:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh57eXWjGhsNK-10ImAhzdEt9bYAb3Q2uglcGd-SIgmlcM0jrjZo5b0EPByDxSLjSsbz-kS6PGLSl6_7PEzttkmNPMQcHqVRXhxIY8rqMn0uzA3XCDp2CYz5DEVr5Dt_b0w-h2k-jIA-Io0/s1600/elo_regular_season_2019.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="475" data-original-width="750" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh57eXWjGhsNK-10ImAhzdEt9bYAb3Q2uglcGd-SIgmlcM0jrjZo5b0EPByDxSLjSsbz-kS6PGLSl6_7PEzttkmNPMQcHqVRXhxIY8rqMn0uzA3XCDp2CYz5DEVr5Dt_b0w-h2k-jIA-Io0/s1600/elo_regular_season_2019.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And a view of the postseason:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYAKMy1LvQPRuM1rAMs-GAl1QyzkFS4wFz2EbddH8QPewr_3i3zyw8T-HXM1LWSTt6qj_pTiwOqXZYuUKML6BBjWihdYeF-iiLa9ZwGQ-ATekvZScGZYanB3NGrY8bLARcSCBsOykUVmmf/s1600/march_madness_2019.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1061" data-original-width="1183" height="570" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYAKMy1LvQPRuM1rAMs-GAl1QyzkFS4wFz2EbddH8QPewr_3i3zyw8T-HXM1LWSTt6qj_pTiwOqXZYuUKML6BBjWihdYeF-iiLa9ZwGQ-ATekvZScGZYanB3NGrY8bLARcSCBsOykUVmmf/s640/march_madness_2019.png" width="640" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Like last year, I built my bracket in reverse, selecting the winner of each game as the team that has the highest probability of eventually winning the championship:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;"><b>Round of 32 Round of 16 Round of 8 ...of 4 ...of 2 ...of 1</b></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Duke Duke </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">VCU Duke </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Liberty Liberty </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Virginia Tech Duke </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Belmont LSU </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">LSU Michigan State </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Minnesota Michigan State </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Michigan State Duke </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Gonzaga Gonzaga </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Syracuse Gonzaga </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Murray State Florida State </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Florida State Gonzaga </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Buffalo Buffalo </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Texas Tech Buffalo </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Nevada Michigan </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Michigan Duke </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Virginia Virginia </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Oklahoma Virginia </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Wisconsin UC Irvine </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">UC Irvine Virginia </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Villanova Villanova </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Old Dominion Tennessee </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Cincinnati Tennessee </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Tennessee Houston </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">UNC UNC </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Utah State UNC </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">New Mexico State New Mexico State </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Kansas Houston </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Iowa State Houston </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Houston Houston </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Wofford Kentucky </span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Kentucky</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Source code is stored on <a href="https://github.com/kindofdoon/march_madness">my GitHub</a>.</span>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-30743488407508197302018-12-06T22:16:00.000-08:002018-12-20T17:42:55.737-08:00NYT "Resistance" Op-Ed: Part 2<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Overview</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Last month, I waded into forensic linguistics, </span><a href="http://www.kindofdoon.com/2018/11/authorship-of-nyt-resistance-op-ed.html" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">writing about</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> using natural language processing along with other contextual clues to identify the most likely author of the New York Times' controversial "</span><a href="https://www.nytimes.com/2018/09/05/opinion/trump-white-house-anonymous-resistance.html" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">I Am Part of the Resistance Inside the Trump Administration</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">", published anonymously by a "senior administration official". My conclusion was that the most likely author was </span><a href="https://en.wikipedia.org/wiki/Fiona_Hill_(presidential_advisor)" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Fiona Hill</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">, a senior-level but low-profile policy adviser on Russia and President Putin. </span><span style="background-color: #ffe599;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In this post, I set aside the "Resistance" op-ed and attempt to quantify more </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">generally how accurate my model may be, and what the implications are for my prediction.</span></span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /><b>Exploring Validation Data</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Like a game of <i>Guess Who</i>, the analysis began by gathering a shortlist of officials </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">considered to be frontrunners by media and betting venues - around 40 in total. For each candidate, I manually collected about 5,000 words of their writing from op-eds, essays, speeches, etc., attempting to maximize similarity to the subject, venue, and tone of the anonymous op-ed, though some compromises had to be made, as the various candidates speak and write for widely varying audiences and occasions. Each writing sample was around 1,000 words in length, and the number of samples per candidate was about five.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">My validation process is straightforward: from my original text data, withhold one writing sample (from a known author), train the model on the remaining data, and rank the candidates in terms of linguistic similarity to the withheld writing sample. Then, repeat this process for all remaining writing samples, around 200 in total, and assess. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The initial result is underwhelming:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLEASkwnvnc7d6s98G06SY5wCxP8MOlAjwfruqrQ14TwqCvGYsfn6e-UpapvG51q5N3Ti8Y3JZBYA24JjO27SLQuJNkV8CudJnAqmCicv-Ckp-wEbXabk1b81HFS-WhOBoWPvpfl3zQNz1/s1600/accuracy_by_author.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="711" data-original-width="654" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLEASkwnvnc7d6s98G06SY5wCxP8MOlAjwfruqrQ14TwqCvGYsfn6e-UpapvG51q5N3Ti8Y3JZBYA24JjO27SLQuJNkV8CudJnAqmCicv-Ckp-wEbXabk1b81HFS-WhOBoWPvpfl3zQNz1/s1600/accuracy_by_author.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A few authors (Hassett, Hill, McMahon, etc.) were correctly identified most of the time, but most were never correctly identified. However, from my limited understanding, forensic linguistics is more probabilistic than exact, and with such a large field of candidates, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">determining exact authorship of a relatively short writing sample is a long shot. To dig deeper, I set aside prediction accuracy and looked instead at relative rankings:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2AmDkjTGHIcxIQH53dZkoqfMc_2gT4qNlBkoaqfS8SNYVl2la3UR5FmUQT57x-7ACzJHPU7pAdcd5B3ViA3GSAduYbRXCm2ky3W5_VK1l2sVWud2okULr7qnDSonfVf1elVNnwHuZ_b1W/s1600/rank_by_author_self.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="711" data-original-width="651" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2AmDkjTGHIcxIQH53dZkoqfMc_2gT4qNlBkoaqfS8SNYVl2la3UR5FmUQT57x-7ACzJHPU7pAdcd5B3ViA3GSAduYbRXCm2ky3W5_VK1l2sVWud2okULr7qnDSonfVf1elVNnwHuZ_b1W/s1600/rank_by_author_self.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This is a bit more encouraging. ~85% of candidates rank in the top half for their respective writing samples, on average. At the bottom of the chart are linguistic chimeras, whose writing samples apparently are so disparate that the author sounds like multiple different voices. The more likely cause though is inconsistent text data with significant stylistic differences between samples, e.g. an op-ed vs. a prepared speech. Another issue exists: the same "usual suspects" frequently appear as top candidates across multiple different authors. Presumably this is due to their linguistic style being highly generic and often "mistaken" for others'. To get a sense of this, I plotted overall ranking averages for <i>all </i>writing samples, including those <i>by</i> the author and those <i>not</i>:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxP1bz0RuQQx26RsjCuCoL7W3UPL2AKmpS-Bsk8-M_x8vIivGL1kx0Mqm89NED8cmJ2JjDghLE543P3bG6Ki34f3VQrMraeUpG6TP1G90gfq3zgxfqeWRBqaWF_jHm0y0Q_uCd-txts_ag/s1600/false_positives_negatives.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="651" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxP1bz0RuQQx26RsjCuCoL7W3UPL2AKmpS-Bsk8-M_x8vIivGL1kx0Mqm89NED8cmJ2JjDghLE543P3bG6Ki34f3VQrMraeUpG6TP1G90gfq3zgxfqeWRBqaWF_jHm0y0Q_uCd-txts_ag/s1600/false_positives_negatives.png" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Another way to evaluate this method is by asking how it compares to random guesswork. Plotting this same data as a PDF and a CDF:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9-Ee5VVa6s51QtEmn7_V0HBwX2X-ENDcIRMpD2MoRbADrq4srvdN4SiphXfmT7yKFluTqUOSPhQPJ6eVNpdzeKn39dQfiPa3rWA7GwbJf2MVdCo0Nq-kr1oAszxzthpVXkoJtFZRtEVvf/s1600/pdf_cdf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="607" data-original-width="523" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9-Ee5VVa6s51QtEmn7_V0HBwX2X-ENDcIRMpD2MoRbADrq4srvdN4SiphXfmT7yKFluTqUOSPhQPJ6eVNpdzeKn39dQfiPa3rWA7GwbJf2MVdCo0Nq-kr1oAszxzthpVXkoJtFZRtEVvf/s1600/pdf_cdf.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Clearly, this method is substantially better than guesswork, though imperfect. The CDF also illustrates a very useful trade: pick the top candidate, and you're 15% likely to be correct. Top two picks is 18%, five is 40%, 10 is 65%, 15 is 75%, and so on. Looking at it from the opposite perspective, we can be 75% sure that the <i>bottom</i> (37-15) = 22 candidates are <i>not</i> the author, and ruling people out may be nearly as useful.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Implications for the NYT Op-Ed</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>On Fiona Hill</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Hill is shown here to be one of the most frequent false-positive candidates, i.e. the algorithm often erroneously attributes other authors' text to her. On the other hand, text by Hill is correctly attributed 85% of the time. <span style="background-color: #ffe599;">Per the PDF, I can now ascribe a confidence level of 15% to my prior Hill prediction.</span><span style="background-color: white;"> </span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="background-color: white;">This is </span></span><span style="background-color: white; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">low in absolute terms but high relative to a field of 37 candidates where a null probability is 2.7%.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>Widening the Net</i></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As explained under the CDF, allowing a larger field of authors increases prediction certainty. Let's re-examine a graph of overall linguistic similarity from my previous post:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGShZJcxRwptKxqNYmekBZLEmqSTg0X5zywHkUFI9C77ZmngjNUQufl713iY7GQFYXKLlH8e4dNoKWSuMjQF7kWJ7fPMi7EuMXw7p6gsOQSTYxxV65nUS4T_spbMoB8_yYUd1Em-JEzwQL/s1600/smoa.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="652" data-original-width="582" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGShZJcxRwptKxqNYmekBZLEmqSTg0X5zywHkUFI9C77ZmngjNUQufl713iY7GQFYXKLlH8e4dNoKWSuMjQF7kWJ7fPMi7EuMXw7p6gsOQSTYxxV65nUS4T_spbMoB8_yYUd1Em-JEzwQL/s1600/smoa.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">From the PDF, we see expectedly that the candidate ranked first is most likely to be correct. Continuing on, the next-most likely candidate is counter-intuitively <i>not</i> the candidate ranked second, but ranked fourth, and so on down the list. So using similarity together with the PDF, if we pick a confidence level, e.g. 60%, we can pick the top N candidates such that we are 60% confident that the author is contained in the set, per the CDF. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For a simple preponderance of the evidence, i.e. >50% certainty, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">the field required is 6 </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">candidates<span style="background-color: white;">. </span></span><span style="background-color: white;">So the author is <i>probably </i>one of:</span></span><br />
<ol><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">
<li>Fiona Hill</li>
<li>Andrew Wheeler</li>
<li>Mike Pence</li>
<li>Rick Perry</li>
<li>Nikki Haley</li>
<li>Jared Kushner</li>
</span></ol>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">
</span>
<br />
<div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Convers</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ely, the author is <i>probably not </i>any of the remaining candidates. But language can be deceptive</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">, as this is still essentially a coin toss scenario with low certainty. I'd rather be at least "pretty sure". So I'll increase the confidence interval to 80%, and from the CDF see tha</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">t a field of 16 candidates is required. <span style="background-color: #ffe599;">So, we can be <i>pretty sure </i>that the author is one of:</span></span></span><br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fiona Hill</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Andrew Wheeler</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mike Pence</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Rick Perry</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Nikki Haley</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jared Kushner</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ryan Zinke</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Bolton</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mike Pompeo</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Kevin Hassett</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Sullivan</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Linda McMahon</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Steven Mnuchin</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Betsy DeVos</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jim Mattis</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Kelly</span></li>
</ol>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="background-color: #ffe599;">And, we can </span><span style="background-color: #ffe599;">be</span></span><span style="background-color: #ffe599; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> <i>pretty sure</i> that the author is <i>not</i>:</span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mick Mulvaney</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Joseph Simons</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Alex Azar</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Robert Wilkie</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Alexander Acosta</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ben Carson</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Raj Shah</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Larry Kudlow</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ivanka Trump</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Gina Haspel</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ajit Pai</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jeff Sessions</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Dan Coats</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Elaine Chao</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Kellyanne Conway</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jon Huntsman</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Wilbur Ross</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Melania Trump</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Kirstjen Nielsen</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Robert Lighthizer</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Sonny Perdue</span></li>
</ul>
</div>
<div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Further Spec</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ulation</span></i></span></div>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Setting aside linguistic similarity and and looking at the "pretty sure" shortlist, suppose we eliminate all officials not involved in foreign policy, the primary policy area of the "Resistance" op-ed:</span><br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fiona Hill</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Andrew Wheeler</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mike Pence</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Rick Perry</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Nikki Haley</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jared Kushner</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Ryan Zinke</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Bolton</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mike Pompeo</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Kevin Hassett</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Sullivan</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Linda McMahon</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Steven Mnuchin</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Betsy DeVos</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jim Mattis</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>John Kelly</strike></span></li>
</ol>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Suppose we then eliminate </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">all candidates who have denied writing the op-ed:</span></span><br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fiona Hill</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Mike Pence</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Nikki Haley</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jared Kushner</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>John Bolton</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Mike Pompeo</strike></span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Sullivan</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><strike>Jim Mattis</strike></span></li>
</ol>
<ol>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">That leaves just:</span></div>
<div>
<ol>
<li><span style="background-color: white; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fiona Hill</span></li>
<li><span style="background-color: white; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jared Kushner</span></li>
<li><span style="background-color: white; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Sullivan</span></li>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And that's as far as I want to take this now. I welcome further speculation and remarks in the comments below.</span></div>
</div>
</div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com2tag:blogger.com,1999:blog-3278537004721616095.post-10112190078215044522018-11-15T22:51:00.000-08:002018-11-17T16:15:09.499-08:00Authorship of the NYT "Resistance" Op-Ed<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In September, The New York Times published "<a href="https://www.nytimes.com/2018/09/05/opinion/trump-white-house-anonymous-resistance.html">I Am Part of the Resistance Inside the Trump Administration</a>", an incendiary op-ed by an anonymous senior official. Since then, there has been wild speculation and sleuthing about the identify of the author. In this post, I aim to cut through the noise and identify the most likely author using natural language processing and other contextual clues.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">First I assembled a list of candidates from <a href="https://en.wikipedia.org/wiki/I_Am_Part_of_the_Resistance_Inside_the_Trump_Administration#Identity_of_the_author">Wikipedia</a>, <a href="https://www.predictit.org/markets/detail/4823/Who-will-NYT-confirm-as-anonymous-op-ed-author-in-2018">PredictIt</a>, and a few other informal forums. It cover</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">s all the top contenders, though isn't exhaustive due to the sprawl of the executive bureaucracy.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ajit Pai, Chairman of the Federal Communications Commission</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Alex Azar, Secretary of Health and Human Services</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Alexander Acosta, Secretary of Labor</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Andrew Wheeler, Acting Administrator of the Environmental Protection Agency</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ben Carson, Secretary of Housing and Urban Development</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Betsy DeVos, Secretary of Education</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Christopher Wray, Director of the Federal Bureau of Investigation</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Dan Coats, Director of National Intelligence</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Don McGahn, White House Counsel</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Elaine Chao, Secretary of Transportation</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fiona Hill, Senior Director for European and Russian Affairs</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Gina Haspel, Director of the CIA</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ivanka Trump, Senior Adviser to the President</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jim Mattis, Secretary of Defense</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jared Kushner, Senior Adviser to the President</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jeff Sessions, Attorney General</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Sullivan, Deputy Secretary of State</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Kelly, White House Chief of Staff</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">John Bolton, National Security Advisor</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Jon Huntsman, Ambassador to Russia</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Joseph Simons, Chairman of the Federal Trade Commission</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Kellyanne Conway, Presidential Counselor</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Kevin Hassett, Chairman of the Council of Economic Advisors</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Kirstjen Nielsen, Secretary of Homeland Security</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Larry Kudlow, Director of the National Economic Council</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Linda McMahon, Administrator of the Small Business Administration</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Melania Trump, First Lady of the United States</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mick Mulvaney, Director of the Office of Management and Budget</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mike Pence, Vice President of the United States</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mike Pompeo, Secretary of State</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Nikki Haley, Ambassador to the United Nations</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Raj Shah, White House Principal Deputy Press Secretary</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Rick Perry, Secretary of Energy</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Robert Lighthizer, United States Trade Representative</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Robert Wilkie, Secretary of Veterans Affairs</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ryan Zinke, Secretary of the Interior</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Sarah Sanders, White House Press Secretary</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Sonny Perdue, Secretary of Agriculture</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Stephen Miller, Senior Policy Advisor</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Steven Mnuchin, Secretary of the Treasury</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Wilbur Ross, Secretary of Commerce</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Zachary Fuentes, Deputy Chief of Staff</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For each candidate, I scraped around 2,000 to 10,000 raw words of their writing, attempting to use material that was maximally similar to the op-ed in subject, setting, and formality. For a few candidates, this was not possible as their body of published writing was too small or informal to make a useful comparison:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Christopher Wray, Director of the Federal Bureau of Investigation</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Don McGahn, White House Counsel</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Sarah Sanders, White House Press Secretary</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Stephen Miller, Senior Policy Advisor</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Zachary Fuentes, Deputy Chief of Staff</span></li>
</ul>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I then broke this raw text into sentence fragments using a series of regular expressions, removing numbers, quotes, and proper nouns. The intention was to make the text maximally subject-independent to focus more on writing style/voice. Here's an example from Dan Coats:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">"Since 1998 when this terrorist payments program reportedly first began, the United States has contributed more than $4.6 billion (in constant dollars) to the PA. The great majority of this amount has been in straight budgetary support to the PA, enabling it to meet its budgetary commitments."</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This is parsed as:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">since</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">when this terrorist payments program reportedly first began</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">the</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">has contributed more than</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">billion</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">in constant dollars</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">to the</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">the great majority of this amount has been in straight budgetary support to the</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">enabling it to meet its budgetary commitments</span></div>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">After parsing all the text, I extracted a dictionary of all unique words across all text, including the anonymous op-ed. Then, I generated Markov matrices to track word transition probabilities, i.e. </span><span style="font-family: "courier new" , "courier" , monospace;">Mrkv(word_x, word_y)</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> gives the probability that </span><span style="font-family: "courier new" , "courier" , monospace;">word_y</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> will follow </span><span style="font-family: "courier new" , "courier" , monospace;">word_x</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> in a sentence fragment. I also extracted at the overall distribution of words, i.e. </span><span style="font-family: "courier new" , "courier" , monospace;">Dist(word_x)</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> gives the frequency of </span><span style="font-family: "courier new" , "courier" , monospace;">word_x</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> in the author's overall writing. Both </span><span style="font-family: "courier new" , "courier" , monospace;">Mrkv</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> and </span><span style="font-family: "courier new" , "courier" , monospace;">Dist</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> are created using "hit counts" and then normalized to the word count, and so their values represent probabilities.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With the Markov matrices and word distributions known, I took the overall "similarity" score as:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">similarity = -sum(abs(Candidate - Op_Ed))</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A similarity score is generated for both </span><span style="font-family: "courier new" , "courier" , monospace;">Mrkv</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> and </span><span style="font-family: "courier new" , "courier" , monospace;">Dist</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">; Markov similarity gives a feel for how words/patterns flow together, while distribution similarity gives a feel for word choice. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here are the results:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_3xhYfCK_Mh4c0W1RfrSXr1V9sgMFPcqrThUwlOnD-W11TTvlwQQyId5j8JgQmB5vAg-B23re2ulN5r4HKX5oSqCxPWNk3NADrz7xpXOEjE_NAz8baaO4jR1lMedfUyNBwnklWnx0uq8_/s1600/fig_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="733" data-original-width="735" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_3xhYfCK_Mh4c0W1RfrSXr1V9sgMFPcqrThUwlOnD-W11TTvlwQQyId5j8JgQmB5vAg-B23re2ulN5r4HKX5oSqCxPWNk3NADrz7xpXOEjE_NAz8baaO4jR1lMedfUyNBwnklWnx0uq8_/s1600/fig_1.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjpd-e0G-zWHpwHmtWp11GHHf2KIeRtaczlnR4GdGvOsc-va2FJDdo0lbRwE4_WvthtlKV1wvLyyuGUN1aqMjz_0BbGtsLXnfiAER80qiFS0ckFNNhlEjjzMn73GOf5f8xXSisWkQO5bn4/s1600/fig_4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="734" data-original-width="735" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjpd-e0G-zWHpwHmtWp11GHHf2KIeRtaczlnR4GdGvOsc-va2FJDdo0lbRwE4_WvthtlKV1wvLyyuGUN1aqMjz_0BbGtsLXnfiAER80qiFS0ckFNNhlEjjzMn73GOf5f8xXSisWkQO5bn4/s1600/fig_4.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Notably, Hill scores highest in both similarity metrics. However, before jumping to conclusions, note that although </span><span style="font-family: "courier new" , "courier" , monospace;">Mrkv</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> and </span><span style="font-family: "courier new" , "courier" , monospace;">Dist</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> are normalized to word counts, there is an additional correlation between word count and similarity. A typical op-ed is ~1,000 words, so theoretically could yield 1,000 word combinations (neglecting grammar). Compare this to the 10,000-word dictionary, which yields 100,000,000 combinations. Our language is too rich to "exhaust" a person's speech in even 10,000 words because unique combinations are so plentiful. In this case, the more text provided for a candidate, the higher they score in similarity, because they have more opportunity to stumble upon a rare combination matching the op-ed. So an additional normalization is necessary.</span></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF96q1K7TsWQ6nLf7VhsUO2AGcD_NUeQmoCnYQ5fOi6qUqogrxxbu44oU7VjLcQaIrVUrFMb5oylFR9XuANZJEz7C44_eogTBPJ0uxIt_uwO86qKJfbE_f5Z1_9f0HKGqwPUUBJgeaK_a7/s1600/fig_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="730" data-original-width="701" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgF96q1K7TsWQ6nLf7VhsUO2AGcD_NUeQmoCnYQ5fOi6qUqogrxxbu44oU7VjLcQaIrVUrFMb5oylFR9XuANZJEz7C44_eogTBPJ0uxIt_uwO86qKJfbE_f5Z1_9f0HKGqwPUUBJgeaK_a7/s1600/fig_2.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim2HlLT_rc6o352XmI8JdPSXBEqS4W8MP4ZTlQjWL4imABUuha_f3C_DXOREnTpUN28s5m-Cg1sMkobCXvd9lK7tZTkvX67iQeCobHuuOqWamljnoDtnPnLjsIuaIyfrAWAgFMf6lwxuMs/s1600/fig_5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="730" data-original-width="701" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEim2HlLT_rc6o352XmI8JdPSXBEqS4W8MP4ZTlQjWL4imABUuha_f3C_DXOREnTpUN28s5m-Cg1sMkobCXvd9lK7tZTkvX67iQeCobHuuOqWamljnoDtnPnLjsIuaIyfrAWAgFMf6lwxuMs/s1600/fig_5.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">To account for this, I re-scored the Markov and distribution similarities as the vertical distance off the linear fit line, and re-evaluated. The intent was to make results maximally dependent on style, not length.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXEGDGzpVoVwSwMddcPSZduGL2QQ3NQ83Zl_VLPeKABvvwueCAtYjYFxFDqtdlfvMk0hO8-_lSsGSKPW49gtENkUFClSEtWLHGxlSg-Bokc4smExE2b362vPvt-NpGi5xohJRtLQQE2Bms/s1600/fig_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="733" data-original-width="735" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXEGDGzpVoVwSwMddcPSZduGL2QQ3NQ83Zl_VLPeKABvvwueCAtYjYFxFDqtdlfvMk0hO8-_lSsGSKPW49gtENkUFClSEtWLHGxlSg-Bokc4smExE2b362vPvt-NpGi5xohJRtLQQE2Bms/s1600/fig_3.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsa5dAXVrMgNqx3auUqm4BkIHvyUNs3mN1rqPd_of1BRQUB2v2wDY4dbmzRRVuZpk8iodx1rYVW65ds3SSAuVdX70VzpzIzwwOdsRrvo9AwhzYjRy7GdmlDkFEP_oE471rt2OfQ1X9nDTW/s1600/fig_6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="733" data-original-width="735" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsa5dAXVrMgNqx3auUqm4BkIHvyUNs3mN1rqPd_of1BRQUB2v2wDY4dbmzRRVuZpk8iodx1rYVW65ds3SSAuVdX70VzpzIzwwOdsRrvo9AwhzYjRy7GdmlDkFEP_oE471rt2OfQ1X9nDTW/s1600/fig_6.png" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Only two candidates rank in the top tier for both similarity metrics: Fiona Hill (#1, #2) and John Bolton (#3, #1). Hill's case is stronger from the linguistic perspective, and the gap widens further upon considering the additional circumstantial evidence.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Hill is one of only six people on this shortlist to have not denied writing the op-ed. (The others are Ivanka, Kushner, Sullivan, Kelly, and Miller. Of this set, Ivanka, Kushner, and Kelly appear to be exonerated by the similarity metrics; John Sullivan is toward the upper end of the similarity spectrum, but not suspiciously so; Miller could not be analyzed as he is unpublished.) Hill's background is in academia and policy, and her most-recent <a href="https://www.brookings.edu/wp-content/uploads/2016/07/fp_20170207_hill_cv.pdf">publications</a>, shown below, revolve around Russia and Putin, both of which are notably mentioned multiple times in the op-ed that is otherwise light on specifics.</span><br />
<br /></div>
<div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">“What makes Putin tick and what the West should do,” Fiona Hill and Clifford Gaddy,Brookings Report (online), January 13, 2017</span></li>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">
<li>“Dealing with a simmering Ukraine-Russia conflict,” Fiona Hill and Steven Pifer, Brookings</li>
<li style="font-family: "helvetica neue", arial, helvetica, sans-serif;">“Election 2016 and America’s Future” series (online), October 6, 2016</li>
<li style="font-family: "helvetica neue", arial, helvetica, sans-serif;">“3 reasons Russia’s Vladimir Putin might want to interfere in the US presidential elections,” Vox (online), July 27, 2016</li>
<li style="font-family: "helvetica neue", arial, helvetica, sans-serif;">“Putin: The one-man show the West doesn’t understand,” Bulletin of the Atomic Scientists, April 13, 2016</li>
<li style="font-family: "helvetica neue", arial, helvetica, sans-serif;">“Understanding and deterring Russia: U.S. policies and strategies,” Testimony to the House Armed Services Committee, February 10, 2016</li>
</span></ul>
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">
</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Bolton has <a href="https://twitter.com/GMarquis45/status/1037832433603948545?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1037832433603948545&ref_url=https%3A%2F%2Fthehill.com%2Fhomenews%2Fadministration%2F405483-bolton-fbi-chief-join-those-denying-writing-anonymous-op-ed">denied authorship</a>, which decreases his likelihood though doesn't rule him out. He has a long history of military and government involvement and is known for being outspoken in his <a href="https://www.wsj.com/articles/the-legal-case-for-striking-north-korea-first-1519862374">controversial views</a>, making him further less likely to carry out this secretive act.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">So, between the linguistic similarities, lack of denial, connection to the subject matter, and personality cues, all signs point to Hill. What about the possibility of the op-ed being written <i>in the voice of Hill</i> by a third party for some ulterior purpose? To some extent we can lean on the New York Times' credibility and rule out this possibility; presumably the editors verified the author's identity before publication. It's remotely possible that a verifiable official imitated Hill in writing the op-ed, perhaps to further hide their identity. However, due to the sophistication required for this task, it seems very unlikely.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="background-color: #ffe599; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">It's not clear what the author hoped to achieve with this op-ed, or how they expected to remain anonymous from a position of national visibility in the age of Twitter and instant, continuous press circulation. Either way, I expect we will eventually know the author's identity, and I expect it will be...Fiona Hill.</span><br />
<span style="background-color: #ffe599; font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Footnotes</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Despite widespread interest, there seems to be little actual data-driven analysis toward answering the authorship question. H</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ere's what other authors have found with similar approaches:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<ul>
<li><a href="https://www.bbc.com/news/world-us-canada-45435813" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">BBC</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> suggests the author is Mike Pence based on "the author's stylistic traits"</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="http://varianceexplained.org/r/op-ed-text-analysis/">David Robinson</a> analyzed tweets, finding D. Trump, Sanders, and Pence most likely</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="http://maxberggren.se/2018/09/07/who-wrote-the-op-ed/">Max Berggren</a> analyzed tweets, finding DeVos, Carson, and Azar most likely</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And for additional qualitative commentary:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<ul>
<li><a href="http://wp.lancs.ac.uk/drclaireh/2018/09/06/how-to-be-a-recreational-forensic-linguist/" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Claire Hardaker</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> concludes: "I don’t think forensic linguistics can solve this one"</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><a href="https://www.washingtonpost.com/politics/the-sleeper-cells-have-awoken-trump-and-aides-shaken-by-resistance-op-ed/2018/09/05/ecdf423c-b14b-11e8-a20b-5f4f84429666_story.html?utm_term=.aa91813c34ef">The Washington Post</a>, conversely, writes: "The outing of the op-ed’s author is virtually inevitable, according to forensic linguists"</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Source code and text data are available on </span><a href="https://github.com/kindofdoon/nyt_resistance_op_ed" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">my GitHub</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">.</span></div>
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-55522900371475814922018-10-16T21:45:00.002-07:002018-11-21T17:28:10.301-08:00Veganism and Energy Efficiency<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Summary</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In this post, I discuss how veganism relates to energy efficiency, evaluate a few specific livestock common in the U.S., and conclude that factory farming techniques are significantly wasteful of food energy. In closing, I suggest some ideas for how people can adjust their diets to be more environmentally sustainable, especially if they are not interested in veganism.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Background</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I've been vegan since May 2017. I made the switch for a few reasons:</span></span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">My brother adopted veganism about a year prior, and convinced me that the diet could be as healthy, or healthier, compared to an omnivorous diet, overturning my misconception that vegans were inherently nutritionally deficient.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A growing body of informal and academic work supports the idea that veganism is more environmentally sustainable that omnivorism.</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Now about 1.5 years later, I've noticed many benefits: increased speed, stamina, energy, and near-elimination of common colds. Contrary to popular misconceptions, my food spending has decreased slightly (despit</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">e inflation), and I've naturally maintained my pre-veganism weight while becoming leaner and more muscular with increased exercise.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtPK80nVa95Z6rVW6KcXJLqXXXxy9F_X8kKE7pTVOj5FrXmkUP3AqGzFdeeyviaCs6Zb9c7EVGtZ2DK0CL6CXNRbXDPb-y2_rw-ERRxKsO1Gw0v0YtpE-1YMz1Qs1AbEkEFJ0mqIj5RPwf/s1600/veganism_grocery_spending_impact.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="475" data-original-width="694" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtPK80nVa95Z6rVW6KcXJLqXXXxy9F_X8kKE7pTVOj5FrXmkUP3AqGzFdeeyviaCs6Zb9c7EVGtZ2DK0CL6CXNRbXDPb-y2_rw-ERRxKsO1Gw0v0YtpE-1YMz1Qs1AbEkEFJ0mqIj5RPwf/s1600/veganism_grocery_spending_impact.png" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Effect of veganism on my combined grocery + restaurant spending</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br />My interest in veganism is primarily as it relates to environmental sustainability, and I've read a goo</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">d deal on the topic. Though the big-picture argument is cohesive and compelling, much of the writing on it is lacking in technical rigor. Here are some typical examples:</span></div>
<blockquote class="tr_bq">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"Eating lower down on the food chain provides a massive savings in terms of how much energy and resources you need. If you're on the third trophic level and you eat herbivores, the animals you eat contain only 10 percent of the energy originally stored by the plants they consumed...[In] general, eating lower on the food chain is always a more efficient practice."</span></blockquote>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">source: <a href="https://sciencing.com/being-vegetarian-conserve-overall-energy-trophic-levels-3342.html">Sciencing: "How Does Being a Vegetarian Conserve Overall Energy in Trophic Levels?"</a></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Seems reasonable, but herbivores can digest food sources that humans can't, like grass and stovers, so not all food is equally valuable to all trophic levels. The food chain is more like a web rather than a neatly-ordered chain. Another example:</span></span><br />
<blockquote class="tr_bq">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"It takes more than 2,400 gallons of water to produce 1 pound of meat; 1 pound of wheat takes 25 gallons."</span></blockquote>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">source: <a href="http://humanefacts.org/infographic/">HumaneFacts: "Environmental Impact of Raising Animals for Food"</a></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Maybe so, but pound-for-pound, meat is much more nutritious and energetic (i.e. higher in calories) than wheat, so maybe the additional water is a good investment? From this statistic alone there's not enough information to make a meaningful conclusion.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<b><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A Litmus Test for Veganism</span></b></div>
<div style="text-align: left;">
<b><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></b></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Unsatisfied with writing on veganism, <span style="background-color: #ffe599;">I sought to develop my own metric: a litmus test to gauge the efficacy of veganism in improving environmental sustainability.</span> The food chain starts with plants, and consequently all other trophic levels depend on plants. Growing plants is non-negotiable. So in effect, a referendum on veganism is a referendum on livestock cultivation. Should we do it, or not?</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In an abstract sense, livestock can be viewed as energy conversion machines that convert plant products like corn and hay to animal products like meat and eggs. The figure of merit for an energy conversion machine is its efficiency - that is, its output divided by its input. The outputs are straightforward - meat, milk, and eggs. The inputs are the animal's diet - typically, some combination of corn, grains, legumes, and forages (i.e. grass, hay, stovers, etc). This was my starting point that I refined as I learned more about the modern food supply system.</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Discourse on environmental impacts of mass agriculture tends to focus on </span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">land/water use, carbon emissions, and pollution, and these are all important considerations. However, I decided to focus on energy efficiency instead, for a few reasons:</span><br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>To clarify a perceived gap:</u> pro-vegan sources usually ignore the fact that livestock are significant consumers of agricultural waste with digestive systems that are fundamentally different from humans', thereby underestimating their practical efficiency.</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>To reduce the problem to its most essential form:</u> energy is arguably the most fundamental agricultural resource, as it can be traded for water (e.g. through desalination), land (e.g. through terracing), carbon emissions (e.g. through sequestration), or pollution cleanup.</span></li>
</ol>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Effect of Diet on Energy Efficiency</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">All energy transfers are less than 100% efficient, so </span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">eliminating unnecessary intermediate trophic levels, and their associated energy transfers, increases overall </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">energy efficiency</span>. Cultivating the world's staple crops like wheat, corn, beans, and rice produces a great deal of agricultural waste </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">that humans can't digest, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">but are readily digested by ruminant livestock. As there are no intermediate trophic levels between livestock and forages, and no other uses for forages, it seems reasonable that they be fed for livestock.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">However, in the factory farming model which dominates U.S. agriculture, forages are a <i>secondary</i> food source for modern livestock, with the primary food source being, most typically in the U.S., corn. These reasons for this are complex, but include heavy tax subsidies for corn, high meat demand, and consumer preference for marbling in meat. Further, </span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">non-ruminant livestock consume no forages at all.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Fro</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">m an energy-efficiency perspective, this is sub-optimal as corn and other livestock feed staples are human-edible. In economic terms, feeding human-edible food to livestock is essentially an "investment" t</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">hat only makes sense if the payout in animal products exceeds the initial investment. In this formulation, forages are excluded from the "investment", since they are not human-edible and have no human value. To quantify this exchange, I developed a m</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">etric called "Return on Useful Energy Input" (RUEI), which is calculated over a livestock's lifetime by:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br />RUEI = (E_ou</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; text-align: center;">tput, all sources - E_input, human-edible sources) / E_input, human-edible sources</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br />By design, RUEI has som</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">e useful properties: it's a dimensionless percentage, enabling direct comparison of dispar</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ate livestock and diets, and it's meaningfully signed: positive RUEI indicates a net gain, and negative RUEI a net loss. Unlike thermodynamic efficiency, which is always 0-100%, RUEI can be negative or exceed 100%, since it is not an efficiency but rather a normalized return.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<b><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">World Livestock Overview</span></b><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI indicates if any given livestock is a good idea or a bad idea from an energy-efficiency perspective. Which livestock to analyze? Here's what the global herd looks like by populatio</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">n:<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAT5HpqoyiJoLwpMb42B3_dMKOsOBa198zivRngvKaTbVgXDAd2ovMbrPlqm1HDO4mwp8oUcuEYzttl-M6Na_fo-UHfUJgx1yeH45GAOYRzTWfjEQoCYHn4kESR0ScYSRAYpI4GhvLDvsC/s1600/populations.png"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAT5HpqoyiJoLwpMb42B3_dMKOsOBa198zivRngvKaTbVgXDAd2ovMbrPlqm1HDO4mwp8oUcuEYzttl-M6Na_fo-UHfUJgx1yeH45GAOYRzTWfjEQoCYHn4kESR0ScYSRAYpI4GhvLDvsC/s1600/populations.png" /></a></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And by to</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">t</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">al biomass:<br /><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY17Sl0J2wMnSvYTNNyR81LzAyNWIntz7oVZTQY3SEGLeswIreh19UEH9UMSeLSxnG0ip6Z8S-duLydI856HFJoYP-GCqBb1YQ_KhTrSp_An7sR0_xBh8eRMdeFHX1YlBQdKe1UbBaINap/s1600/biomass.png"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY17Sl0J2wMnSvYTNNyR81LzAyNWIntz7oVZTQY3SEGLeswIreh19UEH9UMSeLSxnG0ip6Z8S-duLydI856HFJoYP-GCqBb1YQ_KhTrSp_An7sR0_xBh8eRMdeFHX1YlBQdKe1UbBaINap/s1600/biomass.png" /></a><br /><br />To limit sc</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ope, I restricted my analysis to three animals with sufficient data available and that are of prima</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ry importance in the U.S.: cows, pigs, and chickens.<br /><br /><b> Assumptions and Limitations</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Before proceeding, some notes on my simplifying assumptions used to calculate RUEI: </span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Feed ingredient proportions do not change with time </span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Feed amount is proportional to animal mass </span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Animal mass increases linearly with time up to mature mass, after which it is constant </span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Animal products not included in the dressing percentage yield no food </span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Forages and distiller's grains are considered human-inedible and are not included in RUEI </span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">All other food sources are considered human-edible and are included in RUEI </span></li>
</ul>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">And a few notes on overall scope:</span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Other environmental impacts like carbon emissions, land usage, water usage, and pollution are neglected to focus on energy efficiency </span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Nutrition content, aside from calories, is neglected </span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Energy costs upstream and downstream of livestock are neglected; system boundaries are drawn strictly around the livestock only</span></li>
</ul>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /><b>Cows</b><br /><br /> Cows b</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">reeds are specialized for either milk or beef production. Both cases are analyzed below.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>Dairy cows</u></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A typical dairy cow is first mated or inseminated at about 13 months old. After a 9 month gestation, the cow gives birth and produces milk for about 10 months, the "calving period". On average a cow has about 1.7 calving periods before it is no longer profitable, after which it is slaughtered. Over its lifetime, a dairy cow produces about 3,300 gallons of milk and yields about 400 kg of beef when slaughtered, with a dressing percentage of 60%. I considered two diets describing TMRs (total mixed rations), the daily food allotted to each cow, foun</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">d on farm blogs:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: none; table-layout: fixed; width: 0px;" xmlns="http://www.w3.org/1999/xhtml"><colgroup><col width="127"></col><col width="86"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Ingredient"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ingedient</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Mass, lb"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mass, lb</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Alfalfa hay"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Alfalfa hay</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":28}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">28.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Corn"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Corn</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":13.5}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">13.50</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Corn stover"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Corn stover</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":35}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">35.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Cotton seed"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Cotton seed</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":6}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">6.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Oat flour"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Oat flour</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":4.5}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">4.50</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Soybeans"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Soybeans</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":5}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">5.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Wheat"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Wheat</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":15}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">15.00</span></td></tr>
</tbody></table>
</div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">source: <a href="http://www.dairycarrie.com/2013/12/20/what-do-cows-eat/">Dairy Carrie: "What Do Cows Eat"</a></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This diet is representative of more-traditional, non-factory-style feeds, with forages as the primary feed and grains secondary. For obvious reasons, factory farms do not publish their feed recipes as transparently as small farms. The energy breakdown over the cow's lifetime, in round num</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">bers, is:</span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Milk output: 9,000,000 Cal</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Meat output: 1,000,000 Cal</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Feed input, all sources: 198,000,000 Cal</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Feed input, human-edible sources: 43,000,000 Cal</span></li>
</ul>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As can be seen from the data, the cow produces significantly less useful energy than it consumes, even after accounting for its forages. The RUEI is:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; text-align: center;">RUEI = (E_output, all sources - E_input, human-edible sources) / E_input, human-edible sources</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif; text-align: center;">RUEI = ((9,000,000+1,000,000) - 43,000,000) / 43,000,000</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI: -77%</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In other words, the cow is a net useful energy loss; the return is -77% of the useful input, i.e. an input of 100 useful plant calories yields only 23 animal calories. Repeating the same analys</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">is f</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">or </span>an alternate diet from a similar-size farm:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: none; table-layout: fixed; width: 0px;" xmlns="http://www.w3.org/1999/xhtml"><colgroup><col width="127"></col><col width="86"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Ingredient"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ingredient</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Mass, lb"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Mass, lb</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Alfalfa hay"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Alfalfa hay</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":12}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">12.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Canola meal"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Canola meal</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":2}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Corn"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Corn</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":9}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">9.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Corn stover"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Corn stover</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":62}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">62.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Cotton seed"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Cotton seed</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":4}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">4.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Soybean meal"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Soybean meal</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":3}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">3.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Wheat stover"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Wheat stover</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":12}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">12.00</span></td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Whey"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Whey</span></td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":10}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">10.00</span></td></tr>
</tbody></table>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">source: <a href="https://slowmoneyfarm.wordpress.com/2012/06/11/what-do-cows-eat/">Slow Money Farm: "What Do Cows Eat"</a></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI: -68%</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>Beef cows</u></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Data on specific beef cow diets proved difficult to find, so I re-used the diet information for the dairy cows. Beef cows produce no milk and yield a similar amount of meat, though their lives are much shorter at around 18 months.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI: -88%</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Pigs</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Pigs are slaughtered at around 4 months old, with a dressing percentage of 72%, and consume about 2.6% of their body weight daily. Most pigs are fed only corn, soybean meal, and sometimes wheat. Specific pig diets were found abundantly, and seven specific diets were analyzed. Representative highlights are shown below:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"[Baseline] reference diet"</span><br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: none; font-family: arial, sans, sans-serif; table-layout: fixed; width: 0px;" xmlns="http://www.w3.org/1999/xhtml"><colgroup><col width="144"></col><col width="86"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Ingredient"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Ingredient</td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Mass, lb"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Mass, lb</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Corn"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Corn</td><td data-sheets-formula="=R[-8]C[0] * (680/(680+100+200)) * R[-13]C[6]/conv!R[-22]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":5.148571428571428}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">5.15</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Wheat"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Wheat</td><td data-sheets-formula="=R[-9]C[0] * (100/(680+100+200)) * R[-14]C[6]/conv!R[-23]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.7571428571428571}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.76</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Soybean meal"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Soybean meal</td><td data-sheets-formula="=R[-10]C[0] * (200/(680+100+200)) * R[-15]C[6]/conv!R[-24]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":1.5142857142857142}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">1.51</td></tr>
</tbody></table>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">source: <a href="https://www.ipic.iastate.edu/publications/370.examplediets.pdf">Niche Pork Production: "Example Pig Diets"</a></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI: -27%</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"Example [diet] including cooked, full-fat soybeans"</span><br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: none; font-family: arial, sans, sans-serif; table-layout: fixed; width: 0px;" xmlns="http://www.w3.org/1999/xhtml"><colgroup><col width="144"></col><col width="86"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Ingredient"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Ingredient</td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Mass, lb"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Mass, lb</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Corn"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Corn</td><td data-sheets-formula="=R[-8]C[0] * (860/(860+50+100)) * R[-13]C[6]/conv!R[-22]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":6.318019801980197}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">6.32</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Soybean meal"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Soybean meal</td><td data-sheets-formula="=R[-9]C[0] * (50/(860+50+100)) * R[-14]C[6]/conv!R[-23]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.3673267326732674}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.37</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Soybeans"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Soybeans</td><td data-sheets-formula="=R[-10]C[0] * (100/(860+50+100)) * R[-15]C[6]/conv!R[-24]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.7346534653465348}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.73</td></tr>
</tbody></table>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI: -7%</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"High-forage diet for gestating sows"</span><br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: none; font-family: arial, sans, sans-serif; table-layout: fixed; width: 0px;" xmlns="http://www.w3.org/1999/xhtml"><colgroup><col width="144"></col><col width="86"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Ingredient"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Ingredient</td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Mass, lb"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Mass, lb</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Corn"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Corn</td><td data-sheets-formula="=R[-8]C[0] * (599/(599+80+1250)) * R[-13]C[6]/conv!R[-22]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":2.3040850181441153}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">2.30</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Soybean meal"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Soybean meal</td><td data-sheets-formula="=R[-9]C[0] * (80/(599+80+1250)) * R[-14]C[6]/conv!R[-23]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.3077242094349404}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.31</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Alfalfa hay"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Alfalfa hay</td><td data-sheets-formula="=R[-10]C[0] * (1250/(599+80+1250)) * R[-15]C[6]/conv!R[-24]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":4.808190772420942}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">4.81</td></tr>
</tbody></table>
</div>
<div style="text-align: left;">
</div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI: 130%</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This is the only diet found to have a positive RUEI, owing to it being based on forages. Feed varies significantly between farms, and it's unclear how common this type of feed is, but it does suggest an interesting gray area that will be discussed further.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Chickens</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Like cows, chickens breeds are specialized for either egg or meat production, with the latter termed "broilers". A laying chicken typically lives to be 18 months old and produces around 170 eggs, being slaughtered at a weight of around 2.2 kg, with a dressing percentage of around 70%. Broilers live to be about 1.5 months old, and are slaughtered at around 2.0 kg, though some broilers can reach as much as twice this weight. Both types of birds eat about 5% of their weight daily in the form of corn and soybeans. Chickens are not significant consumers of agricultural waste products.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>Laying chickens</u></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Corn-soy-based diet (CS)"</span><br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: none; font-family: arial, sans, sans-serif; table-layout: fixed; width: 0px;" xmlns="http://www.w3.org/1999/xhtml"><colgroup><col width="144"></col><col width="86"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Ingredient"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Ingredient</td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Mass, lb"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Mass, lb</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Corn"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Corn</td><td data-sheets-formula="=R[-8]C[0] * 0.5361 * R[-13]C[6]/conv!R[-22]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.134025}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.13</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Soybean meal"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Soybean meal</td><td data-sheets-formula="=R[-9]C[0] * 0.363 * R[-14]C[6]/conv!R[-23]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.09075}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.09</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Soybean oil"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Soybean oil</td><td data-sheets-formula="=R[-10]C[0] * 0.0509 * R[-15]C[6]/conv!R[-24]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.012725000000000002}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.01</td></tr>
</tbody></table>
</div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">source: <a href="https://academic.oup.com/ps/article/95/8/1881/2563661">Poultry Science: "Energy and nutrient utilization of broiler chickens..."</a></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A chicken's egg production constitutes the majority of its food output, about 73%.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI: -87%</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"Corn-based diet (CN)"</span><br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: none; font-family: arial, sans, sans-serif; table-layout: fixed; width: 0px;" xmlns="http://www.w3.org/1999/xhtml"><colgroup><col width="144"></col><col width="86"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Ingredient"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Ingredient</td><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Mass, lb"}" style="overflow: hidden; padding: 2px 3px; text-align: center; vertical-align: top;">Mass, lb</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Corn"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Corn</td><td data-sheets-formula="=R[-8]C[0] * 0.7217 * R[-13]C[6]/conv!R[-22]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.18042499999999997}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.18</td></tr>
<tr style="height: 21px;"><td data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":2,"2":"Soybean meal"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Soybean meal</td><td data-sheets-formula="=R[-9]C[0] * 0.2178 * R[-14]C[6]/conv!R[-23]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.05445}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.05</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Soybean oil"}" style="overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Soybean oil</td><td data-sheets-formula="=R[-10]C[0] * 0.0305 * R[-15]C[6]/conv!R[-24]C[3]" data-sheets-numberformat="[null,2,"#,##0.00",1]" data-sheets-value="{"1":3,"3":0.007625}" style="overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">0.01</td></tr>
</tbody></table>
</div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI: -83%</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>Broiler chickens</u></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i><br /></i></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Applying the same diet proportions to broilers, noting that their daily food intake is slightly higher:<br /><br />RUEI: -32% to -13%</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Results</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgze8Pjd7cQOOQJS0PZgTLIml5SHAgdLNHXpC3zfL_P3X7gIzRrlXxiiC9RQhmHWSMg2Op4pbxdSJKt6mGISAp0wH5m6k_HyL91QGDBVkcY2wE6zdglvkUECiCb3cV3FTWAe-uIO2HwIPMJ/s1600/food_outputs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="535" data-original-width="547" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgze8Pjd7cQOOQJS0PZgTLIml5SHAgdLNHXpC3zfL_P3X7gIzRrlXxiiC9RQhmHWSMg2Op4pbxdSJKt6mGISAp0wH5m6k_HyL91QGDBVkcY2wE6zdglvkUECiCb3cV3FTWAe-uIO2HwIPMJ/s1600/food_outputs.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This figure shows the food outputs of the livestock analyzed, broken down by the output type in terms of days of food, assuming a typical 2,000 calorie/day diet. Incredibly, a single dairy cow produces enough milk in its brief life for about a decade's worth of human caloric intake.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNuRgdkT1HtfbHX9jP1sbjUMmSe3ppW-1zkUDx6odyx7tfg1f5jasyIKr7X2piLGQAaHeSsm9DWmjvaqwWCckgQec8zSXiceMBmrJ9Lt7L9WqV3APrJIOSPk8bqInPLEdiNH0bdmZ1Esen/s1600/feed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="524" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNuRgdkT1HtfbHX9jP1sbjUMmSe3ppW-1zkUDx6odyx7tfg1f5jasyIKr7X2piLGQAaHeSsm9DWmjvaqwWCckgQec8zSXiceMBmrJ9Lt7L9WqV3APrJIOSPk8bqInPLEdiNH0bdmZ1Esen/s1600/feed.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Feed varies significantly by livestock, farm size, and geographic region, and is also usually proprietary, so these figures cannot be precise. Nevertheless, they capture some important trends about the extent to which livestock are recyclers or consumers of food products. All of these livestock originally existed near 100% on this chart, consuming mostly scraps and forages, but modern farming techniques have dramatically pushed the numbers lower by replacing large portions of feed with grains and legumes.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9eLsRJ-TodpehhxRdrnDotvdad5H-4-5mxciFGWTYn2DJ_0toA62x2LA6S0g8W20onLJRvY48YT2JffNVpMurxUhvRQk72y_koQW5H25mjhB_C2MpqRuUFl6nwltT1eQu2_GT8x_JvNmO/s1600/RUEI.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="401" data-original-width="531" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9eLsRJ-TodpehhxRdrnDotvdad5H-4-5mxciFGWTYn2DJ_0toA62x2LA6S0g8W20onLJRvY48YT2JffNVpMurxUhvRQk72y_koQW5H25mjhB_C2MpqRuUFl6nwltT1eQu2_GT8x_JvNmO/s1600/RUEI.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">RUEI was negative for all livestock analyzed except forage-fed pigs, which consume mostly alfalfa hay or corn stovers. The other livestock shown could also be raised in a positive-RUEI manner, but this is at odds with current factory farming and consumption habits.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Conclusions</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="background-color: #ffe599;">The data supports the view that factory farming, with its livestock feed characterized by low forage and high human-edible feed, is environmentally unsustainable, or at minimum, energetically wasteful.</span> Mainstream methods for cultivation of cows, pigs, and chickens in America cause a net useful energy loss, even when considering the fact that some animals consume agricultural waste that is human-inedible.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">However, an interesting gray area is found in the case of high-forage diets characteristic of free-range agriculture. Further, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">within this framework, livestock that consume human-inedible/waste products exclusively would have an infinitely high RUEI. Interestingly, this aligns with the pre-industrial model of farming, before factory farming, when crop cultivation was the primary focus and livestock existed in a secondary capacity, grazing freely, consuming occasional food waste, and in some cases serving as labor. In these times, meat was rare and weighty, a far cry from its commodity status in modern America.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">We are unlikely to ever return to this idyllic past, but we would be well-served to learn from its wisdom. Those who are not prepared to give up meat should at least better understand its environmental impact and reduce consumption, while opting for local, free-range, forage-fed options whenever possible. Veganism is too extreme for most people, but that's okay. <span style="background-color: #ffe599;">In practice, i</span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="background-color: #ffe599;">t's far more beneficial, and socially conscientious, to reduce livestock consumption </span><span style="background-color: #ffe599;">and/or improve cultivation standards than trying to convert non-vegans, which is usually a losing battle and risks stigmatizing the movement.</span><span style="background-color: white;"> </span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For example, reducing the meat consumption of 10 people by 10% is far better and easier than reducing the meat consumption of 1 person by 100%, since the ask is more reasonable while the impact is equal yet more socially broad. Purism should not stand in the way of pragmatism.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Sources</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Those interested in the data, calculations, and sources may view <a href="https://docs.google.com/spreadsheets/d/1cC7o4d3Zkg9BBXO5yINNLef3W1qH3QODMUqhMifGbCM/edit?usp=sharing">my full spreadsheet</a>, the basis of this post. I welcome any corrections and criticisms.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Books that shaped my general thinking on this topic are "Who Will Feed China?" by Lester R. Brown and "America's Food" by Harvey Blatt.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Update 2018-10-24</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The Economist ran an article last week called <a href="https://www.economist.com/briefing/2018/10/13/why-people-in-rich-countries-are-eating-more-vegan-food">"Why people in rich countries are eating more vegan food"</a>, which includes a nice graph showing "feed to food loss" for various livestock. They use protein as their intermediate quantity to compare between crops and livestock instead of energy as I've done here, but the concept and conclusions are similar.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioIinLvTR5ZoMea6oFaur9nNsIs0BztuQmxe4i5uf_onFbb-7AKhIYDkRWuwWzdOjq-EAsXLFUiBSrJSpx34tLUrncthLZJIWIF_UlHnhj-Ztb31kWVMIHVBQiVy75aXI8cIWiMBCS4aol/s1600/economist_protein_comparison.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="568" data-original-width="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioIinLvTR5ZoMea6oFaur9nNsIs0BztuQmxe4i5uf_onFbb-7AKhIYDkRWuwWzdOjq-EAsXLFUiBSrJSpx34tLUrncthLZJIWIF_UlHnhj-Ztb31kWVMIHVBQiVy75aXI8cIWiMBCS4aol/s1600/economist_protein_comparison.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Graph from The Economist comparing protein gains and losses for crops vs. livestock</span></div>
</div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-9825856705336656032018-10-02T07:51:00.000-07:002018-10-03T12:48:00.977-07:00MLB Postseason Predictions<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Following up on my post "<a href="http://www.kindofdoon.com/2018/08/predicting-baseballs-postseason.html">Predicting Baseball's Postseason</a>", here is my prediction for the outcome of the 2018 MLB Postseason. I originally planned to develop two brackets, one optimized for percentage and the other for points (where the point value per correct prediction doubles with each successive round), but surprisingly the two systems produced the same result, and so I have only this one unified bracket to venture:</span><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Ict1Felfz05f3he7qX9dmPzZGvlJs2POI8Q7UVbKxxJCFjfN8jSWRecYBx8b8DkM34b679b-xSouiWoUumj6a7isWjJJXunQtRbRQgty9jbDf56Pj_diL9qEgqLPb2C1VGmwndBpfd5B/s1600/2018_predictions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="419" data-original-width="655" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh3Ict1Felfz05f3he7qX9dmPzZGvlJs2POI8Q7UVbKxxJCFjfN8jSWRecYBx8b8DkM34b679b-xSouiWoUumj6a7isWjJJXunQtRbRQgty9jbDf56Pj_diL9qEgqLPb2C1VGmwndBpfd5B/s1600/2018_predictions.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In the last month leading up to the playoffs, the clear outlier is the Brewers, who became very hot, culminating in a very strong finish, winning 11 of their last 12 games. Another surprising result comes from the Red Sox; they had the best regular-season record but finished relatively cold, losing 5 of their last 10, which quickly relegated them to the peloton of average teams.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDPKl9y6vgq99ACHqiI0nX5U5no_U1XBDJ433qhpiUdh2oXMAOyePbjlyyIVSfxjEHIEBFb6NEgPyuX4-BRYqe7DK5O0Axvh_8vjjak12oVKmgWtyoyaFhVRBoLNvlcb6-AuU9XNzYaR7I/s1600/2018_postseason_graph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="498" data-original-width="769" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDPKl9y6vgq99ACHqiI0nX5U5no_U1XBDJ433qhpiUdh2oXMAOyePbjlyyIVSfxjEHIEBFb6NEgPyuX4-BRYqe7DK5O0Axvh_8vjjak12oVKmgWtyoyaFhVRBoLNvlcb6-AuU9XNzYaR7I/s1600/2018_postseason_graph.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7K1Yx3z4VtS_uI6bMvDSReQL6JuMUUb2-E7B4Q9GLq4CA7g8obDWTtMf4_WK7zjXhpaHCQS08e2StKmIfMgLfr6jdIBOBg-Zv8EmxFxLXej2EA74mqrEk07xZT_NqV0QBqoP0QRLULhz0/s1600/2018_postseason.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="733" data-original-width="652" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7K1Yx3z4VtS_uI6bMvDSReQL6JuMUUb2-E7B4Q9GLq4CA7g8obDWTtMf4_WK7zjXhpaHCQS08e2StKmIfMgLfr6jdIBOBg-Zv8EmxFxLXej2EA74mqrEk07xZT_NqV0QBqoP0QRLULhz0/s1600/2018_postseason.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Can the Brewers win their first-ever World Series? The odds look good for them this year. I ran Monte Carlo simulations with both "dynamic" and "static" Elo ratings, aka "hot" and "cold", and although they produced different rankings, the bracket outcomes were identical.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">=====================================</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">Elo_K = 0.08;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Elo_k = 11;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">h_f_a = 0.03;</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">Probability of winning World Series:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Elo_state: dynamic</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Runtime: 10 sec</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Simulations: 119140</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">1: Milwaukee Brewers, 42.66%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">2: Colorado Rockies, 11.36%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">3: Houston Astros, 8.53%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">4: Chicago Cubs, 8.07%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">5: Cleveland Indians, 7.57%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">6: New York Yankees, 7.19%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">7: Los Angeles Dodgers, 6.2%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">8: Oakland Athletics, 4.5%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">9: Boston Red Sox, 3.27%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">10: Atlanta Braves, 0.65%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "courier new" , "courier" , monospace;">=====================================</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">Probability of winning World Series:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Elo_state: static</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Runtime: 10 sec</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Simulations: 121221</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">1: Milwaukee Brewers, 54.19%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">2: Houston Astros, 8.6%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">3: Los Angeles Dodgers, 8.09%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">4: Cleveland Indians, 7.77%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">5: Colorado Rockies, 7.04%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">6: New York Yankees, 4.6%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">7: Chicago Cubs, 4.3%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">8: Boston Red Sox, 3%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">9: Oakland Athletics, 2.02%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">10: Atlanta Braves, 0.39%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Note: the predictions in this post were published at 2018-10-02 7:35 pm EST.</span>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-5254060800934241502018-09-23T14:52:00.002-07:002018-09-24T17:47:45.521-07:00Softball Optimization Revisited<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">About a year ago, I wrote about <a href="http://www.kindofdoon.com/2017/08/optimizing-softball-fielding-positions.html">using a computer program to optimize softball lineups</a> by putting players in their preferred fielding positions, to the greatest extent possible. In this post I'll discuss how my philosophy as team captain has evolved since then, and how I've matured my optimization program to match.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMuTaUqIFNJyt5rmHFhImduaQMk8jmT3k-Sw_ScNMYZqicaquaybSTdfjh4WDDqjrFkelwWYaNKHL54tCcFq4KfDyY0SUw178UvD168ybdbpzbOWRQbba0wRNunXIHYQzq-g4ehmg1XYV2/s1600/37841870_2066016963409931_1351369897287876608_o.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="682" data-original-width="1024" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiMuTaUqIFNJyt5rmHFhImduaQMk8jmT3k-Sw_ScNMYZqicaquaybSTdfjh4WDDqjrFkelwWYaNKHL54tCcFq4KfDyY0SUw178UvD168ybdbpzbOWRQbba0wRNunXIHYQzq-g4ehmg1XYV2/s640/37841870_2066016963409931_1351369897287876608_o.jpg" width="640" /></a></div>
<br />
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">the team after the spring 2018 championship, a narrow loss</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">back row, left to right: Shayna, Evan, Dan</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">iel, Paul, Mike, Brett, Peter, Josh</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">front row, le</span>ft to right: Buddy, Hannah, Emily, Kayla</span><br />
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>My Philosophy on Ideal Lineups</b></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">What is the ideal strategy when making lineups? T</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">wo approaches I've tried are to maximize team strength, and to maximize player satisfaction. I've found that both approaches have issues if taken to the extreme: maximizing team strength marginalizes weaker players, and maximizing player satisfaction decreases overall team strength, e.g. if certain players are allowed to monopolize their few preferred positions.</span></span></div>
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Rather than optimizing solely for team strength or player satisfaction, I now believe the ideal strategy is to maximize <i>team morale</i> by simultaneously optimizing and balancing:</span><br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>satisfaction</i>:<i> </i>players' satisfaction with their assignments</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><i>strength</i>: the team's probability of winning games</span></li>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Why do I think morale is the right unifying value to be maximized? In short, because I think that's what people seek in sports teams, especially at the rec level. I also believe that explicitly trying to win at all costs often has the opposite effect, by burning players out, creating rifts, and generally causing disengagement. I think the best way to maximize team strength is to <i>arrive at it</i> by creating the right atmosphere, and that ultimately comes from morale. This sort of environment also fosters camaraderie and keeps people happy, a obviously desirable outcome that also further improves team performance.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">So ideally, every player is assigned to a position they like, they perform well, and the team wins. This leads to individual and team satisfaction, and ultimately to positive morale. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">But how to optimize for this?</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Quantifying Team Strength</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Quantifying team strength requires additional information beyond where people like to play. It requires a more fundamental breakdown of which skills underpin the various positions, how the positions compare at skill requirements, and how individual players compare at these skills. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">It also requires knowledge of the strategic importance of the various positions, which are significantly uneven.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In our league, with the fast pace of the game and relatively low level of seriousness, it's far too cumbersome to maintain player stats, so I had to rule out an absolute assessment of skill such as fielding percentage of batting average. Instead, I settled on relative assessments. I may not know Player A's top throw speed, but I can venture with some confidence if it's higher or lower than Player B's. Similarly, I may not know how much throw strength is required to play shortstop, but I know it's higher than second base.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Bringing this together, I brainstormed seven fairly independent skills that I think underpin the various positions, in varying amounts. I then ranked every player by their aptitude for these skills, and every position by its requirements for these skills.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwzeybB88fd7KgaMW-ZjL5EMVuR1FVsae5JcyD-sP9mXfAEgxPhznl8vA7RFf9VoK42xtUHCUU2qeNNETAVIFeWPqI89LqplqfMi7Al9kpssjquNs26W-kIMnSJpEcw0jWymRCExzlbEWP/s1600/rankings_pseudonyms.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="526" data-original-width="908" height="370" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwzeybB88fd7KgaMW-ZjL5EMVuR1FVsae5JcyD-sP9mXfAEgxPhznl8vA7RFf9VoK42xtUHCUU2qeNNETAVIFeWPqI89LqplqfMi7Al9kpssjquNs26W-kIMnSJpEcw0jWymRCExzlbEWP/s640/rankings_pseudonyms.png" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">player and position rankings; pseudonyms used for anonymity</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">There's a good deal of subjectivity here, as the rankings rely on my informal and unscientific judgement, and it's also significantly subject to confirmation bias. On the other hand, this approach is simple, lightweight, and easy to maintain - in my opinion, the right fit for a rec league. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">But what about the strategic importance of each position? For example, it's clearly more valuable to have a strong pitcher than a strong catcher, since the pitcher has a much greater effect on the game outcome.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Weighting for Strategic Importance</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For this, I use defensive outs generated by each position as a metric for strategic importance. I estimated that 2/3rds of our outs are unassisted, e.g. fly outs or line outs, and 1/3rd of our outs involved two positions, e.g. groundouts. Then, I estimated how many outs each position generates in a typical game, noting that the result should sum to ((2/3)*1 + (1/3)*2 players per out)*(3 outs per inning)*(6 innings per game) = 24 player-outs per game. I estimated these weights based on my league experience:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFolwzZt18mc0gUNlDoUrgfvy1snHU4o2Jt_8-VgEx16gVIWuVL1yRSCFg29IcAEFMU-5pvLCHLDxnEpote-NBpEyLaaeIAvCmpN5COurUhD5TIyyrHu2PWyEK5qcipnPNNtVxUti1q2zK/s1600/outs_by_position_per_game.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="422" data-original-width="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFolwzZt18mc0gUNlDoUrgfvy1snHU4o2Jt_8-VgEx16gVIWuVL1yRSCFg29IcAEFMU-5pvLCHLDxnEpote-NBpEyLaaeIAvCmpN5COurUhD5TIyyrHu2PWyEK5qcipnPNNtVxUti1q2zK/s1600/outs_by_position_per_game.png" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">outs by position per game, estimated</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Scoring a Lineup For Strength</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">My lineup generator reads the rankings shown above, and converts them to a matrix, where the strongest player for each skill is given a 1.0, and the weakest a 0.0, and so on with the positions. Linear interpolation is used for the players and positions between the extremes. Then, evaluating the strength of a lineup is fairly straightforward:</span></div>
<div>
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Initialize team strength = 0</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Pick the first player on the field</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Take the dot product of the player's skill with the requirements for this position</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Multiply by the weight for this position</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Add this number to the team strength</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Repeat Steps 3-5 for all remaining players</span></li>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Down-Selecting to a Single Lineup</b></span></div>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">From my prior work, I have a method of quantifying player satisfaction with assignments, based on survey results asking players to classify each position as "like", "neutral", or "dislike". From this, I generate a "satisfaction" score, 0-100%. For example, 93% might represent nine players liking their assignments, and one player disliking their assignment.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I believe that in the regular season, ideally, all players should sit the bench an equal amount. To this end, I have also incorporated manual constraints that allow me to constrain players to arbitrary positions and optimize the remaining positions.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">What is the upper bound on team strength? The numbers used are dimensionless, so to approximate an upper bound, I temporarily discard all positional constraints and survey data, and seek only to optimize the strength score. I then take the best result as the upper bound, and use it to normalize subsequent lineup strength scores, also 0-100%.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Incorporating player preferences reduces team strength slightly by reducing the solution space, so there's a trade-off to be made. I think the sweet spot is enforcing a minimum satisfaction of around 90-95%, and then optimizing strength given this lower bound. Typically the survey has a fairly minor penalty on team strength of around 5-10%. This is due to players generally liking positions where they are strong, and disliking positions where they are weak. Constraints can have a more significant impact on strength, particularly when the benched player is relatively strong, by as much as 10-20%.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Generating a Sample Lineup</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">As an example, I'll show the process of generating a lineup using the sample rankings shown above. Suppose that Oscar and Alan have not sat the bench yet, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Earl has asked to play second base due to a mild injury, and </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Marvin will be absent.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">...</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Constraints = {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> 'Oscar','Benched'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> 'Earl', 'Benched'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> 'Alan', 'Second base'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> };</span></div>
</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">players_absent = {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> 'Marvin'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> };</span></div>
</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">...</span></div>
<div>
<br /></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Suppose I also set:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">satisfaction_minimum = 0.90; % 0-1</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">After evaluating about 1,500 random lineups per second for a few seconds, the optimized result is returned:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Satisfaction: 93%</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Strength: 95%</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Pitcher: Andrew</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Catcher: Ryan</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">First base: Samuel</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Second base: Earl</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Shortstop: Igor</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Third base: Isaac</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Left field: Aaron</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Left-center field: Vlad</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Right-center field: Eddie</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Right field: Ulrich</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Benched:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Oscar</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Alan</span></div>
</div>
<div style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">
<br /></div>
<div style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">
Note that the constraints were enforced on Oscar, Earl, and Alan, and that Marvin was dropped from the roster due to being absent. Due to the astronomically large solution space, it's dubious to extract high-level meaning from this lineup other than "it achieves the highest strength score for the specified minimum satisfaction". Still, by brute force, the program generates a lineup that seems to have some real thought behind it:<br />
<br /></div>
<div style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">
<ul>
<li>Andrew was assigned to pitcher due to his strong throw accuracy, preference for the position, and the added fact that it was otherwise unpopular in the survey</li>
<li>Igor was assigned to shortstop due to being the all-around strongest player, suitably assigned to the most important defensive position, which he fittingly prefers</li>
<li>Isaac, who has the strongest glove, was assigned to the "hot corner" of third base, a low-weighted position, but one he enjoys despite his weak throw accuracy</li>
<li>Stronger runners were assigned to the left-hand side of the outfield, which sees more line drives that the right side</li>
<li>Weaker runners were assigned to the right-hand side of the outfield, which sees more pop and fly balls than the left side</li>
</ul>
</div>
</div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-65911606792825484152018-08-25T09:47:00.002-07:002018-09-23T18:38:23.104-07:00Predicting Baseball's Postseason<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Having rece</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">ntly </span><a href="http://www.kindofdoon.com/2018/03/predicting-march-madness-with-elo.html">tried my hand</a> at numerically predicting the notoriously unpredictable March Madness basketball tournament<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">, with moderate success, i</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">t was only natural that I would next attempt to predict the outcome of the MLB postseason, with baseball being dearer to my heart and its historical data being so plentiful. In this post I'll describe the groundwork I've done toward this goal so that I'll be ready to generate an optimized bracket when the postseason rolls around. Specifically I'll be focusing on <a href="https://en.wikipedia.org/wiki/Elo_rating_system">Elo ratings</a> and how I've tailored them on a team-by-team basis from first principles </span></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">specifically for predicting MLB postseasons.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Identifying free parameters in Elo</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Typically, implementations of the Elo rating system tune the K-factor only, which controls the speed at which ratings respond to performance. This is well-documented and values have been published for numerous competitive sports. However, focusing only the K-factor only ignores a few important considerations that improve predictive performance:</span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The relationship between rating difference and prediction certainty</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The effect of home field advantage</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">More sophisticated models also take into account weather conditions, individual players (particularly pitchers), and other progressively finer factors. However, for the sake of keeping scope manageable, I'll be looking only at game logs showing the teams, home field, and game score. Everything will be inferred from this basic data.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Relationship between rating differences and prediction certainty</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">At the heart of the Elo system is the </span><a href="https://en.wikipedia.org/wiki/Logistic_function" style="font-family: "helvetica neue", arial, helvetica, sans-serif;">logistic function</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> or "S-curve"</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">:</span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY5vj2IXSXEH7fWu8EYvneNXGxIACVnrkal2AesTxmB_QdNE351YWom_Sp5PckRUXOwv_mTUWkZ3Zzb7QiQI1rXdaEUxBo6JXfYf9wi9qh4eGcXHFnW2YGfm9d5Vx1BTGWZbLwvy2-AJ-6/s1600/logistic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="67" data-original-width="203" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY5vj2IXSXEH7fWu8EYvneNXGxIACVnrkal2AesTxmB_QdNE351YWom_Sp5PckRUXOwv_mTUWkZ3Zzb7QiQI1rXdaEUxBo6JXfYf9wi9qh4eGcXHFnW2YGfm9d5Vx1BTGWZbLwvy2-AJ-6/s1600/logistic.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi46iIY1HdVl-NM3Ye0efA6ihgx-R21DaFd2XSixHXjW1rGRhR2XgWL02wDKQ9FjI96JpIdMyLZd8nTonCSQH0KmSJWo-uHnniMgM9PBSajlh7JL62nIk_ozok4zINqDG1mlPd7Vod1vOZ3/s1600/600px-Logistic-curve.svg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="400" data-original-width="600" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi46iIY1HdVl-NM3Ye0efA6ihgx-R21DaFd2XSixHXjW1rGRhR2XgWL02wDKQ9FjI96JpIdMyLZd8nTonCSQH0KmSJWo-uHnniMgM9PBSajlh7JL62nIk_ozok4zINqDG1mlPd7Vod1vOZ3/s320/600px-Logistic-curve.svg.png" width="320" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Logistic function; L = 1, k = 1, x_o = 0; source: <a href="https://en.wikipedia.org/wiki/Logistic_function">Wikipedia</a></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Equally-rated teams should have equal win probabilities, so x_o must be set to 0. Similarly, a team's probability cannot exceed 100%, so L must be set to 1. This leaves only a single free parameter, k, which controls the slope of the curve. Essentially it represents the slope of the S-curve, or the rate at which prediction confidence changes as the rating gap between the two teams widens.</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>The effect of home field advantage</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Historically, teams win about 54.1% of their home games, and 45.9% of their away games. In other words, for evenly-matched teams, being home confers about a 4.1% win probability advantage, and the same amount as a disadvantage to the away team when compared to a theoretical neutral field.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjchyphenhyphen7x80KKoOO8zsuxlTDiSQRv6_YudpCMUBBC73KL-c8Osq-0jnbLTIAxksoWIGzqSkydQiy7JcamN6M1Lr5evPThiC0f_wa-5KyvwrMbffcXJOiFFJr4_mzM33TD4paZp8O0Bno8ur2d/s1600/hfa_all.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="414" data-original-width="704" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjchyphenhyphen7x80KKoOO8zsuxlTDiSQRv6_YudpCMUBBC73KL-c8Osq-0jnbLTIAxksoWIGzqSkydQiy7JcamN6M1Lr5evPThiC0f_wa-5KyvwrMbffcXJOiFFJr4_mzM33TD4paZp8O0Bno8ur2d/s1600/hfa_all.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Despite seasonal noise, this value has been remarkably consistent over the live-ball era. The modern game, which I'm arbitrarily defining as the last 10 years, falls neatly in line with this apparent historical constant:</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvjoLfCRQUwvnWej_ULMherUYnLq9enT5Uswt15YcZTpO_ccWBObnsBnw6yoK05emtVK-YmyGVGvSQUzSws7upW7ZIJLOQrqsDnHEFlpSAgfSfdPlzcc4T2S4bojXuirGaSujbzcbiQ9b9/s1600/hfa_last_10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="414" data-original-width="704" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvjoLfCRQUwvnWej_ULMherUYnLq9enT5Uswt15YcZTpO_ccWBObnsBnw6yoK05emtVK-YmyGVGvSQUzSws7upW7ZIJLOQrqsDnHEFlpSAgfSfdPlzcc4T2S4bojXuirGaSujbzcbiQ9b9/s1600/hfa_last_10.png" /></a></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Supposing home field advantage was set at 4.1%, when calculating Elo, I subtract this from the away team's probability of winning, and add it to the home team's win probability. This has the intuitive effect of making away wins slightly more consequential than home wins, and so on with losses.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Optimizing Elo for predictive accuracy</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With all this in mind, I define an "Elo configuration" as a set of three values:</span><br />
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K: controls the speed at which ratings adjust to performance</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">k: controls the relationship between prediction confidence and rating difference</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">h_f_a: controls how significant the home field advantage is</span></li>
</ol>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">To optimize these parameters for predictive accuracy, my approach is:</span></div>
<ol>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Pick a set of parameters that define an Elo configuration</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With this configuration, calculate day-by-day Elo ratings for all teams from the start of the live-ball era, 1920, to present</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For each year requested, extract the final game of each postseason series, representing a team being eliminated</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For each of these games, look up the regular-season-end Elo ratings for both teams, and predict the winner to be the one with the higher Elo rating</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Compare the prediction to the actual result</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Loop back to step 1 and repeat with another Elo configuration</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">...</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">After running a sufficiently large number of Elo configurations, select the one that maximizes prediction accuracy over the requested time domain</span></li>
</ol>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A few other notes on my Elo calculation:</span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Elo mean is arbitrarily set at 1,000</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ratings are initialized in 1920, the start of the live-ball era</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Ratings are carried over directly between seasons, without regressions or resets</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Postseason games count toward Elo ratings, but only in subsequent seasons, i.e. the predictor uses a snapshot of Elo right before the requested postseason to generate predictions, and does not "peek ahead"</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Each Elo configuration takes about 1 second to evaluate on my Dell Precision 5520, which is fairly time-expensive. I approached the optimization by first sweeping the three parameters over logarithmically-spaced ranges to get in the right ballpark (pun intended), then sweeping them over linearly-spaced ranges around the best configuration found in the prior step.</span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With this approach, a time domain window is necessary to optimize the Elo parameters. I consider two cases, and show the results below:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
</div>
<div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>"Live-ball" era: 1920-present</u></span><br />
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K = 0.075</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">k = 11.0714</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">h_f_a = 0.017857</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This configuration has an overall prediction accuracy of 70%. The breakdown by decade is:</span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1920s: 100%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1930s: 80%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1940s: 80%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1950s: 70%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1960s: 67%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1970s: 83%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1980s: 68%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">1990s: 64%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2000s: 69%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2010s: 65%</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">An interesting trend here is that baseball seems to be becoming progressively less predictable, especially starting in the 1980s. Causes for this would be an interesting topic for research in and of itself.</span></div>
</div>
</div>
</div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>"Modern" era: 2008-2017</u></span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K = 0.08</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">k = 11</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">h_f_a = 0.03</span></li>
</ul>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This configuration has an overall prediction accuracy of 68%. The breakdown by year is:</span></div>
<div>
<ul>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2008: 86%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2009: 71%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2010: 57%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2011: 71%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2012: 66%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2013: 44%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2014: 67%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2015: 78%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2016: 56%</span></li>
<li><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">2017: 89%</span></li>
</ul>
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">It's worth noting that using the "live ball" configuration in the prior section is very nearly as accurate, and the configuration values are very close. The "modern" configuration correctly predicts 56 of 82 matches, compared to 55 of 82 for the "live ball" configuration. So they're nearly interchangeable.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Snapshot of today's teams</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">What do these Elo configurations say about predicting the postseason? To get some intuition, let's look at how today's teams have fared in the last month:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDh6675iuSRH31EOdmlp4YP41mKF60uezoeDSsYeY2qK_9LLQ_3q9JbVci7NXbASpDr9WwPVSoMGCx9i68qMW8t3tm_GQ63AVnvRwlCJbsLcv3dB_q14MMZWngVbrzHauBvrY5lCVnYOk/s1600/elo_last_month.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="505" data-original-width="713" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDh6675iuSRH31EOdmlp4YP41mKF60uezoeDSsYeY2qK_9LLQ_3q9JbVci7NXbASpDr9WwPVSoMGCx9i68qMW8t3tm_GQ63AVnvRwlCJbsLcv3dB_q14MMZWngVbrzHauBvrY5lCVnYOk/s1600/elo_last_month.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The ratings here can be thought of as a metric for how well the teams would fare in the postseason if it were to start immediately, i.e. their postseason strength. What's interesting to note is how quickly teams can rise above the pack with a strong win streak or regress to mediocrity with a slump. For example, look at the Pirates, who went from 2nd best to 2nd worst in the last month due to a slump. My takeaway here is that postseason strength is highly dependent on "hotness" - that is, how well a team has been performing <i>recently</i>, as opposed to how well they've done all season. Here's the full breakdown:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg__7j6muY5Bl9tgplLiaIlOJw09-4aHEvn3lL8FugQZe3n31FSYtc8UDp52ZSvnPLvSlSa_a7BF9ydGsR_FrRae_Oj6xZJ7CrcZd8S_SmmMBmsvjVZQ6KsJoT7A2sH4Mz4kolRQuTJmpqX/s1600/elo_2018-08-25.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="733" data-original-width="659" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg__7j6muY5Bl9tgplLiaIlOJw09-4aHEvn3lL8FugQZe3n31FSYtc8UDp52ZSvnPLvSlSa_a7BF9ydGsR_FrRae_Oj6xZJ7CrcZd8S_SmmMBmsvjVZQ6KsJoT7A2sH4Mz4kolRQuTJmpqX/s1600/elo_2018-08-25.png" /></a></div>
<br /></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Some historical perspectives</b></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqoOuJl80pDSbTGkFIILG-rx74x81T9yYBac3CSqxW5Clv6kxBHf5FILtTqqkiFoCfhqKEd5Y2AE0PHp2jp90vWRtImUenHOuLbeHJ68_aSajFSc0SY__P71EHmCGjWQtcPd7m7M9fYFN9/s1600/elo_2017_postseason.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="505" data-original-width="725" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhqoOuJl80pDSbTGkFIILG-rx74x81T9yYBac3CSqxW5Clv6kxBHf5FILtTqqkiFoCfhqKEd5Y2AE0PHp2jp90vWRtImUenHOuLbeHJ68_aSajFSc0SY__P71EHmCGjWQtcPd7m7M9fYFN9/s1600/elo_2017_postseason.png" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The 2017 postseason was an especially predictable one, in the sense that the teams that finished the regular season on top also generally finished the postseason on top, i.e. there were few upsets.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">By comparison, look at 2013's postseason:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMHxL-kjOajk2su8fh23f1Kp_SS9oWXUPlOm72PxrJBAYxngkzD_LszHE3J7OXjeifmSTqW0nBNOrueHdnlwt9LYyhTAjiOtoIr5V9Run9Fh7U4bdpI42sVBON-BnZFSicmDhivhmX94rD/s1600/elo_2013_postseason.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="505" data-original-width="725" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMHxL-kjOajk2su8fh23f1Kp_SS9oWXUPlOm72PxrJBAYxngkzD_LszHE3J7OXjeifmSTqW0nBNOrueHdnlwt9LYyhTAjiOtoIr5V9Run9Fh7U4bdpI42sVBON-BnZFSicmDhivhmX94rD/s1600/elo_2013_postseason.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The Red Sox finished the regular season with mediocre strength, but caught fire and upset several teams on their way to win the World Series.</span><br />
<br /></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Plans</b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Once the 2018 postseason bracket is finalized (including the Wild Card games), I'll generate two bracket predictions: one optimized for points (where the value per correct prediction doubles with each successive round), and another optimized for percentage. For the point-optimized bracket, I'll use Monte Carlo simulations in conjunction with the Elo method developed here to </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">account for the probabilistic difficulty of each team's path to the World Series.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Source code</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Available on <a href="https://github.com/kindofdoon/predicting_baseball_postseason">my GitHub</a>, minus the scraper. </span></div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-85149714050849747012018-07-23T23:22:00.001-07:002018-09-24T17:48:06.151-07:00Criticism of Impossible Burger<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I recently had an Impossible Burger, and the experience left me feeling very odd. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Impossible is a California-based food company chartered to "make the global food system more sustainable". Their first product is the "Impossible Burger", a plant-derived burger patty that aims to be indistinguishable from a traditional beef patty. Their profile has been rising steadily since 2016.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuvqdsXzuvofrBSprDqai96AgMNUweP1qgcmJwL-lMeGhUlRYqipPerP4XUTS8z5rqTedTttELpT5sb_o6kzrALnuAwSDZdd1e-LnPhzSfCpR1vZdj-y2urhM2j0wNfRX12KAjBdrPBsTY/s1600/burgers.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="413" data-original-width="511" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuvqdsXzuvofrBSprDqai96AgMNUweP1qgcmJwL-lMeGhUlRYqipPerP4XUTS8z5rqTedTttELpT5sb_o6kzrALnuAwSDZdd1e-LnPhzSfCpR1vZdj-y2urhM2j0wNfRX12KAjBdrPBsTY/s1600/burgers.PNG" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Impossible Burgers; <a href="https://impossiblefoods.com/food/">source</a></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4jvxzBnFW1vhbXZnD_xqXAvw5iQtFJZIy6lUNV8ao3YYliJMhf_qtv46xZEsbcBq-2buQPKCiDGNELOmjZ_4YWmT93ziT5Gcs1-1sW1d8_t4nSd2cbpyDUyZrAJd_kTrXS-RL6SychXm0/s1600/interest.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="229" data-original-width="717" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4jvxzBnFW1vhbXZnD_xqXAvw5iQtFJZIy6lUNV8ao3YYliJMhf_qtv46xZEsbcBq-2buQPKCiDGNELOmjZ_4YWmT93ziT5Gcs1-1sW1d8_t4nSd2cbpyDUyZrAJd_kTrXS-RL6SychXm0/s1600/interest.PNG" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span><br />
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Search interest for "Impossible Burger" since 2016; <a href="https://trends.google.com/trends/explore?date=2016-01-01%202018-07-24&geo=US&q=impossible%20burger">source</a></span></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">
</span><b style="font-family: "helvetica neue", arial, helvetica, sans-serif;"><br /></b>
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Who Is This For?</b><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">On its surface, a plant-based burger patty would seem to be aimed at plant-based eaters. However, Impossible's marketing suggests that they have set their sights much higher at the general population. I think this is the right approach, since vegetarians/vegans are relatively small in number, and Impossible envisions a global impact. <span style="background-color: #fff2cc;">It's also implausible to me that plant-based eaters would be significantly interested in a product that aims to be gastronomically indistinguishable from something they believe to be immoral/unethical.</span></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">So, will the omnivorous general population go for Impossible? From their perspective, </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">the Impossible Burger is a more-expensive, oddly-textured version of a standard burger. The only advantage that Impossible can claim over beef is its reduced environmental impact. But how important is this consideration to omnivores? <span style="background-color: #fff2cc;">A person is an omnivore because they <i>do not</i> find the environmental aspects of plant-based diet to be sufficiently compelling.</span> So why would they switch, given the inferior quality and higher price? Novelty may account for some interest, as it did with my omnivore friend who joined me in trying the strange creation. But the novelty will fade, and I'm quite sure that my friend will go back to a standard beef burger next time around.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Assessment</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="background-color: #fff2cc;">Impossible's product is very ambitious, well-marketed, and clearly well-researched, but they've positioned themselves in a gastronomic no-man's land between veganism and omnivorism.</span> For this reason, I do not foresee a clear market or their product having the large-scale global impact that they envision once the novelty wanes, much as I am onboard with their ultimate goal of improving the sustainability of the global food supply chain.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Outlook</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"Just be yourself" is a good an</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">d common bit of advice for all sorts of social situations. I also think it is very apt for food. An inscrutable mixture legumes, grains, nuts, and vegetables trying to be beef is trying to <i>not </i>be itself. This undertone permeates <a href="https://impossiblefoods.app.box.com/s/edwcfyvojzsvzn5d633dxt4c4ehyzqq3">Impossible's promotional material</a>, which dubiously refers to its product simply as "meat", e.g.:</span><br />
<blockquote class="tr_bq">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">"The burger is just our first product— proof that delicious meats do not have to come from animals."</span></blockquote>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I think this inherently puts the product on weak, unsustainable footing. <span style="background-color: #fff2cc;">In my view, a better approach to achieving Impossible's long-term goals is improving public awareness of the feasibility of plant-based eating and of historically stable cuisines from around the world that rely less heavily on animal products, such as those from India and the Mediterranean.</span><span style="background-color: white;"> </span>For this reason, I strongly support the work that local food chain <a href="https://www.cloverfoodlab.com/">Clover</a> and grocer supplier <a href="http://www.macrovegetarian.com/">Macro Vegetarian</a> are doing in promoting healthy, casual food that isn't "good for being plant-based", but simply good in its own right (though Clover has recently started selling Impossible products). Similarly, the transition to renewable energy will not happen because people suddenly becoming willing to pay more in the face of environmental realities; it will happen when renewables become the cheapest and best option. </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">In my view, this is the real way to have the sort of impact that Impossible envisions.</span>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-1484778887675333262018-07-07T09:09:00.001-07:002018-07-07T09:09:07.582-07:00Sketch: Yellowstone River bridge<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3aKTPrm2CNgVnBvQzze_e8WygWy_-Osbf7-xKXFf2VDX4bie04AAFmcktN6S7Fvq_4XjufkGDp9ua4nsWK55zHjMm_qYr5lbkwxEv9lLae7DAkxufWn5D2dQPnz88hJxhNxhDPl0HSNXm/s1600/yellowstone_bridge_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><img border="0" data-original-height="1098" data-original-width="1600" height="438" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3aKTPrm2CNgVnBvQzze_e8WygWy_-Osbf7-xKXFf2VDX4bie04AAFmcktN6S7Fvq_4XjufkGDp9ua4nsWK55zHjMm_qYr5lbkwxEv9lLae7DAkxufWn5D2dQPnz88hJxhNxhDPl0HSNXm/s640/yellowstone_bridge_2.png" width="640" /></span></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">A sketch I made during a recent trip to Yellowstone National Park in about 1.5 hours, near </span><span style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">near </span><a href="https://www.google.com/maps/place/44%C2%B055'12.4%22N+110%C2%B024'22.0%22W/@44.9201903,-110.4064701,270m/data=!3m1!1e3!4m5!3m4!1s0x0:0x0!8m2!3d44.920112!4d-110.406099" style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">44.920112, -110.406099</a><span style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">. The air was thin and the sun was hot. At the time, I was recovering from tendinitis incurred at the Bozeman Triathlon a few days prior and was using a walking stick to cope. I stuck close to the road and kept an eye out for bears and buffalo. </span><span style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">As far as I know, this bridge is unnamed but spans the Yellowstone River.</span>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-59784664004183774182018-06-10T22:33:00.001-07:002018-06-10T22:50:09.798-07:00Grayscale Image Encryption<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Background</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A few months ago, I listened to <a href="https://www.youtube.com/watch?v=jlPF9_1VIso">a discussion</a> between philosopher Sam Harris and technologist Tristan Harris that I found extremely interesting and persuasive. Tristan Harris has emerged as an outspoken critic of the "attention economy" that underpins many digital services which are offered for free with ad support, most notably Facebook. In essence, he argues that the relationship between human attention and profit that underpins free digital services creates a unhealthy incentive structure that rewards high-impact, shocking, emotional content and attenuates slow-burning, moderate, thoughtful content. My own sense of this disturbing trend led me to leave Facebook shortly after the 2016 presidential election, during which I became frustrated by the prevalence of low-quality, sensationalist content. Tristan Harris is also critical of how modern apps, in an effort to command and maintain attention, use bright, high-contrast, saturated colors that draw upon biases in human perception to "hijack" our attention. One counter-measure he proposes is <a href="http://humanetech.com/take-control/">setting one's phone to grayscale</a>.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">I've had my phone in grayscale for a few months now and strongly support the idea. It has helped me spend less time on my phone, and more time on hobbies I find more valuable. The grayscale makes my phone less visually interesting, and it also reminds me subconsciously that if I'm looking at my phone out of boredom, there are better things I can be doing with my time.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Idea</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">On a particularly unpleasant bus ride recently, I was thinking about digital grayscale image conversion. Any given grayscale value, 0-255, maps to a large number of colors. For example, it's possible to find a particular shade of red, green, blue, yellow, orange, etc. that maps to the same shade of gray in a grayscale conversion process.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><span style="background-color: #ffe599;">This got me thinking - what would a color image look like if it was constrained such that after grayscale conversion, it flattened to a single shade of gray?</span> In other words, suppose you wanted to "encrypt" an image in color such that an agent viewing the image in grayscale would see no image at all, but rather a single shade of gray?</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Grayscale Conversion</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">There is no single way of performing digital grayscale conversion, but rather a variety of techniques. If each pixel's color is represented as a 1-by-3 array, with the elements corresponding to its red, green, and blue components (R, G, B), then a <a href="https://www.johndcook.com/blog/2009/08/24/algorithms-convert-color-grayscale/">few common grayscale conversion methods</a> are:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> • <u>Lightness</u>: average the most and least prominent colors</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> ◦ value = (max(R,G,B) + min(R,G,B)) / 2</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> • <u>Average</u>: average the colors</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> ◦ value = sum(R,G,B) / 3, or equivalently...</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> ◦ value = 0.33*R + 0.33*G + 0.33*B</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> • <u>Luminosity</u>: weighted average of the colors</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> ◦ value = 0.21*R + 0.72*G + 0.07*B</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The <i>average</i> and <i>luminosity</i> methods are essentially identical, with the only difference being the weights given to the color channels. I decided to focus on these two methods for being better-suited for the optimization approach discussed below.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Geometric Approach</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">For an image to satisfy my encryption criteria and flatten to a single color in grayscale, each pixel in the image must satisfy the constraint equation:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">K = 0.21*R + 0.72*G + 0.07*B</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">where K, somewhat arbitrarily, is the average value of all color channels, and [0.21 0.72 0.07] represents the weightings for each color channel. After some thought, I realized that this problem could be approached geometrically by considering the color channel variables R, G, B as displacements in 3D space, i.e. x, y, z. Viewed in this way, the constraint equation actually describes a tilted plane in 3D space. The plane's specifications depend on the K-value from the input image and the weights from the grayscale conversion method. Here are some representative visualizations:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">With the color channels equally weighted:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6viAM7mvXrFdc-CZRT9qZgiibwUn_Nhx8yDxpLcbllfChGaEM8g3ZQd6BwTpmqdTnZXrK3ADe2C0qE-cBGpOHD3-zQbx_ohzVGudtUtf7nkgd4qH6oiWsKbs98LDA3Rji6kHsSeMedzc_/s1600/average.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="645" data-original-width="577" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6viAM7mvXrFdc-CZRT9qZgiibwUn_Nhx8yDxpLcbllfChGaEM8g3ZQd6BwTpmqdTnZXrK3ADe2C0qE-cBGpOHD3-zQbx_ohzVGudtUtf7nkgd4qH6oiWsKbs98LDA3Rji6kHsSeMedzc_/s1600/average.png" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Favoring the red color channel:</span><br />
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCuMptCxjuvhrjNRrvtkCYcw44RMWV00rwXMjCpbixS03cfvS-FgXA-5qgdTjHqDFXCxSfQyC3ElI0vEJ7nlLAAx_akF9ahsXz_kmy8cTrwp8yauPo4Mh17LmSk-olzPgBmSPTF2LX7aDr/s1600/50_42_08.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="645" data-original-width="577" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgCuMptCxjuvhrjNRrvtkCYcw44RMWV00rwXMjCpbixS03cfvS-FgXA-5qgdTjHqDFXCxSfQyC3ElI0vEJ7nlLAAx_akF9ahsXz_kmy8cTrwp8yauPo4Mh17LmSk-olzPgBmSPTF2LX7aDr/s1600/50_42_08.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Favoring the green color channel:</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8nAiqaGmQ_MrcvSAnZFwx72lv6sjkD4KPPmu0oTxUZ-ae63n2FYgbCxx82P8qWEkidNM3JgiiC1CSVDdzyGAMiRav12VwkznI_b73i8wi9TGr1HZTqzE2ITuCGtxpl08Y7TUN2G2Qbr55/s1600/21_72_07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="645" data-original-width="577" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8nAiqaGmQ_MrcvSAnZFwx72lv6sjkD4KPPmu0oTxUZ-ae63n2FYgbCxx82P8qWEkidNM3JgiiC1CSVDdzyGAMiRav12VwkznI_b73i8wi9TGr1HZTqzE2ITuCGtxpl08Y7TUN2G2Qbr55/s1600/21_72_07.png" /></a></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Transforming a pixel can be thought of as projecting it onto the constraint plane. This is equivalent to picking the closest point on the constraint plane, but much faster. The projection is </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">done by calculating the input pixel's distance to the constraint plane, then subtracting this distance along the constraint plane's unit normal vector. It's worth noting that after projection, some pixels may lie outside the bounding box of [0 1] in x, y, z. I haven't thought of a good way of efficiently snapping these points to their best location on the constraint plane. However, for most ordinary photographic images I've analyzed, the K-value is around 0.5 and all pixels can be projected without error.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Results</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Shown below are some results with varying color channel weights. I tested several standard weightings and some non-standard weightings as well. None of these weightings exactly flattened the images in grayscale on my Android phone, but some came pretty close - [0.21 0.72 0.07] seemed to provide the best result.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>Standard weightings:</u></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg79hb6cvGALyQnSudrL_Kge8sT7V8elP0RC9EntBZNXM24w4R4oUBo9QnInS-La4Vq2XOxy0fwiS9Z6tIRfF2UVC8P4L55IH-pTkDgI5Z0elk0w65vfPPUPfYI6XUIl569wNKSLqCW7F5h/s1600/mosque_medium_comparison_0-212_0-701_0-087.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="542" data-original-width="965" height="359" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg79hb6cvGALyQnSudrL_Kge8sT7V8elP0RC9EntBZNXM24w4R4oUBo9QnInS-La4Vq2XOxy0fwiS9Z6tIRfF2UVC8P4L55IH-pTkDgI5Z0elk0w65vfPPUPfYI6XUIl569wNKSLqCW7F5h/s640/mosque_medium_comparison_0-212_0-701_0-087.png" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFVIbAWbmbCIUxgydVuuQMkehk4BYgwsJRLOua1_gpKBF1BbTWFT6zjB7rTFCxvWj9AlNEvxC-eSHrMe2PhoFH0k0Uu43SFs9utNyw6mhYfYfUtHeqOzAdEsI_VQ3_nHyJAmEwExK7HnGE/s1600/flag_medium_comparison_0-33333_0-33333_0-33333.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="619" data-original-width="807" height="490" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFVIbAWbmbCIUxgydVuuQMkehk4BYgwsJRLOua1_gpKBF1BbTWFT6zjB7rTFCxvWj9AlNEvxC-eSHrMe2PhoFH0k0Uu43SFs9utNyw6mhYfYfUtHeqOzAdEsI_VQ3_nHyJAmEwExK7HnGE/s640/flag_medium_comparison_0-33333_0-33333_0-33333.jpg" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJUmCebPms_q_hrd29cyOBH8nZdwrdUjWzZ95jYradco44jeB5t4gHxgK9YNUw2iUhngg_Ss60vHkE8QjwH7OgDDGEZKyVOAQ7nzYJ65vJydsXuEWWbJCh2eS9CFnNbOx5HUg8-RKF9oA9/s1600/charles_medium_comparison_0-299_0-587_0-114.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="512" data-original-width="768" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJUmCebPms_q_hrd29cyOBH8nZdwrdUjWzZ95jYradco44jeB5t4gHxgK9YNUw2iUhngg_Ss60vHkE8QjwH7OgDDGEZKyVOAQ7nzYJ65vJydsXuEWWbJCh2eS9CFnNbOx5HUg8-RKF9oA9/s640/charles_medium_comparison_0-299_0-587_0-114.jpg" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtLFXdAuVOe8R-9qiLpH-Le4qZ_ULUysf6L33JWlrLhC7P7AWH5z4enGtSWbhreLTzqGswVB3PIMNfBkAK4LcAwN8gniCWdb4huUqSQb5qExJUC1C-1EcjOsKLZEZV_EgKvWqJzoA8RJlT/s1600/tile_medium_comparison_0-5_0-419_0-081.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="468" data-original-width="832" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtLFXdAuVOe8R-9qiLpH-Le4qZ_ULUysf6L33JWlrLhC7P7AWH5z4enGtSWbhreLTzqGswVB3PIMNfBkAK4LcAwN8gniCWdb4huUqSQb5qExJUC1C-1EcjOsKLZEZV_EgKvWqJzoA8RJlT/s640/tile_medium_comparison_0-5_0-419_0-081.jpg" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj79lLIFs9gvPCOPr9Qykgu0Bl9P1WIoZN6TSf120uY3dY8UkbQ1d5b7yaycscmpBmaWsBvyl_LqsRE2ZtyQVD_Tm4nHZpGRhvD3FKCtN6rreD9Rz8ZLQwe_jR9SE6YxHCJBSAkVsNT2d9b/s1600/mosque2_medium_comparison_0-5_0-419_0-081.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="468" data-original-width="832" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj79lLIFs9gvPCOPr9Qykgu0Bl9P1WIoZN6TSf120uY3dY8UkbQ1d5b7yaycscmpBmaWsBvyl_LqsRE2ZtyQVD_Tm4nHZpGRhvD3FKCtN6rreD9Rz8ZLQwe_jR9SE6YxHCJBSAkVsNT2d9b/s640/mosque2_medium_comparison_0-5_0-419_0-081.jpg" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2NWbVkcT78oHtoKXQH8tv_NHBNJ9nZwPm9775M7jNa96b9rOEAXAlwFzLe70u1_84-M0eMpPweYcZPc51Kh0yfzEkmVIem-s6ddk-2NML3rekxLUV1U5LLc_fHulBalfFe3LMWvcrl89t/s1600/books_medium_comparison_0-33333_0-33333_0-33333.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="468" data-original-width="832" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2NWbVkcT78oHtoKXQH8tv_NHBNJ9nZwPm9775M7jNa96b9rOEAXAlwFzLe70u1_84-M0eMpPweYcZPc51Kh0yfzEkmVIem-s6ddk-2NML3rekxLUV1U5LLc_fHulBalfFe3LMWvcrl89t/s640/books_medium_comparison_0-33333_0-33333_0-33333.jpg" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBk1D8zqONMxpmfLqcqim0hlMI8Jjww75jIVESPvUZade9N-DrbpQlYJoUuzTQV8p8_dCyTfS4ci3AcqpuB-lbZ3ByNv2T9mtDArBSy8gEZktzBPI944QyGPoY9boQ1GCJyy2ycuNSjzTp/s1600/desert_medium_comparison_0-33333_0-33333_0-33333.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="615" data-original-width="922" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBk1D8zqONMxpmfLqcqim0hlMI8Jjww75jIVESPvUZade9N-DrbpQlYJoUuzTQV8p8_dCyTfS4ci3AcqpuB-lbZ3ByNv2T9mtDArBSy8gEZktzBPI944QyGPoY9boQ1GCJyy2ycuNSjzTp/s640/desert_medium_comparison_0-33333_0-33333_0-33333.jpg" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><u>Non-standard weightings:</u></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHlKKenDqmu_IVnGuydJgtit7gV7OcnlaNPCnkvDaq-u_fnpyVokJunQRWL0zdZvSATDz6ZFMzXiegsEy2N0SrmJLqDfX-DAruZ1CvU4BIBD0G6yIGdyEfSm_TSO_fuVJRguE3dJO-XMcp/s1600/georges_medium_comparison_0-21_0-72_0-07.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="612" data-original-width="816" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHlKKenDqmu_IVnGuydJgtit7gV7OcnlaNPCnkvDaq-u_fnpyVokJunQRWL0zdZvSATDz6ZFMzXiegsEy2N0SrmJLqDfX-DAruZ1CvU4BIBD0G6yIGdyEfSm_TSO_fuVJRguE3dJO-XMcp/s640/georges_medium_comparison_0-21_0-72_0-07.jpg" width="640" /></a></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5I_Juzn7avLxGdQQyOMo-w6zm-vqKvelkXMBfaep1oZNq4up-EYA230sdYG9Zgfnw8NMlQ_6OIgdt3GOAs8mYwIKV4AfiJ-yNhccxKURNaIIzEynNannBdBa91P8jStRmUNAiSm6afeaD/s1600/swan_medium_comparison_0-21_0-07_0-72.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="768" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5I_Juzn7avLxGdQQyOMo-w6zm-vqKvelkXMBfaep1oZNq4up-EYA230sdYG9Zgfnw8NMlQ_6OIgdt3GOAs8mYwIKV4AfiJ-yNhccxKURNaIIzEynNannBdBa91P8jStRmUNAiSm6afeaD/s640/swan_medium_comparison_0-21_0-07_0-72.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAAsuNz38GhtvzwA-JGA06RwoyBkztC29LovjSB8bryH3nTiXxnqgPNUI8HrNwZEyUOKVwnokXNsuSPENFCMOxFklQvYwya-GMTdtZ11Hry57CpVNGjZIR52VlPso3dgS9gK9IKrfunY9m/s1600/mystic2_medium_comparison_0-72_0-21_0-07.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="512" data-original-width="768" height="426" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAAsuNz38GhtvzwA-JGA06RwoyBkztC29LovjSB8bryH3nTiXxnqgPNUI8HrNwZEyUOKVwnokXNsuSPENFCMOxFklQvYwya-GMTdtZ11Hry57CpVNGjZIR52VlPso3dgS9gK9IKrfunY9m/s640/mystic2_medium_comparison_0-72_0-21_0-07.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Takeaways</b></span><br />
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This project yielded some useful knowledge, primarily that </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">visualizing color intensity as displacement in 3D space provides geometric intuition and optimization improvements. However, the idea doesn't have any apparent uses other than as an interesting toy problem for image processing, nor does it seems feasible since "encrypting" the image would require prior knowledge of the grayscale conversion algorithm being used, of which there are many.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Source Code</b></span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b><br /></b></span>
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Available on <a href="https://github.com/kindofdoon/grayscale_image_encryption">my GitHub</a>.</span></div>
</div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com2tag:blogger.com,1999:blog-3278537004721616095.post-22612758579850908502018-06-03T07:38:00.000-07:002018-06-03T08:36:03.110-07:00Swim the Charles!<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Yesterday I raced in the <a href="http://www.charlesriverswimmingclub.org/wp/">Charles River One-Mile Swim</a>, setting a new personal record with a time of 29:48. The water was 68-69 °F, just right for my 2-5 mm wetsuit. The water was surprisingly opaque - looking down in the water, I couldn't see my feet! Visually, it was like swimming in dark beer. In a way, it was pretty when the sun shined through splashed water, illuminating its deep golden-brown color. It's a bit like how urban haze can make sunsets more spectacular. The race organizers closely monitored water quality leading up to the event to ensure that levels of pollutants and bacteria were sufficiently low. The main issue is that rainfall causes runoff, temporarily degrading water quality. With no significant rain preceding the event, we were good to go.</span><br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPbZjJAYroXrj9WChyxv5a_UEYfmiWeF_nGGoOoVRPuTlq2a6KNJBbKk0eytGjaIUtDm0K3sPZJl-TGTSuEmlyQeNli38xngvNDiOHLTDFX3_dZWkS4yjMJ2vjFvuj2KzMnsMiBfpUFwou/s1600/20180602_065222_HDR.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPbZjJAYroXrj9WChyxv5a_UEYfmiWeF_nGGoOoVRPuTlq2a6KNJBbKk0eytGjaIUtDm0K3sPZJl-TGTSuEmlyQeNli38xngvNDiOHLTDFX3_dZWkS4yjMJ2vjFvuj2KzMnsMiBfpUFwou/s640/20180602_065222_HDR.jpg" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">crowd starting to trickle in</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXzNadIee356yMVEP2dQS2nJQVxeX_ZG67HrdTHER7-PmDU4QaUXkD3HyX6LtasD52KyiQQe0Si3EkgZ8n8AIbqOiSIpXEJcxHBiSaWnKD6yd58F0fvX5NvI_m7J2QIKVGVHlc9l1xYOPL/s1600/20180602_091156_HDR.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1600" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiXzNadIee356yMVEP2dQS2nJQVxeX_ZG67HrdTHER7-PmDU4QaUXkD3HyX6LtasD52KyiQQe0Si3EkgZ8n8AIbqOiSIpXEJcxHBiSaWnKD6yd58F0fvX5NvI_m7J2QIKVGVHlc9l1xYOPL/s640/20180602_091156_HDR.jpg" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">post-race merriment</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZRoGf_lQBB46g3cAt9tIwnLzvBA-SeH248ymd9ikERY4ljtlE8REic-MJwKi9H9V0oToITqLQMg8WeFNAaBmc0_L0elbdjd3QniISqtFQa_X60kJr3CsJPyRlhl_B9hXSu43diedfmPoQ/s1600/course.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="493" data-original-width="1078" height="292" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZRoGf_lQBB46g3cAt9tIwnLzvBA-SeH248ymd9ikERY4ljtlE8REic-MJwKi9H9V0oToITqLQMg8WeFNAaBmc0_L0elbdjd3QniISqtFQa_X60kJr3CsJPyRlhl_B9hXSu43diedfmPoQ/s640/course.jpg" width="640" /></a></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">coat hanger-like course shape</span></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Here's how the results stacked up:</span></div>
<div style="text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX-zVtb1jBoqNwTDZ-mqf8u6HxvRt_sCYyj8-ExsikkVVkmQZMIgMTEeV9V71B1fBNXilQzrBoF3EsqvJm8nUXWX3uZpsOch99Jz0v7MO3mRIgpVTOFIKI6vnPO9cDTn0iOzf1WCmglaEA/s1600/age.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="531" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX-zVtb1jBoqNwTDZ-mqf8u6HxvRt_sCYyj8-ExsikkVVkmQZMIgMTEeV9V71B1fBNXilQzrBoF3EsqvJm8nUXWX3uZpsOch99Jz0v7MO3mRIgpVTOFIKI6vnPO9cDTn0iOzf1WCmglaEA/s1600/age.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_caCxhh0RZ7yFC3f0dHLbOdXNe_l8XvqYo1_Rdh_2ouYF43SAbpcyaNS7HbtHidMySDKMf_QjAEF_vNeYlhsjL401FMozw7E45k8zJW0Rz5ujEod62JLQVw5TYU_Rb2yD5UZUKr42yU9t/s1600/time.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="531" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_caCxhh0RZ7yFC3f0dHLbOdXNe_l8XvqYo1_Rdh_2ouYF43SAbpcyaNS7HbtHidMySDKMf_QjAEF_vNeYlhsjL401FMozw7E45k8zJW0Rz5ujEod62JLQVw5TYU_Rb2yD5UZUKr42yU9t/s1600/time.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The race was staggered into two waves based on estimated finish time. I was placed into the first wave. Finishing with a very average time, I was slower than most in the first wave and faster than most in the second wave.</span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgKWWbPRiQKL-p0eb_rq1GoLnwlkyxzdTQZ23ZQk63tebAGKunse7nzR2ZyFzEjIsaujLUVUIrVSN5QyQYohtrghHqdxNhdbGboR1MLKviIQoqOnylfhUC5h21VPNUtYFYD4g_Fjfic5aj/s1600/travel.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="525" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgKWWbPRiQKL-p0eb_rq1GoLnwlkyxzdTQZ23ZQk63tebAGKunse7nzR2ZyFzEjIsaujLUVUIrVSN5QyQYohtrghHqdxNhdbGboR1MLKviIQoqOnylfhUC5h21VPNUtYFYD4g_Fjfic5aj/s1600/travel.png" /></a></div>
<br />
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Where did people come from? Primarily Cambridge, Boston, Somerville, Brookline, and Belmont, in that order.</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9G03Kz9XuEBqWidVlUCa-2evMiS4xDh0Vas_erEZ-tm5LccGiXSIzs2uvhLBAoH8jt7AZXvJ-lFCvpGD2yojc-HJ8FJKaYeq4mHpX64gO_LRyBEvvKXJAAf5MV78iJPhfrQYYeGSRF7Jn/s1600/heatmap.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="525" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9G03Kz9XuEBqWidVlUCa-2evMiS4xDh0Vas_erEZ-tm5LccGiXSIzs2uvhLBAoH8jt7AZXvJ-lFCvpGD2yojc-HJ8FJKaYeq4mHpX64gO_LRyBEvvKXJAAf5MV78iJPhfrQYYeGSRF7Jn/s1600/heatmap.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLvE6zQxPPouvpymFXXvw8cnzGo4Buw3oO4Twq50_TaybPDEVp1xVJbItf1HvCJMZAQcNJjI-WT_8edA3mLUlT5dheS6riathgkXBDHAG60Gkmy19A3pfqGI3feCUCbWt6Be2nwHKi8u_i/s1600/bib.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="525" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLvE6zQxPPouvpymFXXvw8cnzGo4Buw3oO4Twq50_TaybPDEVp1xVJbItf1HvCJMZAQcNJjI-WT_8edA3mLUlT5dheS6riathgkXBDHAG60Gkmy19A3pfqGI3feCUCbWt6Be2nwHKi8u_i/s1600/bib.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">The biggest surprise I found in the data was how closely a person's bib number correlated to their race time. The trend is very clear in the plot above. In fact, the data indicates that a person's bib number is a significantly better predictor of their performance than any other factor, including their age and how far they traveled to the race. How interesting!</span></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">Looking to dig deeper, I performed a sexually bi-modal multi-linear regression for finish time based on age, bib number, and distance traveled to the race from each athlete's hometown using Google's Geocoding API. The error between predicted and actual times had a mean of about 0 minutes and standard deviation of about 3.9 minutes, which is not bad considering the sparseness of the data. I then ranked the results by "surprising-ness", taking the normalized regression error as a metric for how surprising a performance was:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both;">
<b style="font-family: "helvetica neue", arial, helvetica, sans-serif;">Top 10 Surprising Performances</b></div>
<div class="separator" style="clear: both;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"></span></div>
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: none; font-family: arial, sans, sans-serif; font-size: 10pt; table-layout: fixed; width: 0px;" xmlns="http://www.w3.org/1999/xhtml"><colgroup><col width="45"></col><col width="132"></col><col width="86"></col><col width="45"></col><col width="62"></col><col width="84"></col><col width="155"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Rank"}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Rank</td><td data-sheets-value="{"1":2,"2":"Name","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Name</td><td data-sheets-value="{"1":2,"2":"Age, years","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Age, years</td><td data-sheets-value="{"1":2,"2":"State","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">State</td><td data-sheets-value="{"1":2,"2":"Gender","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Gender</td><td data-sheets-value="{"1":2,"2":"Time, min.","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Time, min.</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":2,"2":"Reg. error, norm., %","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Reg. error, norm., %</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">1</td><td data-sheets-value="{"1":2,"2":"Kirkham Wood","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Kirkham Wood</td><td data-sheets-value="{"1":3,"3":63}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">63</td><td data-sheets-value="{"1":2,"2":"CA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">CA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":24.71}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">24.71</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":26.3838703782719}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">26.4</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":2}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">2</td><td data-sheets-value="{"1":2,"2":"Rafael Irizarry","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Rafael Irizarry</td><td data-sheets-value="{"1":3,"3":46}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">46</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":26.3833333333333}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">26.38</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":21.8370281817589}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">21.8</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":3}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">3</td><td data-sheets-value="{"1":2,"2":"Don Haut","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Don Haut</td><td data-sheets-value="{"1":3,"3":52}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">52</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":23.62}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">23.62</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":20.058089644327502}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">20.1</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":4}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">4</td><td data-sheets-value="{"1":2,"2":"Donald Kaiser","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Donald Kaiser</td><td data-sheets-value="{"1":3,"3":67}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">67</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":27.6416666666667}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">27.64</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":19.9791803895711}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">20.0</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":5}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">5</td><td data-sheets-value="{"1":2,"2":"Darryl Starr","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Darryl Starr</td><td data-sheets-value="{"1":3,"3":49}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">49</td><td data-sheets-value="{"1":2,"2":"RI","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">RI</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":24.0216666666667}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">24.02</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":19.0631045234223}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">19.1</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":6}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">6</td><td data-sheets-value="{"1":2,"2":"Ursula Hester","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Ursula Hester</td><td data-sheets-value="{"1":3,"3":47}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">47</td><td data-sheets-value="{"1":2,"2":"CO","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">CO</td><td data-sheets-value="{"1":2,"2":"F","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">F</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":29.77}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">29.77</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":18.4010578313633}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">18.4</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":7}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">7</td><td data-sheets-value="{"1":2,"2":"Len Van Greuning","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Len Van Greuning</td><td data-sheets-value="{"1":3,"3":50}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">50</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":22.175}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">22.18</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":18.1291518205153}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">18.1</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":8}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">8</td><td data-sheets-value="{"1":2,"2":"Alex Meyer","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Alex Meyer</td><td data-sheets-value="{"1":3,"3":29}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">29</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":18.8083333333333}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">18.81</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":17.8796153184693}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">17.9</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":9}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">9</td><td data-sheets-value="{"1":2,"2":"Louis Harwood","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Louis Harwood</td><td data-sheets-value="{"1":3,"3":28}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">28</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":29.9866666666667}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">29.99</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":16.8637105560088}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">16.9</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":10}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">10</td><td data-sheets-value="{"1":2,"2":"Haruka Uchida","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">Haruka Uchida</td><td data-sheets-value="{"1":3,"3":22}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">22</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"F","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; vertical-align: bottom;">F</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":23.7366666666667}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">23.74</td><td data-sheets-numberformat="[null,2,"#,##0.0"]" data-sheets-value="{"1":3,"3":16.2368821360036}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px; text-align: right; vertical-align: bottom;">16.2</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">This is neat, but it's easily gamed, as a person could increase their "surprising-ness" significantly by registering at the last minute, making them appear statistically as more of an underdog, for example. To this end, I also characterized pure athletic performance by </span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">excluding bib number and hometown data, looking only at gender and age, which increased the error standard deviation to 5.6 minutes. In effect, this is similar to awarding prizes by division, but in a continuous sense rather than a discrete one with arbitrarily-defined brackets such as "Men 30-39".</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><b>Top 10 Athletic Performances</b></span></div>
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: none; font-family: arial,sans,sans-serif; font-size: 10pt; table-layout: fixed; width: 0px;" xmlns="http://www.w3.org/1999/xhtml"><colgroup><col width="45"></col><col width="134"></col><col width="86"></col><col width="45"></col><col width="62"></col><col width="84"></col><col width="144"></col></colgroup><tbody>
<tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Rank"}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Rank</td><td data-sheets-value="{"1":2,"2":"Name","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Name</td><td data-sheets-value="{"1":2,"2":"Age, years","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Age, years</td><td data-sheets-value="{"1":2,"2":"State","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">State</td><td data-sheets-value="{"1":2,"2":"Gender","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Gender</td><td data-sheets-value="{"1":2,"2":"Time, min.","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Time, min.</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":2,"2":"Reg. err., norm., %","6":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Reg. err., norm., %</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":1}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">1</td><td data-sheets-value="{"1":2,"2":"Alex Meyer","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Alex Meyer</td><td data-sheets-value="{"1":3,"3":29}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">29</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":18.8083333333333}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">18.81</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":31.7032591950876}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">31.70</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":2}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">2</td><td data-sheets-value="{"1":2,"2":"Eric Nilsson","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Eric Nilsson</td><td data-sheets-value="{"1":3,"3":30}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">30</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":18.9316666666667}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">18.93</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":31.549284535202}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">31.55</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":3}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">3</td><td data-sheets-value="{"1":2,"2":"Anton McKee","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Anton McKee</td><td data-sheets-value="{"1":3,"3":24}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">24</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":19.7733333333333}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">19.77</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":26.6240663454286}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">26.62</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":4}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">4</td><td data-sheets-value="{"1":2,"2":"Jessica Stokes","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Jessica Stokes</td><td data-sheets-value="{"1":3,"3":41}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">41</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"F","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">F</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":22.1766666666667}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">22.18</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":26.6062451315023}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">26.61</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":5}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">5</td><td data-sheets-value="{"1":2,"2":"Jen Olsen","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Jen Olsen</td><td data-sheets-value="{"1":3,"3":47}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">47</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"F","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">F</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":22.6266666666667}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">22.63</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":26.392924676156397}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">26.39</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":6}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">6</td><td data-sheets-value="{"1":2,"2":"Len Van Greuning","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Len Van Greuning</td><td data-sheets-value="{"1":3,"3":50}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">50</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":22.175}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">22.18</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":26.137476421501997}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">26.14</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":7}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">7</td><td data-sheets-value="{"1":2,"2":"Kathleen Tetreault","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Kathleen Tetreault</td><td data-sheets-value="{"1":3,"3":56}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">56</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"F","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">F</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":23.5216666666667}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">23.52</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":25.388386631904602}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">25.39</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":8}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">8</td><td data-sheets-value="{"1":2,"2":"Gail Fricano","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Gail Fricano</td><td data-sheets-value="{"1":3,"3":44}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">44</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"F","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">F</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":22.765}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">22.77</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":25.306547986765697}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">25.31</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":9}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">9</td><td data-sheets-value="{"1":2,"2":"Christophe Graefe","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Christophe Graefe</td><td data-sheets-value="{"1":3,"3":44}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">44</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":22.0883333333333}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">22.09</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":24.6456123179053}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">24.65</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":3,"3":10}" style="font-size: 11pt; font-weight: bold; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">10</td><td data-sheets-value="{"1":2,"2":"Ed Baker","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">Ed Baker</td><td data-sheets-value="{"1":3,"3":39}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">39</td><td data-sheets-value="{"1":2,"2":"MA","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">MA</td><td data-sheets-value="{"1":2,"2":"M","6":1}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; vertical-align: bottom;">M</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":21.9133333333333}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">21.91</td><td data-sheets-numberformat="{"1":2,"2":"#,##0.00","3":1}" data-sheets-value="{"1":3,"3":23.7039410053034}" style="font-size: 11pt; overflow: hidden; padding: 2px 3px 2px 3px; text-align: right; vertical-align: bottom;">23.70</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<style type="text/css"><!--td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}--></style></div>
<div class="separator" style="clear: both;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">A major aspect of this swim is changing public opinion on the feasibility</span><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> of the Charles as a public recreation area for swimming. A great deal of work has been to study, improve, and monitor its water quality. A </span><a href="http://www.thecharles.org/media/uploads/2016/07/Swimmable-Charles-Study_reduced.compressed.pdf" style="font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;">2016 report</a><span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"> said that the prospect of a permanent swimming facility on the Charles "could potentially be feasible" and included this tantalizing photo below. It's a very intriguing possibility. Getting the river to a point where urban swimming is once again feasible would have significant benefits aside from enabling the creation of a forward-looking, yet retro swimming site.</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhShw-4QMDq1BT4NainAokQAjWbd_yPh8ZUgB9_bFXvVYBQzH9egQj7bapHPuPopd6m2NQsHC0A7_N_zWS981BcRS4CilCNbHn8qwua0oVx1d1ETasybtDpjrnVP2Ijf-__giLt_EgcDNNm/s1600/perspective_cover_FINAL-website.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="676" data-original-width="1350" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhShw-4QMDq1BT4NainAokQAjWbd_yPh8ZUgB9_bFXvVYBQzH9egQj7bapHPuPopd6m2NQsHC0A7_N_zWS981BcRS4CilCNbHn8qwua0oVx1d1ETasybtDpjrnVP2Ijf-__giLt_EgcDNNm/s640/perspective_cover_FINAL-website.jpg" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "helvetica neue" , "arial" , "helvetica" , sans-serif;">artist's rendering of an urban swimming site on the Charles</span></div>
<style type="text/css"><!--td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}--></style><style type="text/css"><!--td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}--></style><style type="text/css"><!--td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}--></style><br />
<style type="text/css"><!--td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}--></style><style type="text/css"><!--td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}--></style>Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-79236317894947724962018-03-15T09:21:00.000-07:002018-04-16T22:03:39.572-07:00Predicting March Madness with Elo ratings and Monte Carlo simulations<span style="font-family: "arial" , "helvetica" , sans-serif;">I was recently invited to join a March Madness bracket pool at my office. I quickly realized that this was a great opportunity to apply some of the concepts that I learned about in reading Kasparov's recent book <i>Deep Thinking</i>, discussed in my <a href="http://www.kindofdoon.com/2018/02/tic-tac-toe-and-musings-about.html">previous post</a>. My original idea was to apply Elo ratings, originally developed for chess, to inform my bracket. The scope of this effort quickly grew as I realized that I could wrap additional layers of abstraction around an Elo calculator, incorporating Monte Carlo simulations and sensitivity analysis, to make a fully-automated bracket generator. In this post, I'll discuss my approach, method, and results.<br /><br /><b> About Elo ratings</b><br /><br /> Elo ratings were originally created for the purpose of quantifying a player's skill level in chess over time relative to their peers. The Elo rating system has many nice properties, such as the ability to predict game outcomes based on prior skill levels, and its drop-in/drop-out asynchronous nature. For its simplicity and power, the rating scale has found use in many sports beyond chess. You can read about the math behind it <a href="https://en.wikipedia.org/wiki/Elo_rating_system">on Wikipedia</a>.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVKZXtusnMRqbMEA6HytUvxMNy6Jrd3mlQZKBCbllFwnKbhGDWjkLLgZ5LzgtmF45aVG8xBUGqvmuAWa0HQ2bR8vA8mD2QlYgzkR0RNMOS7Zei_LHNFJiyO_VvVhBeot0Mi-QQ5B42kK0t/s1600/elo_win_prob.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="353" data-original-width="468" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVKZXtusnMRqbMEA6HytUvxMNy6Jrd3mlQZKBCbllFwnKbhGDWjkLLgZ5LzgtmF45aVG8xBUGqvmuAWa0HQ2bR8vA8mD2QlYgzkR0RNMOS7Zei_LHNFJiyO_VvVhBeot0Mi-QQ5B42kK0t/s1600/elo_win_prob.png" /></a></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div style="text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">Graph showing relationship between Elo difference and win probability; </span><a href="https://metinmediamath.wordpress.com/2013/11/12/sports-elo-rating-and-win-probability-carlsen-vs-anand/" style="font-family: arial, helvetica, sans-serif;">source</a></div>
<div style="text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">
<b> Elo vs. NCAA RPI</b><br /><br /> In ranking its teams, the NCAA uses a ranking system called <a href="https://en.wikipedia.org/wiki/Rating_percentage_index">RPI</a>, or rating percentage index, which is an oddly arbitrary system. Historically, it seems to have good predictive power, but this may be somewhat deceiving. The act of receiving a high seed seems to be inherently advantageous regardless of team skill due to the bracket structure, </span><span style="font-family: "arial" , "helvetica" , sans-serif;">as </span><a href="https://www.youtube.com/watch?v=4a1TUszkMfI#t=1m42s" style="font-family: arial, helvetica, sans-serif;">Jon Bois humorously shows:</a><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir8MfPZuqkFU6T6tmhmc7NvdTj5LHza158sa6_hplH29c-y4EYq26VoKWj8XPbNyNanp2ZjoLMcwPa4ROWyFD0PJy6Jic-3w67nRsqSgXLJT0XP8PZr-Dwlmrdh0ZMl_Zx6LhOHGSrHEjJ/s1600/seed_effect.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="467" data-original-width="757" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir8MfPZuqkFU6T6tmhmc7NvdTj5LHza158sa6_hplH29c-y4EYq26VoKWj8XPbNyNanp2ZjoLMcwPa4ROWyFD0PJy6Jic-3w67nRsqSgXLJT0XP8PZr-Dwlmrdh0ZMl_Zx6LhOHGSrHEjJ/s1600/seed_effect.png" /></a></div>
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"> The primary free parameter in the Elo rating system is its so-called K factor, which controls the speed at which ratings respond to apparent increases in player skill. In comparison, the RPI system has three weighting parameters, which are more or less arbitrary, and whose meaning is less obvious in a higher-level sense. As Wikipedia puts it, RPI "lacks theoretical justification from a statistical standpoint" and the "heavy emphasis upon strength of schedule [may give] an unfair advantage to teams from major conferences". My analysis supports this criticism of the RPI system - more on this below. More critically for this effort, it also has limited predictive power, so in my model, I use Elo exclusively and neglect NCAA ranking except as it influences the initial bracket structure.<br /><br /><b> Generating Elo ratings</b><br /><br /> Elo ratings are generated by examining win/loss records. I decided to limit my scope to only the 2017-2018 season, neglecting any prior data, to maintain simplicity and avoid the additional modeling assumptions that would be required.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">I scra</span><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;">ped </span>a complete ga</span><span style="font-family: "arial" , "helvetica" , sans-serif;">me log for all of the active teams and parsed them to remove duplicates and non-D1 games</span><span style="font-family: "arial" , "helvetica" , sans-serif;">. In total, the scraper extracted 5,401 unique games between 351 D1 teams spanning 2017-11-10 to 2018-03-10. I also manually added the play-in "First Four" games, which are effectively regular-season games. For those interested, this dataset is available on <a href="https://github.com/kindofdoon/march_madness">my GitHub</a>.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /> With a log of all unique games, calculating Elo ratings is straightforward. Teams are initialized with an average score, and their score is adjusted as they win and lose games according to Elo's equations. In essence, the equations predict the probability of each team winning based on their rating difference, then compare the actual result to the prediction, then update the teams' ratings accordingly. Its simple and self-correcting nature reminds me of Bayes' Theorem, another useful statistical tool for making predictions based on observations.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtQFsUlbszBKtay5arhEPlo7jvQSXXssUKWpnEHjXT5TNzUq6L8rE7rrCgD2TZ6gwqmdXvEzh4BUP2AyOuQdL8tgifR09RpfL-gCpoe6jjyTWrd_sOj6ABJ1nRZgAxrZ5AwklUouVMtIzd/s1600/elo_all_teams_small.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="476" data-original-width="744" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtQFsUlbszBKtay5arhEPlo7jvQSXXssUKWpnEHjXT5TNzUq6L8rE7rrCgD2TZ6gwqmdXvEzh4BUP2AyOuQdL8tgifR09RpfL-gCpoe6jjyTWrd_sOj6ABJ1nRZgAxrZ5AwklUouVMtIzd/s1600/elo_all_teams_small.png" /></a></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div>
<div style="text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">Elo over 2017-2018 season plus First Four, selected teams highlighted</span></div>
<div style="text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><b>Comparing Elo and NCAA rankings</b></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Elo provides a check against the NCAA ranking system. Which teams are most overrated? Most underrated? Here is what the data says about the NCAA's top 25 teams:</span><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM6lo55gkcM8b3f_0lrvCtcWDHop3Vae9KrlUC9PcHCif828kvYeqoTdqxe9wwF_NqLEGJoD1YyIVTqoTS_fN8Lgn2c3AlSdOgSXLICD2b4N2pLHEWqjEdBhRCZ8p3KzWKA38f3aPdb2O-/s1600/rankings_comparison.png" style="font-family: arial, helvetica, sans-serif; margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM6lo55gkcM8b3f_0lrvCtcWDHop3Vae9KrlUC9PcHCif828kvYeqoTdqxe9wwF_NqLEGJoD1YyIVTqoTS_fN8Lgn2c3AlSdOgSXLICD2b4N2pLHEWqjEdBhRCZ8p3KzWKA38f3aPdb2O-/s1600/rankings_comparison.png" /></a></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div style="text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">Green: underrated; red: overrated, per Elo assessment</span></div>
<div style="text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">For Elo, K = 25 and mean = 1500; NCAA source: </span><a href="https://www.google.com/search?q=ncaa+basketball+rankings&oq=ncaa+ba&aqs=chrome.0.69i59j0l4j69i60.2831j0j7&sourceid=chrome&ie=UTF-8#sie=lg;/g/11c6w0gymx;3;/g/11ckvf54fz;rn;fp;1" style="font-family: arial, helvetica, sans-serif;">Google</a></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /><span style="font-family: "arial" , "helvetica" , sans-serif;">Interestingly, the comparison produces a jarring collection of strong agreements and strong disagreements. Most overrated is Florida, ranked at #23 with a 20-12 record. Most underrated are Houston and Saint Mary's (CA), ranked #21 and #25, with records of 26-7 and and 28-5, respectively. The systems agree that Virginia and Villanova are the strongest teams. Here are my top 25 teams sorted by regular-season Elo:</span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsYHfJM0kTGvkgQEKlYSLjehmzWCt8CchzqtF6TJzjCQJFyQmoZRbtfykGENz6a57mBRMcJAjQUGDIpvkmlaeYzN7r7fHTslU33Whby5nWAbx_M665ZrX-oz2_8wfs-xb4sCUSf1J30G7C/s1600/elo_top_teams.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="564" data-original-width="416" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsYHfJM0kTGvkgQEKlYSLjehmzWCt8CchzqtF6TJzjCQJFyQmoZRbtfykGENz6a57mBRMcJAjQUGDIpvkmlaeYzN7r7fHTslU33Whby5nWAbx_M665ZrX-oz2_8wfs-xb4sCUSf1J30G7C/s1600/elo_top_teams.png" /></a></div>
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Notably, Saint Mary's (CA), ranked #16 in Elo, did not qualify for the Round of 64 - a victim of the NCAA's archaic ranking system.</span><br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><b style="font-family: arial, helvetica, sans-serif;"> Determining postseason probabilities</b><br /><br />Elo's equations combined with teams' ratings can be used to calculate the probability of any team beating any other team. </span><span style="font-family: "arial" , "helvetica" , sans-serif;">For example, in the first game, Virginia, rated 1761, plays UMBC, rated 1604. Per Elo, Virginia's win probability is:</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"></span><br />
<div style="text-align: center;">
<span style="font-family: "courier new" , "courier" , monospace;">[1+10^((1604-1761)/400)]^-1 = 71.2%</span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">So Virginia is most likely to win. At this point, a call to a random number generator bounded on 0 to 1 can be used to simulate a game. If the result is < 0.712, Virginia wins, otherwise, UMBC wins. So Virginia is most likely to advance here, but we also can't rule out an upset either. How to track both outcomes? For this, I turned to Monte Carlo simulations. This allows us to re-run this game, and all downstream games, an arbitrarily large amount of times until a coherent image of overall probability emerges. </span><span style="font-family: "arial" , "helvetica" , sans-serif;">The result is the probability of any team reaching any round, encompassing both team skill and bracket structure. </span><a href="https://projects.fivethirtyeight.com/2018-march-madness-predictions/" style="font-family: arial, helvetica, sans-serif;">FiveThirtyEight</a><span style="font-family: "arial" , "helvetica" , sans-serif;"> has done a typically excellent job of visualizing this. My own visualiz</span><span style="font-family: "arial" , "helvetica" , sans-serif;">ation of the same data is shown below, though our models and probabilities differ.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br />As a clerical note</span><span style="font-family: "arial" , "helvetica" , sans-serif;">, I experimented with two approaches for dealing with Elo ratings after simulated games: "static" Elo, where the ratings are unchanged after games, and "dynamic" Elo, where the ratings are updated based on the simulated outcome. The difference between the two ended up being fairly negligible - more on this later.</span><br />
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /><b style="font-family: arial, helvetica, sans-serif;"> Incorporation of Monte Carlo simulations</b><br /><br /><span style="font-family: "arial" , "helvetica" , sans-serif;"> Each game in March Madness can have two possible outcomes, and there are 32+16+8+4+2+1 = 63 games in total. So the total number of brackets is 2^63, or 9.22 x 10^18. This enormous state space makes exhaustive analysis impossible, and also explains why Warren Buffett has not yet had to pay out </span><a href="http://fortune.com/2018/03/12/ncaa-bracket-warren-buffett-challenge/" style="font-family: arial, helvetica, sans-serif;">his jackpot prize</a><span style="font-family: "arial" , "helvetica" , sans-serif;"> for a perfect bracket, and is not likely to. However, exhaustive analysis, even if it was possible, is not necessary - Monte Carlo simulations provide a sufficiently accurate approximation.</span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /><span style="font-family: "arial" , "helvetica" , sans-serif;">My program operates at a speed of about 5,000 tournaments per second on a Dell Precision 5520. It monitors the maximum probability of any team becoming champion, as a figure of merit, and considers the probabilities converged when this value changes less than 0.025% between 5-second intervals. This takes around 100,000 tournaments, or 20 seconds.</span><br /><br /><b style="font-family: arial, helvetica, sans-serif;"> Visualizing probabilities</b><br /><br /><span style="font-family: "arial" , "helvetica" , sans-serif;"> </span></span><br />
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcEF-uqKfnIhOYyqZOVCujCMrLTCxrBqmYumQrGwZgGuCVGXN6uEqbFO0tSemLkecZ8MSXfopzIksJbUS5zsSXXFvigyrfAzzA7ZS9tnNyDslzD2uEcBgjwQCwAwzG2z2GHQekG5J6ldGF/s1600/probabilities_k_25_mean_1500_dynamic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="900" data-original-width="1183" height="486" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcEF-uqKfnIhOYyqZOVCujCMrLTCxrBqmYumQrGwZgGuCVGXN6uEqbFO0tSemLkecZ8MSXfopzIksJbUS5zsSXXFvigyrfAzzA7ZS9tnNyDslzD2uEcBgjwQCwAwzG2z2GHQekG5J6ldGF/s640/probabilities_k_25_mean_1500_dynamic.png" width="640" /></a></span></span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;">
</span></span>
<br />
<div style="text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Click to enlarge - </span></span>Elo K: 25, Elo mean: 1500, dynamic Elo in postseason</span></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Colors: <span style="text-align: start;">green denotes above-average probability for that round; red is below-average</span><span style="text-align: start;"> </span></span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">
</span>
<br />
<div style="text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">
</span>
<br />
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">The probabilities are then sorted according to each team's probability of winning the championship - more why the probabilities are sorted this way below. The low probability of the most likely outcomes - e.g. the strongest teams have only a 5-10% of winning the championship - </span><span style="font-family: "arial" , "helvetica" , sans-serif;">makes clear how difficult the outcome is to predict</span><span style="font-family: "arial" , "helvetica" , sans-serif;">. The ultimate odds are relatively slim for all but the top teams, and absolutely slim for all teams.</span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /><b style="font-family: arial, helvetica, sans-serif;"> Down-selecting to a single bracket</b><br /><br />In moving from probabilities to a final bracket, I considered how the bracket will be scored and more generally, what the ultimate goal is. In my case, my goal is to maximize my bracket's score, as scored by ESPN, so I can win the office pool. <a href="http://games.espn.com/tournament-challenge-bracket/2018/en/story?pageName=tcmen\rules">ESPN's rules</a> indicate:</span></div>
<div>
<div>
<ul><span style="font-family: "arial" , "helvetica" , sans-serif;">
<li>Round of 32: 10 points per pick</li>
<li>Round of 16: 20 points per pick</li>
<li>Round of 8: 40 points per pick</li>
<li>Round of 4: 80 points per pick</li>
<li>Round of 2: 160 points per pick</li>
<li>Round of 1: 320 points per pick</li>
</span></ul>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">This scoring system results in the optimal strategy being a bit counter-intuitive. Suppose every game is decided at random with a coin toss. The probability of correctly selecting the champion, worth 320 points, is 1/64, or 1.6%. One round upstream, the probability of correctly selecting both teams in the Round of 2, also worth 320 points, is (1/32)^2, or 0.1%. The percentages get progressively worse further upstream. In short, the expected point yield gets worse the further upstream you target, so the optimal strategy is to target as far downstream as possible - in effect, to build your bracket in reverse chronological order.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
</div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">
</span>
<br />
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">For my bracket, I use overall probability of winning the championship as the metric to determine which teams advance. If the rounds were equally weighted, or equivalently, if I was competing for overall percentage, I would simply advance the team with the greater Elo rating in each game, and Monte Carlo simulation would not be necessary.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<span style="font-family: "arial" , "helvetica" , sans-serif;">In summary, my bracket does not represent my best guess at the tournament's outcome, but rather a series of choices made to maximize score - an important distinction. </span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">
</span>
<br />
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<b style="font-family: Arial, Helvetica, sans-serif;">Sensitivity analysis</b><br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">To probe the sensitivity of my results to my modeling assumption, I wrapped an additional layer of abstraction around the bracket generator and modified three of the key model param</span><span style="font-family: "arial" , "helvetica" , sans-serif;">eters, borrowing historically stable values from chess to guide parameter ranges:</span><br />
<ol>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Elo mean - 1000 and 1500, the two standard values I've seen in literature</span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Elo K value - 10, 25, and 40, per <a href="https://en.wikipedia.org/wiki/Elo_rating_system#Most_accurate_K-factor">FIDE's standards</a></span></li>
<li><span style="font-family: "arial" , "helvetica" , sans-serif;">Elo rating in playoffs - either "dynamic" or "static"</span></li>
</ol>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Since it wasn't obvious which of these models was best, I decided to analyze all permutations, 12 in total, and weigh them equally. In other words, each bracket gets a vote, and the majority vote wins.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br />In general, the models are in unanimous agreement about the best choice for most bracket positions, including </span><span style="font-family: "arial" , "helvetica" , sans-serif;">from the Round of 4 onward, and with only a single dissenting vote in the Round of 8. Further upstream, minor disagreements creep in progressively. </span><span style="font-family: "arial" , "helvetica" , sans-serif;">After extracting a consensus from the brackets, I surveyed which, if any, models produced a bracket that exactly matched the consensus bracket - in other words, which model was most "centrist". I found that my initial set of model parameters - Elo mean: 1500, Elo K: 25, dynamic postseason Elo - provided an exact match. So the sensitivity analysis confirms that these settings are reasonably stable.</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span>
<b style="font-family: arial, helvetica, sans-serif;">My bracket</b><br />
<br style="font-family: arial, helvetica, sans-serif;" />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Bringing it all together, here is <a href="http://games.espn.com/tournament-challenge-bracket/2018/en/entry?entryID=581291">my bracket</a>:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4s279-5LiPSFpEnICX_QdfCIjU65_KN8p4NJcqhesb097gXJDZ8EkHe86PXlrjNbZSOOr9HfJGajf-LKorBgWDOiq-vicsdv8etjw3yW51bFQPHBq3ec3UTas8ifcDSkaRRpg1uq_MdCn/s1600/bracket_final.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="609" data-original-width="600" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4s279-5LiPSFpEnICX_QdfCIjU65_KN8p4NJcqhesb097gXJDZ8EkHe86PXlrjNbZSOOr9HfJGajf-LKorBgWDOiq-vicsdv8etjw3yW51bFQPHBq3ec3UTas8ifcDSkaRRpg1uq_MdCn/s1600/bracket_final.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b><span style="font-family: "arial" , "helvetica" , sans-serif;">Source Code</span></b></div>
<div class="separator" style="clear: both; text-align: left;">
<b><span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></b></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">Full source code and data logs, minus the game scraper, are available on <a href="https://github.com/kindofdoon/march_madness">my GitHub</a>.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><strike> </strike></span><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike><strike style="font-family: arial, helvetica, sans-serif;"> </strike></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><b>Update: April 4, 2018</b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><b><br /></b></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">March Madness is now complete. How did my bracket do?<br /><br />Better than average globally, but not as well as I hoped. It scored 680 points out of a possible 1920, ranked #9 of 16 in the office pool, and was 63rd percentile per ESPN.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir8WQIc1t9JOuRvRNxmiQRCNKK8NzkUgL5Kce_cfAW0SWe_rvS_UJKQkT4kCoRLZNVg2hpS_4bIvVpmCfPii4JcDyIbXrVZATnu4n-Q9qeqK2pKsSgGkKCMPzIFkx29Gi2TQmWmSOuuj27/s1600/bracket_percentile.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="292" data-original-width="465" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir8WQIc1t9JOuRvRNxmiQRCNKK8NzkUgL5Kce_cfAW0SWe_rvS_UJKQkT4kCoRLZNVg2hpS_4bIvVpmCfPii4JcDyIbXrVZATnu4n-Q9qeqK2pKsSgGkKCMPzIFkx29Gi2TQmWmSOuuj27/s1600/bracket_percentile.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">distribution of ESPN bracket scores from various pools</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">What does this mean for my bracket program? In short, it's hard to say. In the presence of March Madness' trademark unpredictability, a poor result does not necessarily indicate a poor decision-making process, nor does a good result indicate a good decision-making process.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">This year, UMBC upset Virginia in the first round, the first time in tournament history that a #16 seed defeated a #1 seed in the postseason. My program predicted Virginia had a 71% chance to win; FiveThirtyEight had them at <a href="https://projects.fivethirtyeight.com/2018-march-madness-predictions/">98%</a>; Ken Pomeroy <a href="https://kenpom.com/blog/2018-ncaa-tournament-probabilities/">97%</a>. Had Virginia instead won this match and continued to win the championship as I predicted, my bracket would have scored 1310, or 99th percentile. This is wishful thinking, of course, but it illustrates how sensitive the results are to flukes, upsets, injuries, or a team simply being "off" or "on".</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">More succinctly, The Harvard Sports Analysis Collective <a href="http://harvardsportsanalysis.org/2011/05/quantifying-intangibles-a-network-analysis-prediction-model-for-the-ncaa-tournament/">wrote</a> in 2011:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;">"More generally, almost all prediction methods make the dubious assumption that NCAA Tournament games are the same as regular season games. That does not seem to hold true. NCAA Tournament games are played in bigger arenas, under brighter media spotlights, and with higher stakes than almost any regular season game."</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">When it comes to bracketology, I've learned that there seems to be no end to the number of metrics and methods that armchair statisticians like myself have devised in an attempt to crack this inscrutable problem. T</span><span style="font-family: "arial" , "helvetica" , sans-serif;">he next steps I see for this are refining the prediction method using historical regular season and tournament outcomes, and also evaluating other sports, particularly baseball, which has a longer regular- and post-season, and so is a better candidate for statistical analysis.</span></div>
</div>
</div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0tag:blogger.com,1999:blog-3278537004721616095.post-21546295630045486142018-02-25T21:58:00.002-08:002018-09-23T18:39:25.074-07:00Tic-Tac-Toe, and Musings About Kasparov/Deep Blue<span style="font-family: "arial" , "helvetica" , sans-serif;">I'm currently reading Deep Thinking by Garry Kasparov, best known for his historic series of chess games against IBM's Deep Blue supercomputer in 1996 and 1997. These games are considered to be a collective watershed moment in the history of man/machine interaction for demonstrating that computers had finally exceeded human skill in the game of chess. In his book, Kasparov grieves that Deep Blue's victory was not the result of a scientific breakthrough about intelligence, but was rather an inevitability given the predictable relationship between computation speed and chess Elo rating, combined with Moore's Law. Kasparov's loss is fascinating for both its historical importance and its contemporary relevance, as computers continue reaching into increasingly "human" domains, such as driving cars, writing stories, diagnosing illnesses, and composing music.<br /><br /> In 1997, it shocked the public that a supercomputer could beat the chess world champion. In 2018, it's even more shocking that Kasparov held his own, achieving a win and several draws, against a supercomputer capable of evaluating more than 200,000,000 positions per second. This is absolutely astonishing to me, and difficult to even comprehend.<br /><br /> Inspired by this reading, I wrote an AI to play a much simpler game, tic-tac-toe. Unlike with chess, the game tree of tic-tac-toe can be explored fully in a reasonable amount of time because the game's <a href="https://en.wikipedia.org/wiki/Game_complexity#Complexities_of_some_well-known_games">state space is many orders of magnitude smaller</a>. Heuristic rules for perfect play are straightforward to grasp, and perfect play always results in a draw. My interest in tic-tac-toe has less to do with the game itself, and more in the game as a simple testbed for general 2-player perfect-information games like chess, the more complex of which are unlikely to ever be solved. Interestingly, this leaves room for technical and creative innovation in AI design, as evidenced by the recent dramatic overtaking of StockFish by AlphaZero in computer chess, which is radically different in design than its contemporaries.<br /><br /> My tic-tac-toe program uses random playouts to evaluate possible moves. A value matrix is incremented if the random playout results in victory, decremented if a loss, and unchanged if a draw. On my 2011 Dell E6420 laptop, the program executes about 700 playouts per second, which is very modest. Nonetheless, this is sufficient for the program to loosely deduce many higher-level game heuristics, such as:</span><br />
<div>
<br />
<ol style="font-family: Arial, Helvetica, sans-serif;">
<li>It's best to start play at the center, or secondarily the corners </li>
<li>A winning move out-ranks all other moves </li>
<li>If the opponent is one move away from winning, they must be blocked </li>
<li>Playing on the non-corner edges is weak unless blocking or winning </li>
</ol>
<span style="font-family: "arial" , "helvetica" , sans-serif;">To visualize the computer's "thoughts", I displayed the computer's value matrix alongside the game board - red for the worst move, green for the best, and gray for occupied spaces. It's fascinating to watch the computer's "thoughts" develop in a way that seems to mirror my own while playing in a much more casual fashion. </span><br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Most games result in a draw:</span><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGBJXNsi5gRb46xP3dg2DnUfvM55uGzsVik-baevurbDgySFnZ3KBgtsgS7v8tmaCVUq7NAkh-IuiPqMMhCk6HO1lUgnNHFP3VaGqfPzXzqFlHjIIGYuZ8yCTg8LNTbqRM5Dt0p2-7J-nm/s1600/ezgif-3-f0312a7257_draw.gif" style="font-family: Arial, Helvetica, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGBJXNsi5gRb46xP3dg2DnUfvM55uGzsVik-baevurbDgySFnZ3KBgtsgS7v8tmaCVUq7NAkh-IuiPqMMhCk6HO1lUgnNHFP3VaGqfPzXzqFlHjIIGYuZ8yCTg8LNTbqRM5Dt0p2-7J-nm/s640/ezgif-3-f0312a7257_draw.gif" /></a><br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Here, the computer capitalizes on my second-move blunder to create a fork, achieving a victory:</span><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOyQdiFyU0jEJrpYk6mcYDtKz20moDu0pMqjPbTkSTHktyhVcCEz45a3osAAY7V4NrxcO6YlPo6Fg5rUOwPmjP7ROuqcJuYxve-Q94ISOhcb0NHOBYe25grd3N2X_fcCxI2RTqoqzSAGEF/s1600/ezgif-3-aed7895c30_CPU_victory.gif" style="font-family: Arial, Helvetica, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOyQdiFyU0jEJrpYk6mcYDtKz20moDu0pMqjPbTkSTHktyhVcCEz45a3osAAY7V4NrxcO6YlPo6Fg5rUOwPmjP7ROuqcJuYxve-Q94ISOhcb0NHOBYe25grd3N2X_fcCxI2RTqoqzSAGEF/s640/ezgif-3-aed7895c30_CPU_victory.gif" /></a><br />
<br />
<br />
<br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Here, the computer fails to block, allowing me to win.</span><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFZkXLn4rchyGVwALcKwEE60xkmcnc1RfDAv8t_nkHLRWnJz8BfaC3lRaTIrxl7PRI3JTfgpBexWpTgvPI9Spplwhp3fqOoWBj9n3vwPaOkRlMlmVQKXxK9ORjPcbN9V1m_o0V-NFN8pf0/s1600/ezgif-3-a31a7c987c_human_victory.gif" style="font-family: Arial, Helvetica, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFZkXLn4rchyGVwALcKwEE60xkmcnc1RfDAv8t_nkHLRWnJz8BfaC3lRaTIrxl7PRI3JTfgpBexWpTgvPI9Spplwhp3fqOoWBj9n3vwPaOkRlMlmVQKXxK9ORjPcbN9V1m_o0V-NFN8pf0/s640/ezgif-3-a31a7c987c_human_victory.gif" /></a><br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">I probed this error on move 6 further by giving the computer a full 30 seconds to think, instead of the 2.5 seconds shown above. The value matrix came back as:</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> NaN NaN NaN<br />-8907 NaN -4317<br /> NaN -4442 -8824</span><br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">indicating that it considered the correct move, the block, a toss-up with its blunder move. Replaying the scenario repeatedly for debugging purposes, I noted that the computer chose to block about 50% of the time. Working through the game tree, it became clear why the computer blunders: the blocking move results in zero paths for O to win and one path for X to win, while the blunder move results in one path for O to win and two paths for X to win. The net score between the moves is equal at -1, so the computer essentially flips a coin in deciding between them.</span><br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtTpWVzdo9t3Lc4zpOzrc9lPLaMyVX_9e8WTkQVINgWe7SQlGMC2EVAlad6Fy07IYSiydqH9yUJ5mc18mgiiVfau3uQQ0rPRER6NdhJs7Zpn2_gTJ-4ZY_F-Cqd9JtXqe2qxUkLc9kdPr0/s1600/20180226_000448_crop.png" style="font-family: Arial, Helvetica, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhtTpWVzdo9t3Lc4zpOzrc9lPLaMyVX_9e8WTkQVINgWe7SQlGMC2EVAlad6Fy07IYSiydqH9yUJ5mc18mgiiVfau3uQQ0rPRER6NdhJs7Zpn2_gTJ-4ZY_F-Cqd9JtXqe2qxUkLc9kdPr0/s640/20180226_000448_crop.png" /></a><br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">So this is not a bug, but rather a limitation of the random playout valuation method in this particular game. It's easy enough to hard-code the computer to block, but it's much more interesting to see what the computer can and cannot work out on its own with a primitive valuation function. The short answer seems to be: a lot, but not everything.</span><br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">Full source code can be found on my GitHub:</span><br />
<br />
<a href="https://github.com/kindofdoon/tic_tac_toe" style="font-family: Arial, Helvetica, sans-serif;">https://github.com/kindofdoon/tic_tac_toe</a><br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">More games can be seen in this video:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/tAzFNP8XKbE/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/tAzFNP8XKbE?feature=player_embedded" width="320"></iframe></div>
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"></span></div>
Daniel W. Dichterhttp://www.blogger.com/profile/07858499797877507401noreply@blogger.com0