HSV颜色空间是一个圆椎形的空间,如果用x,y,z坐标来计算两个颜色的距离,我认为是不正确的。
因此,写了这么一段代码(C++),计算圆椎内两个点与中轴形成的轴对称扇面的对角线,用这个长度作为HSV空间内两个颜色之间的距离。
   struct SpHSV{
        float h;
        float s;
        float v;
        SpHSV()
        {
            h = s = v = 0.0f;
        }
        SpHSV(float _h, float _s, float _v)
        {
            h = _h; s = _s; v = _v;
        }
        inline float distance(const SpHSV& other) const
        {
            float arc = abs(h - other.h);
            arc = (arc > 0.5f ? 1.0f - arc : arc) * 2.0f * 3.1415926f;
            float r1 = s * (v);
            float r2 = other.s * (other.v);
            float height = sqrt((r1 - r2) * (r1 - r2) + (v - other.v) * (v - other.v));
            return sqrt( r1 * arc * r2 * arc + height * height);
        }
    };
另外还有 HSL 的版本
    struct SpHSL{
        float h;
        float s;
        float l;
        SpHSL()
        {
            h = s = l = 0.0f;
        }
        SpHSL(float _h, float _s, float _l)
        {
            h = _h; s = _s; l = _l;
        }
        inline float distance( const SpHSL& other) const
        {
            float arc = abs(h - other.h);
            arc = (arc > 0.5f ? 1.0f - arc : arc) * 2.0f * 3.1415926f;
            float r1 = (s * (1.0f - abs(0.5f - l) * 2.0f));
            float r2 = (other.s * (1.0f - abs(0.5f - other.l) * 2.0f));
            float height = sqrt((r1 - r2) * (r1 - r2) + (l - other.l) * (l - other.l));
            return sqrt(r1 * arc * r2 * arc + height * height);
        }
    };
RGB 的版本
  struct SpRGB{
        float r;
        float g;
        float b;
        SpRGB()
        {
            r = g = b = 0.0f;
        }
        SpRGB(float _r, float _g, float _b)
        {
            r = _r; g = _g; b = _b;
        }
        SpRGB(int32_t _r, int32_t _g, int32_t _b)
        {
            r = _r / 255.0f; g = _g / 255.0f; b = _b / 255.0f;
        }
        inline bool isEqual(float a, float b) const
        {
            return abs(a - b) < 0.00392157f;
        }
        inline bool operator == (const SpRGB& other)
        {
            return (isEqual(r, other.r) && isEqual(g, other.g) && isEqual(b, other.b));
        }
        inline float distance( const SpRGB& other) const
        {
            float x = r - other.r, y = g - other.g, z = b - other.b;
            return sqrt(x*x + y*y + z*z);
        }
        //验证颜色转换计算结果:http://colorizer.org/
        SpHSV toHSV() const
        {
            //返回的 vec3 中,均为归一化的值,包括色相 s。
            float maxValue = std::max(r, std::max(g, b));
            float minValue = std::min(r, std::min(g, b));
            float v = maxValue - minValue;
            SpHSV hsv(0.0f, 0.0f, maxValue);
            if ( v > 0.0f )
            {
                hsv.s = v / maxValue;
                if (isEqual(maxValue, r))
                    hsv.h = ((g - b) / v + (g < b ? 6.0f : 0.0f)) / 6.0f;
                else if (isEqual(maxValue, g))
                    hsv.h = ((b - r) / v + 2.0f) / 6.0f;
                else
                    hsv.h = ((r - g) / v + 4.0f) / 6.0f;
            }
            return hsv;
        }
        SpHSL toHSL() const
        {
            float maxValue = std::max(r, std::max(g, b));
            float minValue = std::min(r, std::min(g, b));
            float v = maxValue - minValue;
            SpHSL hsl(0.0f, 0.0f, (maxValue + minValue) * 0.5f);
            if (v > 0.0f )
            {
                //计算色深,等价于 s = l < 0.5 ? v/(2.0*l) : v/(2.0-2.0*l);
                hsl.s = v / ( 1.0f - abs( 2.0f * hsl.l - 1.0f));
                if (isEqual(maxValue, r))
                    hsl.h = ((g - b) / v + (g < b ? 6.0f : 0.0f)) / 6.0f;
                else if (isEqual(maxValue, g))
                    hsl.h = ((b - r) / v + 2.0f) / 6.0f;
                else
                    hsl.h = ((r - g) / v + 4.0f) / 6.0f;
            }
            return hsl;
        }
    };转载请注明:《计算HSV颜色空间中,两个颜色的距离》
