Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>HCL is a very generic name there are a lot of ways to have a hue, a chroma, and a lightness. Chroma.js for example has something it calls HCL which is polar coord converted Lab (when you look at the actual code). Other implementations, even ones linked from that same site use Polar Luv. Since you can simply borrow the L factor and derive the hue by converting to polar coords these are both valid ways to get those three elements. It is far better to call them Polar Lab and Polar Luv, because of the confusion factor.</p> <p>M. Sarifuddin (2005)'s algorithm is not Polar Luv or Polar Lab and is computationally simpler (you don't need to derive Lab or Luv space first), and may actually be better. There are some things that seem wrong in the paper. For example applying a Euclidean distance to a CIE L*C*H* colorspace. The use of a Hue means it's necessarily round, and just jamming that number into A²+B²+C² is going to give you issues. The same is true to apply a hue-based colorspace to D94 or D00 as these are distance algorithms with built in corrections specific to Lab colorspace. Unless I'm missing something there, I'd disregard figures 6-8. And I question the rejection tolerances in the graphics. You could set a lower threshold and do better, and the numbers between color spaces are not normalized. In any event, despite a few seeming flaws in the paper, the algorithm described is worth a shot. You might want to do Euclidean on RGB if it doesn't really matter much. But, if you're shopping around for color distance algorithms, here you go.</p> <p>Here is HCL as given by M. Sarifuddin implemented in Java. Having read the paper repeatedly I cannot avoid the conclusion that it scales the distance by a factor of between 0.16 and 180.16 with regard to the change in hue in the distance_hcl routine. This is such a profound factor that it almost cannot be right at all. And makes the color matching suck. I have the paper's line commented out and use a line with only the Al factor. Scaling Luminescence by constant ~1.4 factor isn't going to make it unusable. With neither scale factor it ends up being identical to cycldistance.</p> <p><a href="http://w3.uqo.ca/missaoui/Publications/TRColorSpace.zip" rel="nofollow">http://w3.uqo.ca/missaoui/Publications/TRColorSpace.zip</a> is corrected and improved version of the paper.</p> <pre><code>static final public double Y0 = 100; static final public double gamma = 3; static final public double Al = 1.4456; static final public double Ach_inc = 0.16; public void rgb2hcl(double[] returnarray, int r, int g, int b) { double min = Math.min(Math.min(r, g), b); double max = Math.max(Math.max(r, g), b); if (max == 0) { returnarray[0] = 0; returnarray[1] = 0; returnarray[2] = 0; return; } double alpha = (min / max) / Y0; double Q = Math.exp(alpha * gamma); double rg = r - g; double gb = g - b; double br = b - r; double L = ((Q * max) + ((1 - Q) * min)) / 2; double C = Q * (Math.abs(rg) + Math.abs(gb) + Math.abs(br)) / 3; double H = Math.toDegrees(Math.atan2(gb, rg)); /* //the formulae given in paper, don't work. if (rg &gt;= 0 &amp;&amp; gb &gt;= 0) { H = 2 * H / 3; } else if (rg &gt;= 0 &amp;&amp; gb &lt; 0) { H = 4 * H / 3; } else if (rg &lt; 0 &amp;&amp; gb &gt;= 0) { H = 180 + 4 * H / 3; } else if (rg &lt; 0 &amp;&amp; gb &lt; 0) { H = 2 * H / 3 - 180; } // 180 causes the parts to overlap (green == red) and it oddly crumples up bits of the hue for no good reason. 2/3H and 4/3H expanding and contracting quandrants. */ if (rg &lt; 0) { if (gb &gt;= 0) H = 90 + H; else { H = H - 90; } } //works returnarray[0] = H; returnarray[1] = C; returnarray[2] = L; } public double cycldistance(double[] hcl1, double[] hcl2) { double dL = hcl1[2] - hcl2[2]; double dH = Math.abs(hcl1[0] - hcl2[0]); double C1 = hcl1[1]; double C2 = hcl2[1]; return Math.sqrt(dL*dL + C1*C1 + C2*C2 - 2*C1*C2*Math.cos(Math.toRadians(dH))); } public double distance_hcl(double[] hcl1, double[] hcl2) { double c1 = hcl1[1]; double c2 = hcl2[1]; double Dh = Math.abs(hcl1[0] - hcl2[0]); if (Dh &gt; 180) Dh = 360 - Dh; double Ach = Dh + Ach_inc; double AlDl = Al * Math.abs(hcl1[2] - hcl2[2]); return Math.sqrt(AlDl * AlDl + (c1 * c1 + c2 * c2 - 2 * c1 * c2 * Math.cos(Math.toRadians(Dh)))); //return Math.sqrt(AlDl * AlDl + Ach * (c1 * c1 + c2 * c2 - 2 * c1 * c2 * Math.cos(Math.toRadians(Dh)))); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload