[英]How can I know the difference in percentage between one UIColor and another?
我将在这里回答我自己的问题......
根据这个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.