将任意字符串映射到RGB值

8
我有一大批任意的自然语言字符串。为了让我的工具对它们进行分析,我需要将每个字符串转换为唯一的颜色值(RGB或其他)。我需要颜色对比度取决于字符串相似性(字符串与其他字符串越不同,它们各自的颜色就应该越不同)。如果我总是得到相同的字符串的颜色值就更完美了。
你有什么建议来解决这个问题吗?
关于字符串之间的距离更新:
我可能需要像Levenstein距离这样定义“相似性”。不需要进行自然语言分析。
也就是说:
"I am going to the store" and 
"We are going to the store"

相似。

"I am going to the store" and 
"I am going to the store today"

与之类似(但略微较少)。

"I am going to the store" and 
"J bn hpjoh up uif tupsf"

相当不相似。

(感谢Welbog!)

只有当我看到程序输出时,我才可能知道我需要什么样的距离函数。所以让我们从简单的事情开始。

任务简化更新

我已经删除了将任务分为两个部分——绝对距离计算和颜色分布的建议。这不会起作用,因为首先我们将维度信息缩减为一维,然后再试图将其综合成三维。


色调实际上并不是三维的。你可能想要在变化色调时比其他值更加多样化,因为当你得到低值或高饱和度时,你无法真正区分颜色。我的主要建议是在HSV空间中工作,而不是RGB,主要使用色调。 - Welbog
8个回答

3
你需要更详细地解释“类似字符串”的含义,以便编写适当的转换函数。这些字符串是什么?
 "I am going to the store" and 
"We are going to the store" 

被认为相似?那字符串呢?
 "I am going to the store" and 
"J bn hpjoh up uif tupsf" 

(将原始文本中的每个字母+1),或

 "I am going to the store" and 
"I am going to the store today"

根据您所说的“相似”,您可能会考虑不同的函数。

如果差异仅基于字符的值(在Unicode或任何其他空间中), 那么您可以尝试将这些值相加,并将结果用作HSV空间的色调。如果较长的字符串应导致颜色更加不同,您可以考虑按其在字符串中的位置加权字符。

如果差异更为复杂,例如某些字母或单词的出现次数,则需要确定这一点。如果您的领域有很多这些东西,那么也许您可以根据字符串中E、S和R的数量选择红、绿和蓝值。或者根据元音与辅音的比率,或者根据单词与音节的比率选择色调。

有许多不同的方法来解决这个问题,但最好的方法取决于您所说的“相似”字符串。


2

听起来你需要某种哈希算法。它不需要很安全(所以不用像MD5或SHA那样复杂),但可以使用以下方法:

char1 + char2 + char3 + ... + charN % MAX_COLOUR_VALUE

作为简单的第一步,可以这样做。您还可以进行更高级的操作,比如让每个字符充当R、G和B的“振幅”(例如e可以是+1R、+2G和-4B等),然后只需将字符串中所有值相加…在末尾对它们进行夹紧,就可以将任意长度的字符串转换为颜色,作为一种“颜色哈希”过程。


1
不行 - MD5故意破坏了局部性。如果S1和S2相似,color(S1)和color(S2)应该是相似的。但MD5(S1)和MD5(S2)并不相似。 - MSalters
好的,但我并没有建议使用MD5,这只是为了更清晰明了。 - workmad3

1

1
首先,您需要选择一种测量字符串相似性的方法。最小编辑距离是传统的方法,但不足以对字符串进行良好排序,如果您想每次将相同颜色分配给相同的字符串,则需要这样做 - 也许您可以按字母距离加权编辑成本。此外,仅使用最小编辑距离可能不太有用,如果您想要的是口语上的相似性而不是书面形式(如果是这样,请先考虑词干/ Soundex 处理)或其他“相似性”的意义。
然后,您需要选择一种基于该度量标准遍历可见颜色空间的方法。考虑使用HSL 或 HSV 颜色表示法可能会有所帮助 - 然后算法可以变得简单,只需选择一个起始色调并遍历排序的语料库,在偏移前一个字符串的差异之前将当前色调分配给每个字符串。

1
多重字符串颜色相同对于编程有多重要?
如果不是非常重要,那么也许这个方法可以奏效?
您可以选择一个与圆“同伦”的一维颜色空间:假设颜色函数 c(x) 的定义范围是 0 1 。 然后,您希望c(0) == c(1)
现在,您将所有字符值的总和取模某些缩放因子,并将其回绕到颜色空间中: c((SumOfCharValues(word) modulo ScalingFactor) / ScalingFactor) 如果定义了更高维度的“包装”颜色空间,并且为每个维度选择不同的 SumOfCharValues 功能,则此方法可能效果更好;有人建议交替使用和长度求和。
仅供参考...希望有所帮助

哦,我看到其他人也建议了这个,但用其他话说...抱歉! - wires

1
这是我的建议(我认为这个算法有一个通用的名称,但我太累了,记不起来了):
您想将每个字符串转换为一个3D点节点(r, g, b)(您可以缩放值,使其适合您的范围),以便最小化以下误差:
Error = \sum_i{\sum_j{(dist(node_i, node_j) - dist(str_i, str_j))^2}}

你可以这样做:
  1. 首先为每个字符串分配一个随机颜色(r,g,b)
  2. 重复直到满意(例如,误差调整小于\epsilon = 0.0001):
    1. 选择一个随机节点
    2. 调整其位置(r,g,b),以使误差最小化
  3. 缩放坐标系,使得每个节点的坐标在范围[0.,1.)或[0, 256]内

0

我可能会定义两个字符串之间的一些差异。我不知道您如何定义两个字符串的差异(或“不相等”),但我能想到的最明显的事情是字符串长度和特定字母出现的次数(以及它们在字符串中的索引)。实现它应该不难,使得在相等的字符串中返回相同的颜色代码(如果您先进行相等比较,并在进一步比较之前返回)。

当涉及到实际的RGB值时,我会尝试将字符串数据转换为4个字节(RGBA),或者如果您只使用RGB,则为3个字节。我不知道每个字符串是否都适合它们(因为这可能是语言特定的?)。


0

抱歉,但您无法使用Levenshtein距离或类似方法完成您要寻找的操作。RGB和HSV是三维几何空间,而Levenshtein距离描述了一个度量空间 - 一组没有固定维数的松散约束条件。在始终保持局部性的情况下,无法将度量空间映射到固定数量的维度。

就近似而言,对于单个术语,您可以使用Soundex或Metaphone算法的修改版本来选择颜色;对于多个术语,例如,您可以将Soundex或Metaphone应用于每个单独的单词,然后将它们相加(带溢出)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接