posts - 41,  comments - 23,  trackbacks - 1

本文实现了三种颜色匹配的方法,
一,先将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

Tag标签: 开发 Net Color
posted on 2008-06-04 13:39 王者之魂 阅读(789) 评论(6)  编辑 收藏

FeedBack:
2008-06-04 13:57 | i.Posei      
颜色匹配主要用来做什么呢?
  回复  引用  查看    
2008-06-04 15:37 | 簡簡單單..      
Mark
  回复  引用  查看    
2008-06-05 10:39 | 阿齐      
@i.Posei
我也有同问
  回复  引用  查看    
#4楼 [楼主]
2008-06-05 13:50 | 王者之魂      
比如现在你要将rgb颜色转换成256颜色,
rgb颜色比256颜色多很多种,某种rgb颜色不可能不可能和256颜色完全对应起来,这时就需要找到在256颜色中与rgb颜色最为接近的颜色
@阿齐

  回复  引用  查看    
2008-06-10 18:59 | Sangplus      
很直观的方法是均方根误差,很直观的应用是模式匹配。不过lz的方法好像距离实际应用差的还是有点远的。
  回复  引用  查看    
#6楼 [楼主]
2008-06-11 08:26 | 王者之魂      
谢谢!我的第三种方法就是均方根误差法。

均方根误差法有时候不准确,会有明显的失真,比如将rgb颜色转换为cad索引颜色时
而第一种方法就比均方根误差法准确很多@Sangplus

  回复  引用  查看    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接:
 

众 万
志 众
成 一
城 心

诚 心
祝 愿
中 震
国 区
人 百
民 姓
幸 安
福 康

QQ:13945133
MSN:yangguanjunmeteor@hotmail.com


<2008年6月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

与我联系

搜索

 

常用链接

留言簿(1)

我参与的团队

我的标签

随笔档案(41)

友情链接

最新评论

阅读排行榜

评论排行榜