下面的代码源于欧几里德距离算法的工作。颜色表只是测试算法的工具。它可能是在重新发明轮子,但它本身很有用。任何 3 个 RGB 整数 (0-255) 都可以与最接近的 X11 颜色名称相关联。非常感谢svick的见解。
在当前代码中,ColorTable 在创建实例后通过 AddColor 方法进行初始化。但是,可以使用 loadrgb/colorinfo 组合从 Web 上拉下 X11 颜色表。
我在从 X11 rgb.txt 文件的在线版本初始化颜色表时遇到了最后一个问题。我需要将文本解析为 {Name: Values:} 列表。目前,结果在字符串元组中。我正在努力让“colorinfo”加载“ColorTable”。
// currently the color table is create via the AddColor method, however
// the initial values should be created with the loadrgb and colorinfo members
type MyFSColorTable() =
// pull the X11 rgb.txt color table off the web in text format
static let loadrgb =
let url = "http://people.csail.mit.edu/jaffer/Color/rgb.txt"
let req = WebRequest.Create(url)
let resp = req.GetResponse()
let stream = resp.GetResponseStream()
let reader = new StreamReader(stream)
let txt = reader.ReadToEnd()
txt
// parse the text of the rgb.txt color table into a Name: Values: list
static let colorinfo =
loadrgb.Split([|'\n'|])
|> Seq.skip 1
|> Seq.map (fun line -> line.Split([|'\t'|]))
|> Seq.filter (fun values -> values |> Seq.length = 3)
|> Seq.map (fun values -> string values.[0], string values.[2])
|> Seq.map (fun (rgb, name) -> rgb.Split([|' '|]), name)
|> Seq.map (fun (rgb, name) -> [|name, rgb.[0], rgb.[1], rgb.[2]|])
// Mutable Color Table will be defined on-the-fly
let mutable ColorTable = []
// Euclidean distance between 2 vectors - float is overkill here
static let Dist (V1: float[]) V2 =
Array.zip V1 V2
|> Array.map (fun (v1, v2) -> pown (v1 - v2) 2)
|> Array.sum
// Add new colors to the head of the ColorTable
member x.AddColor name rgb = ColorTable <- {Name = name; Values = rgb}::ColorTable
// Find nearest color by calculating euclidean distance of all colors,
// then calling List.minBy for the smallest
member x.FindNearestColor (rgb : float[]) =
let nearestColor =
ColorTable |> List.minBy (fun color -> Dist rgb color.Values)
nearestColor.Name