C#图像颜色域判断以及颜色直方图识别方法




算法原理:

颜色特征的提取

由于该算法会将很多图片,尤其是人脸识别为海边风景,我们首先添加了一个限制条件。取典型的海颜色亮蓝色,其RGB值分别为0≤R≤100,100≤G≤255,150≤B≤255,当亮蓝色颜色区域超过图像区域3%的时候才进行下一步提取图像颜色直方图。否则就不是海边风景类型。

先提取输入图像的颜色特征,即统计图像中每种颜色的像素的数目。在本软件中,使用GetPixel()对图像按像素提取颜色信息。但是,对24位的RGB图像来说,其颜色空间(即不同的颜色数目)是224=256×256×256=16777216。在实际应用中, 若直接选用此值,数据量巨大, 特征提取缓慢, 同时也会使特征库非常庞大。为此, 可将颜色空间等距离分组(在该系统中分为16000种颜色值)取值,然后再统计每组中对应的像素数目,从而得到整个图像的颜色直方图, 这样, 图像的颜色直方图可以存在一个有16000个元素数组中。

2.1.2 图像相似度的度量

比较两幅图像是否相似,就是计算两幅图像的欧式距离。假设输入图像的直方图用G(g1,g2…… ,gN) 表示,数据库中的标准图像直方图用S(s1,s2,……sN) 表示,可以将这两个直方图看作欧氏空间的两个点,利用欧氏距离来描述它们的相似性,即:Ed(G,S)= ,其中N 为颜色级数,Ed(G,S)的值越接近0,则两幅图像越相似。如果两幅图像完全一致,则Ed(G,S)=0。在本系统中,则是两个分别代表输入图像和标准图像的颜色直方图的数组,按照上述公式计算距离d,当d<0.07时,认为输入图片与标准图片是相似的,可以把输入图片归类到标准图片的一类。

2.2 优缺点分析

l 算法简单易于理解,同时执行效率很高;

l 加入2.1.1的第一条限制条件后,对输入图片的判断成功率很高;

l 对于非蓝色为主的海景,如黄昏或者晚上的海景以及沙滩等不能成功识别,蓝色为主的图片也会导致误识别。

2.3 可做的改进与扩展

l 可以采用多张标准图片,扩展可识别图片的范围;

l 可用同样的颜色识别方法扩展做出森林、山水、雪山等风景图片,或者夜景、黄昏景色等类型图片的识别和检索,但是要加上相应的纹理判断和更多条件才能保证识别的准确性。

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Diagnostics;

namespace Readimage3
{
    public class ColorAnalysis//此类实现图像颜色直方图提取与匹配算法,方法为与标准图像的颜色直方图特征向量对比,通过计算两幅直方图之间的欧氏距离来描述它们之间的相似性,选出与标准图片相似的图片,主要用于海边风景的识别
    {

        //用于检索颜色相似的算法所声明的变量
        int i, j;
        string c11, c22;
        int r = 16000, n1, m11, m1, n2, m22, m2;
        Color c1 = new Color();
        Color c2 = new Color();
        public double ColorValue(Image p,Image pS1)//通过与标准图像颜色分布进行对比,并返回颜色分布相似值
        {
            //变量声明以及初始化
            double[,] s1 = new double[20000, 2];
            double[,] s2 = new double[20000, 2];
            double seaBlue=0;//海蓝色像素点数
            double percent;//海蓝色占图像比率
            double u = 0, d;
            string D = " ";
            u = 0;
            n1 = 0;
            m11 = 0;
            m1 = 0;
            n2 = 0;
            m22 = 0;
            m2 = 0;
           

            Form1 f=new Form1();

            //计算打开的图片像素分布
            if (p != null)
            {
                Bitmap p1 = new Bitmap(p);
                for (i = 0; i < p1.Width - 1; i++)
                {
                    for (j = 0; j < p1.Height - 1; j++)
                    {
                        c1 = p1.GetPixel(i, j); //获得图像每点的颜色基本属性
                        if (c1.R >= 0 && c1.R <= 100 && c1.G >= 100 && c1.G <= 255 && c1.B >= 150 && c1.B <= 255)//判断颜色是否为海蓝色区域
                            seaBlue++;
                        n1 = n1 + 1; //统计像素数
                        c11 = c1.Name; //返回RGB 值
                        m1 = Convert.ToInt32(Math.Pow(256, 3) / r); //每组颜色值的范围,这里设置组数为16000,可以扩大组数以提高精度,但会降低识别速度。
                        string str = c11;
                        //将十六进制装换成十进制
                        int val = (-1) * Int32.Parse(str, System.Globalization.NumberStyles.HexNumber);
                        m11 = Convert.ToInt32(Math.Floor(Convert.ToDouble(val / m1))); //提取颜色归属于哪一组
                        s1[m11, 0]++; //统计每组颜色的像素数

                    }
                }

                //用于对比的标准图片
                Bitmap p2 = new Bitmap(pS1);
                for (i = 0; i < p2.Width - 1; i++)
                {
                    for (j = 0; j < p2.Height - 1; j++)
                    {
                        c2 = p2.GetPixel(i, j); //获得图像每点的颜色基本属性
                        n2 = n2 + 1; //统计像素数
                        c22 = c2.Name; //返回RGB 值
                        m2 = Convert.ToInt32(Math.Pow(256, 3) / r); //每组颜色值的范围
                        string str = c22;
                        //将十六进制装换成十进制
                        int val = (-1) * Int32.Parse(str, System.Globalization.NumberStyles.HexNumber);
                        m22 = Convert.ToInt32(Math.Floor(Convert.ToDouble(val / m2))); //提取颜色归属于哪一组
                        s2[m22, 0]++; //统计每组颜色的像素数

                    }
                }


                for (i = 0; i < 16000; i++)
                {
                    u += (Convert.ToDouble((s1[i, 0] - s2[i, 0]) / n1)) * (Convert.ToDouble((s1[i, 0] - s2[i, 0]) / n1));
                }
                percent = seaBlue / n1;
              
                 if (percent > 0.03)//海蓝色比率大于0.03再进行d值的判断,否则直接跳过d值的计算
                  {
                      d = Math.Pow(u, 0.5);
                      D = String.Format("{0:F6}", d);
                      return d;
                  }
                  else
                      return d = 1;
            
              }
          
            else
                return d=1;
              
        }
    }
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值