检查颜色是不是接近

Posted

技术标签:

【中文标题】检查颜色是不是接近【英文标题】:Check if colors are close检查颜色是否接近 【发布时间】:2018-03-12 15:50:44 【问题描述】:
    我得到了一张这样的图片,我想将一些特殊类型的滤镜应用到:

    我为深绿色区域(最大的区域)设置了 RGB 颜色 (49, 76, 14)。

所以我想获得某种阈值属性用于过滤目的:我想过滤每个图像像素以检查它的颜色是否接近给定的 RGB 值 (49, 76, 14)。阈值表示偏移率。

Threshold small :
             --> `(49, 76, 14) close to (48, 75, 13)`
             --> `(49, 76, 14) "not" close to (50, 75, 13)`

Threshold big :
             --> `(49, 76, 14) close to (48, 75, 13)`
             --> `(49, 76, 14) "also" close to (50, 75, 13)`

过滤具有最小阈值的图像,只过滤给定的 rgb 颜色:

更大的阈值也会过滤给定 rgb 颜色附近的颜色:

如何实现编码一个能够检查一种颜色是否接近另一种颜色(+阈值属性)(+使用 rgb 值)的函数?

注意:

这是我在上面首先考虑的代码,但对其进行了测试 - 它并没有真正导致成功(通过过滤给定的值,左上角的小区域首先应该被过滤,因为它的颜色几乎看起来像给定的一。但是这段代码首先匹配的是灰色的,显然与给定的颜色不匹配!)

 var offset = (threshold/100.0) * 255.0
 var color = [r,g,b]
 var r = redvalue, g = greenvalue, b = bluevalue
 if !(
      (r >= color[0]-offset) &&
      (r <= color[0]+offset) &&
      (g >= color[1]-offset) &&
      (g <= color[1]+offset) &&
      (b >= color[2]-offset) &&
      (b <= color[2]+offset)
     )  // apply filter 

任何帮助将不胜感激。一些用 Swift 或 JavaScript 甚至一些 PseudoCode 编写的源代码也可以。

编辑: 一个自发的想法是将 rgb-colors int lab-colors 转换为随后计算 欧几里得距离 来自两种颜色。但我不确定这个解决方案是否有效,也不确定它是否是最有效的解决方案:)

【问题讨论】:

有一些有趣的想法here 我编写了一个应用程序,通过将颜色的“距离”与命名颜色的规范 RGB 十六进制进行比较来命名图像中的颜色(ISTR 我使用了 X11 列表) - 我最终不得不这样做它在 HSL(色相饱和度亮度)而不是 RGB 中,色相的权重为 10 - 任意,但这似乎工作得很好。 能分享一些sn-ps的代码吗? :)@Grimxn 我认为您将浮点值与整数混合,这会导致舍入错误,因为您在示例中显示的两种颜色与您比较的绿色具有相同的距离......48 和 @987654336 @ 与49 的距离相同...尝试使用offset = round((threshold/100.0) * 255.0);floorceil ....我通常使用距离。您可以将颜色处理为 3D 向量,因此减去它们并计算距离...不需要 sqrt 您可以将距离^2 与阈值^2 进行比较...请参阅Detectings small circles on game minimap 我正是这样做的。 如果您需要更好的颜色检测,您可以使用 HSV,它处理颜色的方式更像人类感知。 【参考方案1】:

这不是一个完整的答案,而是对我在评论中提出的建议的详细说明,OP 要求我提供一些代码。

我有一个应用程序,它通过计算与 X11 三元组列表中的规范命名颜色的欧几里德距离来命名颜色(类似于 OP 试图做的事情,但目的不同)。正如他所做的那样,我发现使用 RGB 空间并不能给出直观的答案,因此我将每种颜色转换为色调饱和度亮度 (HSL) 维度,然后赋予色调维度比其他两个更高的权重。这是实际的“距离”代码,以及转换维度的支持函数:

private let oneThird = 1.0 / 3.0
private let twoThirds = 2.0 / 3.0

func hsl(red: Double, green: Double, blue: Double) -> (hue: Double, saturation: Double, lightness: Double) 
    let minv = min(red, green, blue)
    let maxv = max(red, green, blue)
    let diff = maxv - minv
    let sum = maxv + minv

    let l = sum * 0.5
    var s = 0.0
    var h = 0.0

    if (diff > 0.0) 
        if (l < 0.5) 
            s = diff / sum
         else 
            s = diff / (2.0 - sum)
        

        let dr = (((maxv - red) / 6.0) + (diff / 2.0)) / diff
        let dg = (((maxv - green) / 6.0) + (diff / 2.0)) / diff
        let db = (((maxv - blue) / 6.0) + (diff / 2.0)) / diff

        if red == maxv 
            h = db - dg
         else if green == maxv 
            h = oneThird + dr - db
         else if blue == maxv 
            h = twoThirds + dg - dr
        
    
    return (modp(h, denominator: 1.0), s, l)


func modp<T: BinaryFloatingPoint>(_ numerator : T, denominator : T) -> T 
    // acts as fmod, but assures the result is positive between 0 and fabs(denominator)
    let myDenominator = abs(denominator)
    var myNumerator = numerator.remainder(dividingBy: myDenominator)
    //var myNumerator = fmod(numerator, myDenominator)
    while (myNumerator < 0)  myNumerator += myDenominator 
    return myNumerator


let (h1, s1, l1) = hsl(red: r1, green: g1, blue: b1) // The reference colour
let (h2, s2, l2) = hsl(red: r2, green: g2, blue: b2) // The colour to be tested
let (dh, ds, dl) = (h1 - h2, s1 - s2, l1 - l2)
let hueWeight = 10 // Arbitrary, but works.
let distance = sqrt(hueWeight * dh * dh + ds * ds + dl * dl)

然后,您可以将您的 distance 值与您的阈值进行比较...

我认为 HSL 公式的原始来源是 here...

附言这些值我使用了Double——那是因为我使用了我自己的颜色类型——如果你用UIColor实现它,你最好使用CGFloats...

【讨论】:

【参考方案2】:

您的“接近某个阈值”的概念与 色彩空间的color model 有关。

颜色模型具有三个或四个维度。 RGB 在 3 个维度(或组件)中运行。

以目标颜色为中心的半径为“阈值”的球体的想法还不错。如果您设置该球体的边界,请注意负坐标。

如果RGBcolor 模型没有给您足够的“精度”,那么您可以更改为 CIELAB 或 HSL 模型;但是由于这些色彩空间中每个“维度”的含义不同,因此您需要同时使用多个阈值。

【讨论】:

如果您使用 HSL 而不是三个不同的阈值,则更多的是尺寸的 权重 的情况 - 权重可以固定 - 请参阅我对 OP 的评论。跨度>

以上是关于检查颜色是不是接近的主要内容,如果未能解决你的问题,请参考以下文章

使用 shapely 和 geopandas 检查点列表是不是接近 python 中的线串列表的快速方法

当播放器与接近提示交互时,它会检查播放器是不是有工具,如果没有,则执行功能 -ROBLOX STUDIO

检查 UIImage 是不是具有 alpha(透明)颜色的问题

检查两个节点相互接触时的颜色是不是相同

检查字符串是不是是有效的颜色表示

如何检查字符串是不是是有效的十六进制颜色表示?