繁体   English   中英

我如何知道一种 UIColor 和另一种 UIColor 之间的百分比差异?

[英]How can I know the difference in percentage between one UIColor and another?

我有一个基线UIColor (见下文)。 我怎么能知道如何彼此接近UIColor是我的底线UIColor ,让我们说.red.blue在这个例子中。

让我们忽略 alpha 通道。

最好我想要一个百分比返回,所以我可以打印类似“.red color is a 40% match to your base color”之类的东西。

在此处输入图片说明

我将在这里回答我自己的问题......

根据这个How to compare two colours for Similarity/difference ,为了得到正确的人类感知色差值,我们需要将UIColor的 RGB 转换为 Lab。 然后使用Lab,我们可以使用最新的CIEDE2000公式获得deltaE(即两种颜色之间的差异)值。

这是基于这里设置的这个令人敬畏的UIColor 扩展的 Swift 代码: https : //github.com/jathu/sweetercolor/blob/master/Sweetercolor/Sweetercolor.swift

这将获得两种颜色之间的 deltaE:

/**
    Detemine the distance between two colors based on the way humans perceive them.
    Uses the Sharma 2004 alteration of the CIEDE2000 algorithm.
 
    - parameter compare color: A UIColor to compare.
 
    - returns: A CGFloat representing the deltaE
*/
func CIEDE2000(compare color: UIColor) -> CGFloat {
    // CIEDE2000, Sharma 2004 -> http://www.ece.rochester.edu/~gsharma/ciede2000/ciede2000noteCRNA.pdf
    
    func rad2deg(r: CGFloat) -> CGFloat {
        return r * CGFloat(180/Double.pi)
    }
    
    func deg2rad(d: CGFloat) -> CGFloat {
        return d * CGFloat(Double.pi/180)
    }
    
    let k_l = CGFloat(1), k_c = CGFloat(1), k_h = CGFloat(1)
    
    let LAB1 = self.LAB
    let L_1 = LAB1[0], a_1 = LAB1[1], b_1 = LAB1[2]
    
    let LAB2 = color.LAB
    let L_2 = LAB2[0], a_2 = LAB2[1], b_2 = LAB2[2]
    
    let C_1ab = sqrt(pow(a_1, 2) + pow(b_1, 2))
    let C_2ab = sqrt(pow(a_2, 2) + pow(b_2, 2))
    let C_ab  = (C_1ab + C_2ab)/2
    
    let G = 0.5 * (1 - sqrt(pow(C_ab, 7)/(pow(C_ab, 7) + pow(25, 7))))
    let a_1_p = (1 + G) * a_1
    let a_2_p = (1 + G) * a_2
    
    let C_1_p = sqrt(pow(a_1_p, 2) + pow(b_1, 2))
    let C_2_p = sqrt(pow(a_2_p, 2) + pow(b_2, 2))
    
    // Read note 1 (page 23) for clarification on radians to hue degrees
    let h_1_p = (b_1 == 0 && a_1_p == 0) ? 0 : (atan2(b_1, a_1_p) + CGFloat(2 * Double.pi)) * CGFloat(180/Double.pi)
    let h_2_p = (b_2 == 0 && a_2_p == 0) ? 0 : (atan2(b_2, a_2_p) + CGFloat(2 * Double.pi)) * CGFloat(180/Double.pi)
    
    let deltaL_p = L_2 - L_1
    let deltaC_p = C_2_p - C_1_p
    
    var h_p: CGFloat = 0
    if (C_1_p * C_2_p) == 0 {
        h_p = 0
    } else if fabs(h_2_p - h_1_p) <= 180 {
        h_p = h_2_p - h_1_p
    } else if (h_2_p - h_1_p) > 180 {
        h_p = h_2_p - h_1_p - 360
    } else if (h_2_p - h_1_p) < -180 {
        h_p = h_2_p - h_1_p + 360
    }
    
    let deltaH_p = 2 * sqrt(C_1_p * C_2_p) * sin(deg2rad(d: h_p/2))
    
    let L_p = (L_1 + L_2)/2
    let C_p = (C_1_p + C_2_p)/2
    
    var h_p_bar: CGFloat = 0
    if (h_1_p * h_2_p) == 0 {
        h_p_bar = h_1_p + h_2_p
    } else if fabs(h_1_p - h_2_p) <= 180 {
        h_p_bar = (h_1_p + h_2_p)/2
    } else if fabs(h_1_p - h_2_p) > 180 && (h_1_p + h_2_p) < 360 {
        h_p_bar = (h_1_p + h_2_p + 360)/2
    } else if fabs(h_1_p - h_2_p) > 180 && (h_1_p + h_2_p) >= 360 {
        h_p_bar = (h_1_p + h_2_p - 360)/2
    }
    
    let T1 = cos(deg2rad(d: h_p_bar - 30))
    let T2 = cos(deg2rad(d: 2 * h_p_bar))
    let T3 = cos(deg2rad(d: (3 * h_p_bar) + 6))
    let T4 = cos(deg2rad(d: (4 * h_p_bar) - 63))
    let T = 1 - rad2deg(r: 0.17 * T1) + rad2deg(r: 0.24 * T2) - rad2deg(r: 0.32 * T3) + rad2deg(r: 0.20 * T4)
    
    let deltaTheta = 30 * exp(-pow((h_p_bar - 275)/25, 2))
    let R_c = 2 * sqrt(pow(C_p, 7)/(pow(C_p, 7) + pow(25, 7)))
    let S_l =  1 + ((0.015 * pow(L_p - 50, 2))/sqrt(20 + pow(L_p - 50, 2)))
    let S_c = 1 + (0.045 * C_p)
    let S_h = 1 + (0.015 * C_p * T)
    let R_t = -sin(deg2rad(d: 2 * deltaTheta)) * R_c
    
    // Calculate total
    
    let P1 = deltaL_p/(k_l * S_l)
    let P2 = deltaC_p/(k_c * S_c)
    let P3 = deltaH_p/(k_h * S_h)
    let deltaE = sqrt(pow(P1, 2) + pow(P2, 2) + pow(P3, 2) + (R_t * P2 * P3))
    
    return deltaE
}

这在上述函数 ( func CIEDE2000 ) 中func CIEDE2000以从 UIColor 获取 Lab 颜色:

/**
    Get the CIE L*ab values.
 
    - returns: An array of three CGFloat numbers representing LAB respectively.
*/
var LAB: [CGFloat] {
    // http://www.easyrgb.com/index.php?X=MATH&H=07#text7
    
    let XYZ = self.XYZ
    
    func LAB_helper(c: CGFloat) -> CGFloat {
        return 0.008856 < c ? pow(c, 1/3) : ((7.787 * c) + (16/116))
    }
    
    let X: CGFloat = LAB_helper(c: XYZ[0]/95.047)
    let Y: CGFloat = LAB_helper(c: XYZ[1]/100.0)
    let Z: CGFloat = LAB_helper(c: XYZ[2]/108.883)
    
    let L: CGFloat = (116 * Y) - 16
    let A: CGFloat = 500 * (X - Y)
    let B: CGFloat = 200 * (Y - Z)
    
    return [L, A, B]
}

色差

您可以找到获取两种颜色之间距离的公式。

由于色差的大多数定义是颜色空间内的距离,因此确定距离的标准方法是欧几里得距离。 如果当前有一个 RGB(红、绿、蓝)元组并希望找到颜色差异,那么计算上最简单的方法之一是考虑定义颜色空间的 R、G、B 线性维度。

在此处输入图片说明

当结果在计算上也应该很简单时,去除平方根并简单地使用通常是可以接受的:

在此处输入图片说明

尝试这个 :-

func testing(setColor: UIColor, myColor: UIColor)-> String{
    var finalSum : Float = 0.0
    for i in 0...2{
        var sum = setColor.cgColor.components![i] - myColor.cgColor.components![i]
        if sum < 0{
            sum = -sum
            finalSum = finalSum + Float(sum)
        }else{
            finalSum = finalSum + Float(sum)
        }
    }
    return "Colors match \(Int(finalSum*100/3))%"
}

用:-

print(testing(setColor: .blue, myColor: .brown))

我希望它对你有用:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM