【问题标题】:How can I know the difference in percentage between one UIColor and another?我如何知道一种 UIColor 和另一种 UIColor 之间的百分比差异?
【发布时间】:2020-11-23 06:32:10
【问题描述】:

我有一个基线UIColor(见下文)。我怎么知道另一个UIColor 与我的基线UIColor 有多接近,在这个例子中假设.red.blue

让我们忽略 alpha 通道。

最好我希望返回一个百分比,这样我就可以打印类似“.red color is a 40% match to your baseline color”之类的内容。

【问题讨论】:

    标签: ios swift uicolor


    【解决方案1】:

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

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

    这里是基于 awesome 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) 中调用此函数以从 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]
    }
    

    【讨论】:

      【解决方案2】:

      Color difference.

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

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

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

      【讨论】:

      • 谢谢!这让我走上了正确的道路。从这个stackoverflow.com/questions/9018016/… 看来,我可能需要考虑使用deltaE 方法,但以获得更人类感知的准确结果。
      • 当然,最好检查一下哪个更适合人眼。从here 获得黑色和绿色之间 %80 的相似度很有趣:)
      【解决方案3】:

      试试这个:-

      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))

      我希望它对你有用:)

      【讨论】:

        猜你喜欢
        • 2023-03-04
        • 1970-01-01
        • 1970-01-01
        • 2020-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-20
        相关资源
        最近更新 更多