本文实现了三种颜色匹配的方法,
一,先将Color结构的颜色转换为HSB颜色,然后再对其进行匹配比较,这是目前为止比较准确的一种方法,得到的颜色近似度很高
二,比较两个Color结构颜色的RGB分量的差的绝对大小,设定一个阈值,选出最为接近的一个,这种方法精度不高,有些颜色会有很明显的失真,但速度较快
三,比较两个Color结构颜色的RGB分量的差的平方和的大小,得到容差,最好选出容差最小的一个,这种方法精度比(二)高,速度比(一)快
笔者用的第一种方法,对256颜色匹配的非常好,其中三种方法的代码(VB.Net)如下,大家一看便知如何应用
#Region "先转换成hsb颜色,再进行匹配,最为准确的颜色匹配方法"
''' <summary>
''' hsb颜色类,相当于一个结构
''' </summary>
''' <remarks></remarks>
Class HSB
Public Hue As Double
Public Saturation As Double
Public Brightness As Double
Sub New(ByVal h As Double, ByVal s As Double, ByVal b As Double)
Hue = h
Saturation = s
Brightness = b
End Sub
End Class
''' <summary>
''' rgb转换为hsb
''' </summary>
''' <param name="red"></param>
''' <param name="green"></param>
''' <param name="blue"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function RGBtoHSB(ByVal red As Integer, ByVal green As Integer, ByVal blue As Integer) As HSB
Dim r As Double = red / 255.0
Dim g As Double = green / 255.0
Dim b As Double = blue / 255.0
Dim max As Double = Math.Max(r, Math.Max(g, b))
Dim min As Double = Math.Min(r, Math.Min(g, b))
Dim h As Double = 0.0
If (max = r And g >= b) Then
h = 60 * (g - b) / (max - min)
ElseIf (max = r And g < b) Then
h = 60 * (g - b) / (max - min) + 360
ElseIf (max = g) Then
h = 60 * (b - r) / (max - min) + 120
ElseIf (max = b) Then
h = 60 * (r - g) / (max - min) + 240
End If
Dim s As Double
If max = 0 Then
s = 0.0
Else
s = 1.0 - (min / max)
End If
Return New HSB(h, s, max)
End Function
''' <summary>
''' 获得最为接近的索引颜色
''' </summary>
''' <param name="color">所比较的颜色</param>
''' <param name="LabelColorsHSB">颜色列表</param>
''' <returns>返回与所比较的颜色最为接近的颜色在颜色列表中的索引值</returns>
''' <remarks></remarks>
Private Function GetNearestColorLabelIndex(ByVal color As Color, ByVal LabelColorsHSB As List(Of HSB)) As Integer
Const weightHue As Double = 0.8
Const weightSaturation As Double = 0.1
Const weightValue As Double = 0.1
Dim minDistance As Double = Double.MaxValue
Dim minIndex As Integer = 255
Dim targetHSB As HSB = RGBtoHSB(color.R, color.G, color.B)
For i As Integer = 0 To LabelColorsHSB.Count - 1
Dim dH As Double = LabelColorsHSB(i).Hue - targetHSB.Hue
Dim dS As Double = LabelColorsHSB(i).Saturation - targetHSB.Saturation
Dim dV As Double = LabelColorsHSB(i).Brightness - targetHSB.Brightness
Dim curDistance As Double = Math.Sqrt(weightHue * Math.Pow(dH, 2) + weightSaturation * Math.Pow(dS, 2) + weightValue * Math.Pow(dV, 2))
If (curDistance < minDistance) Then
minDistance = curDistance
minIndex = i + 1
End If
Next
Return minIndex
End Function
#End Region
#Region "绝对值容差,设置阈值得到匹配颜色"
''' <summary>
''' 得到相近的color
''' </summary>
''' <param name="pColor">所匹配颜色</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetCloseColor(ByVal pColor As Color,Byavl ColorList As List(of Color)) As Integer
Dim pColorDis As Integer = Const_ColorDistance
Dim Dif As Integer
Dim pACIcolor As Integer = Const_DefaultColorIndex
For i As Integer = 0 To ColorList.Count - 1
''绝对值容差法
Dif = Math.Abs(ColorList(i).R - pColor.R) + Math.Abs(ColorList(i).G - pColor.G) + Math.Abs(ColorList(i).B - pColor.B)
If Dif < pColorDis Then
pColorDis = Dif
pACIcolor = i + 1
End If
Next
Return pACIcolor
End Function
#End Region
#Region "平方容差选择最小值得到匹配颜色"
''' <summary>
''' 平方容差选择最小值得到匹配颜色
''' </summary>
''' <param name="pColor">所匹配颜色</param>
''' <returns></returns>
''' <remarks></remarks>
Private Function GetCloseColor(ByVal pDC As Color,Byavl ColorList As List(of Color)) As Integer
Dim pACIcolor As Integer = Const_DefaultColorIndex
Dim pDifs As New List(Of Long)
Dim pHash As New Hashtable
For i As Integer = 0 To ColorList.Count - 1
Dim tCompValue As Long
tCompValue = ColorValueComp(RGB(pDC.R, pDC.G, pDC.B), RGB(ColorList(i).R, ColorList(i).G, ColorList(i).B))
pDifs.Add(tCompValue)
If Not pHash.Contains(tCompValue) Then pHash.Add(tCompValue, i + 1)
Next
pDifs.Sort()
pACIcolor = pHash(pDifs(0))
Return pACIcolor
End Function
''' <summary>
''' 判断两个color在容差范围内是否相似
''' </summary>
''' <param name="pColorA">颜色A</param>
''' <param name="pColorB">颜色B</param>
''' <param name="pValve">容差</param>
''' <returns></returns>
''' <remarks></remarks>
Private Function ColorValueIsBorder(ByVal pColorA As Long, ByVal pColorB As Long, ByVal pValve As Long) As Boolean
'在容差pValve的范围内,比较两个颜色是否近似。
Dim tOutValue As Boolean
Dim tCompValue As Long
tCompValue = ColorValueComp(pColorA, pColorB)
If tCompValue <= pValve Then
tOutValue = True
Else
tOutValue = False
End If
Return tOutValue
End Function
''' <summary>
''' 通过Value值获得color
''' </summary>
''' <param name="pColorValue">Value值</param>
''' <returns></returns>
''' <remarks></remarks>
Private Function ColorGetByValue(ByVal pColorValue As Long) As Color
'从一个Long类型的颜色数据获得一个ColorRGB类型。
Dim tOutColor As Color = Color.FromArgb(255, pColorValue Mod 2 ^ 8, (pColorValue \ 2 ^ 8) Mod 2 ^ 8, (pColorValue \ 2 ^ 16) Mod 2 ^ 8)
Return tOutColor
End Function
''' <summary>
''' 获得两种long类型颜色的容差
''' </summary>
''' <param name="pColorA">颜色A</param>
''' <param name="pColorB">颜色B</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function ColorValueComp(ByVal pColorA As Long, ByVal pColorB As Long) As Long
'获得两个Long类型颜色的色差。
Dim tOutValue As Long
Dim tColorA As Color
Dim tColorB As Color
tColorA = ColorGetByValue(pColorA)
tColorB = ColorGetByValue(pColorB)
tOutValue = ColorRGBComp(tColorA, tColorB)
Return tOutValue
End Function
''' <summary>
''' 获得两种颜色之间的容差
''' </summary>
''' <param name="pColorA">颜色A</param>
''' <param name="pColorB">颜色B</param>
''' <returns></returns>
''' <remarks>平方容差法</remarks>
Public Function ColorRGBComp(ByRef pColorA As Color, ByRef pColorB As Color) As Long
'获得两个ColorRGB的色差。
Dim tOutValue As Long
Dim tAbsR As Long
Dim tAbsG As Long
Dim tAbsB As Long
tAbsR = Math.Abs(CLng(pColorA.R) - CLng(pColorB.R))
tAbsG = Math.Abs(CLng(pColorA.G) - CLng(pColorB.G))
tAbsB = Math.Abs(CLng(pColorA.B) - CLng(pColorB.B))
tOutValue = Math.Sqrt(tAbsR ^ 2 + tAbsG ^ 2 + tAbsB ^ 2)
Return tOutValue
End Function
#End Region
posted on 2008-06-04 13:39
王者之魂 阅读(789)
评论(6) 编辑 收藏