<p><a href="https://stackoverflow.com/questions/180/function-for-creating-color-wheels">Original Question</a></p>

<p>I am looking for a function that attempts to quantify how "distant" (or distinct) two colors are. This question is really in two parts: </p>

<ol>
<li>What color space best represents human vision?</li>
<li>What distance metric in that space best represents human vision (euclidean?)</li>
</ol>

[{'answer_id': 1322, 'author': 'Lasse V. Karlsen', 'author_id': 267, 'author_profile': 'https://Stackoverflow.com/users/267', 'pm_score': 2, 'selected': False, 'text': '<p>The easiest <em>distance</em> would of course be to just consider the colors as 3d vectors originating from the same origin, and taking the distance between their end points.</p>\n\n<p>If you need to consider such factors that green is more prominent in judging intensity, you can weigh the values.</p>\n\n<p><a href="http://www.imagemagick.org/Usage/color/#grayscale" rel="nofollow noreferrer">ImageMagic</a> provides the following scales:  </p>\n\n<ul>\n<li>red: 0.3</li>\n<li>green: 0.6</li>\n<li>blue: 0.1</li>\n</ul>\n\n<p>Of course, values like this would only be meaningful in relation to other values for other colors, not as something that would be meaningful to humans, so all you could use the values for would be similiarity ordering.</p>\n'}, {'answer_id': 1325, 'author': 'huseyint', 'author_id': 39, 'author_profile': 'https://Stackoverflow.com/users/39', 'pm_score': 3, 'selected': False, 'text': '<p>HSL and HSV are better for human color perception. According to <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" rel="nofollow noreferrer">Wikipedia</a>:</p>\n\n<blockquote>\n  <p>It is sometimes preferable in working with art materials, digitized images, or other media, to use the HSV or HSL color model over alternative models such as RGB or CMYK, because of differences in the ways the models emulate how humans perceive color. RGB and CMYK are additive and subtractive models, respectively, modelling the way that primary color lights or pigments (respectively) combine to form new colors when mixed.</p>\n</blockquote>\n\n<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/HSV_cylinder.png/200px-HSV_cylinder.png" alt="Graphical depiction of HSV"></p>\n'}, {'answer_id': 1348, 'author': 'Brendan', 'author_id': 199, 'author_profile': 'https://Stackoverflow.com/users/199', 'pm_score': 2, 'selected': False, 'text': '<p>Well, as a first point of call, I\'d say of the common metrics HSV (Hue, Saturation and Value) or HSL are better representative of how humans perceive colour than say RGB or CYMK. See <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" rel="nofollow noreferrer">HSL, HSV on Wikipedia</a>. </p>\n\n<p>I suppose naively I would plot the points in the HSL space for the two colours and calculate the magnitude of the difference vector. However this would mean that bright yellow and bright green would be considered just as different as green to dark green. But then many consider red and pink two different colours.</p>\n\n<p>Moreover, difference vectors in the same direction in this parameter space are not equal. For instance, the human eye picks up green much better than other colours. A shift in hue from green by the same amount as a shift from red may seem greater. Also a shift in saturation from a small amount to zero is the difference between grey and pink, elsewhere the shift would be the difference between two shades of red.</p>\n\n<p>From a programmers point of view, you would need to plot the difference vectors but modified by a proportionality matrix that would adjust the lengths accordingly in various regions of the HSL space - this would be fairly arbitrary and would be based on various colour theory ideas but be tweaked fairly arbitrarily depending on what you wanted to apply this to.</p>\n\n<p>Even better, you could see if anyone has already done such a thing online...</p>\n'}, {'answer_id': 25118, 'author': 'palm3D', 'author_id': 2686, 'author_profile': 'https://Stackoverflow.com/users/2686', 'pm_score': 2, 'selected': False, 'text': '<p>The <a href="http://en.wikipedia.org/wiki/Color_difference" rel="nofollow noreferrer">Wikipedia article on color differences</a> lists a number of color spaces and distance metrics designed to agree with human perception of color distances.</p>\n'}, {'answer_id': 74033, 'author': 'DarenW', 'author_id': 10468, 'author_profile': 'https://Stackoverflow.com/users/10468', 'pm_score': 7, 'selected': True, 'text': '<p>Convert to La*b* (aka just plain "Lab", and you\'ll also see reference to "CIELAB").   A good quick measaure of color difference is   </p>\n\n<blockquote>\n  <p>(L1-L2)^2 + (a1-a2)^2 + (b1-b2)^2</p>\n</blockquote>\n\n<p>Color scientists have other more refined measures, which may not be worth the bother, depending on accuracy needed for what you\'re doing.</p>\n\n<p>The <code>a</code> and <code>b</code> values represent opposing colors in a way similar to how cones work, and may be negative or positive.   Neutral colors - white, grays are <code>a=0</code>,<code>b=0</code>. The <code>L</code> is brightness defined in a particular way, from zero (pure darkness) up to whatever.  </p>\n\n<p>Crude explanation :>> Given a color, our eyes distinguish between two broad ranges of wavelength - blue vs longer wavelengths. and then, thanks to a more recent genetic mutation, the longer wavelength cones bifurcated into two, distinguishing for us red vs. green.     </p>\n\n<p>By the way, it\'ll be great for your career to rise above your color caveman collegues who know of only "RGB" or "CMYK" which are great for devices but suck for serious perception work.  I\'ve worked for imaging scientists who didn\'t know a thing about this stuff!</p>\n\n<p>For more fun reading on color difference theory, try:</p>\n\n<ul>\n<li><a href="http://white.stanford.edu/~brian/scielab/introduction.html" rel="noreferrer">http://white.stanford.edu/~brian/scielab/introduction.html</a> and info </li>\n<li>and links on color theory in general, websurf starting with <a href="http://www.efg2.com/Lab/Library/Color/" rel="noreferrer">http://www.efg2.com/Lab/Library/Color/</a> and </li>\n<li><a href="http://www.poynton.com/Poynton-color.html" rel="noreferrer">http://www.poynton.com/Poynton-color.html</a>  </li>\n</ul>\n\n<p>More detail on Lab at <a href="http://en.kioskea.net/video/cie-lab.php3" rel="noreferrer">http://en.kioskea.net/video/cie-lab.php3</a> I can\'t at this time find a non-ugly page that actually had the conversion formulas but I\'m sure someone will edit this answer to include one.</p>\n'}, {'answer_id': 74396, 'author': 'bruceatk', 'author_id': 791, 'author_profile': 'https://Stackoverflow.com/users/791', 'pm_score': 2, 'selected': False, 'text': "<p>As someone who is color blind I believe it is good to try to add more separation then normal vision.  The most common form of color blindness is red/green deficiency.  It doesn't mean that you can't see red or green, it means that it is more difficult to see and more difficult to see the differences.  So it takes a larger separation before a color blind person can tell the difference.</p>\n"}, {'answer_id': 19416874, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 3, 'selected': False, 'text': '<p>as cmetric.htm link above failed for me, as well as many other implementations for color distance I found (after a very long jurney..) how to calculate the best color distance, and .. most scientifically accurate one: <strong>deltaE</strong> and from 2 RGB (!) values using OpenCV:</p>\n\n<p>This required 3 color space conversions + some code conversion from javascript (<a href="http://svn.int64.org/viewvc/int64/colors/colors.js">http://svn.int64.org/viewvc/int64/colors/colors.js</a>) to C++</p>\n\n<p>And finally the code (seems to work right out of the box, hope no one finds a serious bug there ... but it seems fine after a number of tests)</p>\n\n<pre><code>#include &lt;opencv2/core/core.hpp&gt;\n#include &lt;opencv2/imgproc/imgproc.hpp&gt;\n#include &lt;opencv2/highgui/highgui.hpp&gt;\n#include &lt;opencv2/photo/photo.hpp&gt;\n#include &lt;math.h&gt;\n\nusing namespace cv;\nusing namespace std;\n\n#define REF_X 95.047; // Observer= 2°, Illuminant= D65\n#define REF_Y 100.000;\n#define REF_Z 108.883;\n\nvoid bgr2xyz( const Vec3b&amp; BGR, Vec3d&amp; XYZ );\nvoid xyz2lab( const Vec3d&amp; XYZ, Vec3d&amp; Lab );\nvoid lab2lch( const Vec3d&amp; Lab, Vec3d&amp; LCH );\ndouble deltaE2000( const Vec3b&amp; bgr1, const Vec3b&amp; bgr2 );\ndouble deltaE2000( const Vec3d&amp; lch1, const Vec3d&amp; lch2 );\n\n\nvoid bgr2xyz( const Vec3b&amp; BGR, Vec3d&amp; XYZ )\n{\n    double r = (double)BGR[2] / 255.0;\n    double g = (double)BGR[1] / 255.0;\n    double b = (double)BGR[0] / 255.0;\n    if( r &gt; 0.04045 )\n        r = pow( ( r + 0.055 ) / 1.055, 2.4 );\n    else\n        r = r / 12.92;\n    if( g &gt; 0.04045 )\n        g = pow( ( g + 0.055 ) / 1.055, 2.4 );\n    else\n        g = g / 12.92;\n    if( b &gt; 0.04045 )\n        b = pow( ( b + 0.055 ) / 1.055, 2.4 );\n    else\n        b = b / 12.92;\n    r *= 100.0;\n    g *= 100.0;\n    b *= 100.0;\n    XYZ[0] = r * 0.4124 + g * 0.3576 + b * 0.1805;\n    XYZ[1] = r * 0.2126 + g * 0.7152 + b * 0.0722;\n    XYZ[2] = r * 0.0193 + g * 0.1192 + b * 0.9505;\n}\n\nvoid xyz2lab( const Vec3d&amp; XYZ, Vec3d&amp; Lab )\n{\n    double x = XYZ[0] / REF_X;\n    double y = XYZ[1] / REF_X;\n    double z = XYZ[2] / REF_X;\n    if( x &gt; 0.008856 )\n        x = pow( x , .3333333333 );\n    else\n        x = ( 7.787 * x ) + ( 16.0 / 116.0 );\n    if( y &gt; 0.008856 )\n        y = pow( y , .3333333333 );\n    else\n        y = ( 7.787 * y ) + ( 16.0 / 116.0 );\n    if( z &gt; 0.008856 )\n        z = pow( z , .3333333333 );\n    else\n        z = ( 7.787 * z ) + ( 16.0 / 116.0 );\n    Lab[0] = ( 116.0 * y ) - 16.0;\n    Lab[1] = 500.0 * ( x - y );\n    Lab[2] = 200.0 * ( y - z );\n}\n\nvoid lab2lch( const Vec3d&amp; Lab, Vec3d&amp; LCH )\n{\n    LCH[0] = Lab[0];\n    LCH[1] = sqrt( ( Lab[1] * Lab[1] ) + ( Lab[2] * Lab[2] ) );\n    LCH[2] = atan2( Lab[2], Lab[1] );\n}\n\ndouble deltaE2000( const Vec3b&amp; bgr1, const Vec3b&amp; bgr2 )\n{\n    Vec3d xyz1, xyz2, lab1, lab2, lch1, lch2;\n    bgr2xyz( bgr1, xyz1 );\n    bgr2xyz( bgr2, xyz2 );\n    xyz2lab( xyz1, lab1 );\n    xyz2lab( xyz2, lab2 );\n    lab2lch( lab1, lch1 );\n    lab2lch( lab2, lch2 );\n    return deltaE2000( lch1, lch2 );\n}\n\ndouble deltaE2000( const Vec3d&amp; lch1, const Vec3d&amp; lch2 )\n{\n    double avg_L = ( lch1[0] + lch2[0] ) * 0.5;\n    double delta_L = lch2[0] - lch1[0];\n    double avg_C = ( lch1[1] + lch2[1] ) * 0.5;\n    double delta_C = lch1[1] - lch2[1];\n    double avg_H = ( lch1[2] + lch2[2] ) * 0.5;\n    if( fabs( lch1[2] - lch2[2] ) &gt; CV_PI )\n        avg_H += CV_PI;\n    double delta_H = lch2[2] - lch1[2];\n    if( fabs( delta_H ) &gt; CV_PI )\n    {\n        if( lch2[2] &lt;= lch1[2] )\n            delta_H += CV_PI * 2.0;\n        else\n            delta_H -= CV_PI * 2.0;\n    }\n\n    delta_H = sqrt( lch1[1] * lch2[1] ) * sin( delta_H ) * 2.0;\n    double T = 1.0 -\n            0.17 * cos( avg_H - CV_PI / 6.0 ) +\n            0.24 * cos( avg_H * 2.0 ) +\n            0.32 * cos( avg_H * 3.0 + CV_PI / 30.0 ) -\n            0.20 * cos( avg_H * 4.0 - CV_PI * 7.0 / 20.0 );\n    double SL = avg_L - 50.0;\n    SL *= SL;\n    SL = SL * 0.015 / sqrt( SL + 20.0 ) + 1.0;\n    double SC = avg_C * 0.045 + 1.0;\n    double SH = avg_C * T * 0.015 + 1.0;\n    double delta_Theta = avg_H / 25.0 - CV_PI * 11.0 / 180.0;\n    delta_Theta = exp( delta_Theta * -delta_Theta ) * ( CV_PI / 6.0 );\n    double RT = pow( avg_C, 7.0 );\n    RT = sqrt( RT / ( RT + 6103515625.0 ) ) * sin( delta_Theta ) * -2.0; // 6103515625 = 25^7\n    delta_L /= SL;\n    delta_C /= SC;\n    delta_H /= SH;\n    return sqrt( delta_L * delta_L + delta_C * delta_C + delta_H * delta_H + RT * delta_C * delta_H );\n}\n</code></pre>\n\n<p>Hope it helps someone :)</p>\n'}]
['https://Stackoverflow.com/questions/1313', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/2089740/']