一种新的颜色相似度算法的具体实现(作者:郑斯彬,C#2005)

很久之前一直被两个像素点如何正确比对色彩相似度困扰,百度的方案都不太理想,直到自己动手把算法专研出来,实测效果还是非常理想的。

 int 最终差异值 = Math.Max(亮度差异, Math.Max(色调差异值, 色彩浓度差异));   //这句就是核心的思想,取三者最大值就OK了

根据算法,测试得到最终差异值【0-21】一般可以视为两个颜色相似,【21-42】有丁点相似,【42-64】基本不相似色。接近或大于85则是绝对的不相似色彩。例如(255,128.0)和(255,0.0)最终差异=42.5,纯黄色和纯红色最终差异=85,红色和青色最终差异=255(反色都是255)

 

相似的比较的方案一:测试黑色和纯红色返回255,纯红色和纯青色返回512,值越小越相似,经跟测试看起来也不错。

  private int 两点相似度(rgbClassRef a, rgbClassRef b) //传入两个像素点对象
        {//取值范围【0-512】
            int 亮度差异 = Math.Abs(a.X - b.X);//取得亮度差异
            int 色彩差异 = 0;
            if (a.SPname == b.SPname) 色彩差异 += Math.Abs(a.SP - b.SP) ; else 色彩差异 += (int)(a.SP + b.SP); //红绿蓝之间,同色分量相减,异色分量相加
            if (a.ZHname == b.ZHname) 色彩差异 += Math.Abs(a.ZH - b.ZH) ; else 色彩差异 += (int)(a.ZH + b.ZH);//青黄紫之间,同色分量相减,异色分量相加          
            return  (亮度差异 + 色彩差异);     //这里的色彩差异可以看作包含了色彩浓度和色调差异,返回全部的差异值
        }

-----------------------------------------------------------------------------------------------------------------------------------------------------

色调比较的方案://取值范围【0-255】,实测结果也是非常准确
  private int 色调距离_理论(rgbClassRef a, rgbClassRef b)
        {
            //从RGB空间制约关系,发现可以不用 Math.Abs,结果取值范围【0-255】,由于色调不区分明暗关系,所以作为相似度参考之一
            int Rsub = a.SXR - b.SXR; //计算R色调之间的空间距离【0-255】
            int Gsub = a.SXG - b.SXG;//计算G色调之间的空间距离【0-255】
            int Bsub = a.SXB - b.SXB;//计算B色调之间的空间距离【0-255】 

            //返回值0-24 挺相似的,24.5-42.5有半点相似,42.5-64色彩已切换,64到85几乎不相似了,85以上,绝对不相似了
            return   Math.Max(Rsub, Math.Max(Gsub, Bsub));      //【0-255】
        }
 

-----------------------------------------------------------------------------------------------------------------------------------------------------

//根据上面的研究成果,也可以灵活的调整相似度分数权重比较,权重值根据自己图片处理时实际需要调整


        private int 两点相似度(rgbClassRef a, rgbClassRef b)    //传入两个像素点对象
        {             
            int Rsub = Math.Abs(a.SXR - b.SXR); //计算和R色调的空间距离【0-255】
            int Gsub = Math.Abs(a.SXG - b.SXG);//计算和G色调的空间距离【0-255】
            int Bsub = Math.Abs(a.SXB - b.SXB);//计算和B色调的空间距离【0-255】
            int 色彩浓度差异 = Math.Abs(a.SN - b.SN) / 3;//因生活中浓度差异没有色调差异敏感,这里除权重取3,结果范围【0-85】 

int 色彩浓度最大值 = Math.Max(a.SN, b.SN); 

          int 色调差异值 = Math.Max(Rsub, Math.Max(Gsub, Bsub)); //【0-255】
            if (色彩浓度最大值 < 12)          //取色调权重=12,由于色彩浓度太小,色调不能辨识,如白色或黑色中掺杂的色彩
           { 
              色调差异值 = 色彩浓度最大值;  //或考虑 色调差异值 * 色彩浓度最大值 / 255;    //色调差异和色彩浓度成反比
            } 

            int 亮度差异 = Math.Abs(a.XLD - b.XLD)/3;  //亮度权重也取3;   //结果范围【0-85】

            int 最终差异值 = Math.Max(亮度差异, Math.Max(色调差异值, 色彩浓度差异));  //色调、色彩、浓度、取三者最大差异值,三者取值范围//【0-255】,最终取值范围//【0-255】
            return 最终差异值;
        }

 

 

  //解答部分疑问:

//色调距离的公式中,肯定有人又想问SXR那几个东西是怎么来的?看好了, _SN = R,G,B分量最大的那个去减最小的那个( 也就是*pX)。

//假设a.SPname=“红”,那么a.SP就是红色的比重值,取值范围【0-255】,SP可不是R分量,需要对R,G,B中的两个值做一次减法运算才能拿到

//计算色彩与红色的空间距离【0-255】
        public byte SXR
        {
            get
            {
                if (_SN > 0)//如果色彩浓度大于0
                     _SX = (byte)(85 * (_SN + g + b - *pX - r) / _SN);
                else
                    _SX = (byte)0;  //无色为0
                return _SX;
            }
            set
            {
                _SX = value;
            }
        }  //距离红色0~255


        public byte SXG {
            get {
                if (_SN > 0)
                      _SX = (byte)(85 * (_SN + r + b - *pX - g) / _SN); 
                else 
                    _SX = (byte)0; return _SX;
            } set { _SX = value; } }   //距离绿色0-255的色相范围  


        public byte SXB {
            get {
            if (_SN > 0) 
                  _SX = (byte)(85 * (_SN + r + g - *pX - b) / _SN);
            else
                _SX = (byte)0; return _SX;
            }
            set { _SX = value; } }   //距离蓝色0-255的色相范围 

        public byte SXQ { get { if (_SN > 0)  _SX = (byte)(255 - 85 * (_SN + g + b - *pX - r) / _SN); else _SX = (byte)0; return _SX; } set { _SX = value; } }   //距离青色0-255的与色相范围  

        public byte SXZ { get { if (_SN > 0)  _SX = (byte)(255 - 85 * (_SN + r + b - *pX - g) / _SN); else _SX = (byte)0; return _SX; } set { _SX = value; } }   //距离紫色0-255的色相范围  
        public byte SXH { get { if (_SN > 0)  _SX = (byte)(255 - 85 * (_SN + r + g - *pX - b) / _SN); else _SX = (byte)0; return _SX; } set { _SX = value; } }   //距离黄色0-255的色相范围

  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值