基于内容的相似图片检索

基于内容的相似图片检索(颜色)

基于内容的图像检索是计算机视觉的一个重要课题,它包括基于颜色、基于纹理、基于形状的图像检索,其中,今天我们讨论的是相对简单的基于颜色的图像检索。

       我们知道,直方图是标识图像内容的一种有效方式,因此这里关键是要做到,仅仅比较它们的直方图就能测量出两个图像的相似度。需要定义一个测量函数来评估两个直方图之间的差异程度或者相似程度。下面我们直奔话题。

实现原理

OpenCV中,已经提供了

cv:compareHist(cv::InputArray H1, cv::InputArray H2,intmethod)函数

三个参数分别的含义:

H1 H2是两张要比较的图片生成的颜色直方图,method是要比较的方法:参数也有好几个

CV_COMP_INTERSECT 逐个比较每个直方图中的数值,并保存最小的值,然后把这些最小值进行累加,作为相似度测量值,因此两个没有相同颜色的直方图得到交叉值为0,而两个完全相同的直方图得到的值就等于像素总数

CV_COMP_CHISQR   累加各箱子的归一化平方差;相同返回0

CV_COMP_BHATTACHARYYA 用在统计学,评估两个概率分布的相似度相同返回0

CV_COMP_CORREL 相关性方法范围为01,1为最好匹配,卡方法和Bhattacharyya距离法是值为0最好,而交集法为值越大越好。

构建颜色直方图,利用此函数比较两个直方图,根据返回来区分两张图片的差异度或者相似度。

准备工作

       1)减色:

       减色具体来说是减少图像中的颜色的数量。彩色图像由三通道像素组成,每个通道表示红、绿、蓝三种原色中一种颜色的亮度值,每个值都是8位的无符号字符类型,因此颜色总数为256*256*256,即超过1600万种颜色,因此,为了降低分析的复杂性,加快检索速度,有时需要减少图像中颜色的数量。一种方法是把RGB空间细分到大小相等的方块中,例如:如果把每种颜色数量减少到1/8,那么颜色总数就变为32*32*32。将旧图像中的每个颜色值划分到了一个方块,该方块的中间值就是新的颜色值;新图像使用新的颜色值,颜色数就减少了。实际上,基本的减色算法很简单,假设N是减色因子,将图像中每个像素的每个通道的值除以N(使用整数除法,不保留余数)。然后将结果乘以N,得到N的倍数,并且刚好不超过原始图像值。只需要加上N/2,就得到相邻的N倍数之间的中间值。对所有8位通道值重复这个过程,就会得到(256/N*256/N*256/N)中可能的颜色值。

       2)颜色转换:

       默认是以RGB三颜色通道读取图片,之所以选择RGB,是因为把它们组合起来后可以产生色域很宽的各种颜色。但是,利用RGB色彩空间计算颜色之间的差距,并不是衡量两个颜色相似度的最好方式,因为它并不是感知均匀的色彩空间,就是说,两种具有一定差距的颜色可能看起来非常接近,而另外两种具有同样差距的颜色看起来却差别很大,因此,这里使用的是HSV颜色模型,它是具有感知均匀特性的颜色模型,在此需要将图像转换为HSV颜色表示,就可以真正地使用图像像素与目标颜色之间的欧几里得距离来度量颜色之间的视觉相似度。

HSV颜色模型:
1.H
参数表示色彩信息,即所处的光谱颜色的位置。该参数用角度量来表示,红、绿、蓝分别相隔120度。互补色分别相差180度。
2.S
参数表示饱和度,该参数为一比例值,范围从01,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率。S=0时,只有灰度
3.V
参数表示色彩的明亮程度,范围从01。有一点要注意:它和光强度之间并没有直接的联系。


注意:在opencv里面:

在opencv中hsv 分别为 0-180 0-255 0-255



首先构建颜色直方图


//彩色图像的直方图
/*
   彩色图像一个三维的矩阵,如果选用含有256个箱子的直方图
   这个矩阵就有(256*256*256)个元素,大约1600万个项目,因此,最好在计算直方图时减少箱子的数量,
   也可以用稀疏矩阵(非零元素非常稀少的矩阵),而不会消耗过多的内存
   calcHist 函数有返回这种矩阵的版本SparseMat
*/
classColorHistogram{
private :
   int histSize[3];   //每个维度的大小
   float hranges[2];    //值的范围
   const float*ranges[3];//每个维度的范围
   int channels[3];      //需要处理的通道
public :
   ColorHistogram(){
      //默认参数
      //每个维度的大小和范围是相等的
      histSize[0]= histSize[1] = histSize[2] = 256;
      hranges[0]= 0.0;  //BGR范围
      hranges[1]= 256.0;
      ranges[0]= hranges;//所有的通道的范围都相等
      ranges[1]= hranges;
      ranges[2]= hranges;
      channels[0]= 0;//指定通道
      channels[1]= 1;
      channels[2]= 2;
   }
   voidsetSize(intSize){
      histSize[0]=histSize[1]=histSize[2]=Size;
   }
   Mat getHistogram(constMat&image){
      Mat hist;
 
      //BGR颜色直方图范围
      hranges[0]= 0.0;
      hranges[1]= 256.0;
      channels[0]= 0;
      channels[1]= 1;
      channels[2]= 2;
      calcHist(&image,//源图像
        1,        //单个图像的直方图
        channels,    //用到的通道  
        Mat(),       //不使用掩码
        hist,     //结果集
        3,        //返回三维直方图
        histSize,    //箱子数量
        ranges);  //像素值的范围
      returnhist;
   }
   SparseMat getSpareHistogram(constMat &image){
      SparseMat hist(3,  //维数
                 histSize,//每个维数的大小(即箱子数量)
                 CV_32F);
      //BGR颜色直方图
      hranges[0]= 0.0;
      hranges[1]= 256.0;
      channels[0]= 0;
      channels[1]= 1;
      channels[2]= 2;
 
      //计算直方图
      calcHist(&image,
        1,     //一个直方图
        channels, //要用到的通道
        Mat(),    //不使用掩码
        hist,  //结果集
        3,     //三维直方图
        histSize, //箱子数量
        ranges);//像素值的范围
      returnhist;
   }
};
 
其次这里采取的减色因子是64。
void divMat(constMat&image){
   //用查找表实现减色函数
   //创建一维查找表
   Mat lookup(1, 256,CV_8U);
   //定义减色查找表的值
   //定义减色因子
   intdiv = 64;
   for(int i = 0; i < 256; i++)
      lookup.at<uchar>(i) = i / div * div + div / 2;
   LUT(image,lookup,image);
}
直方图比较类:
classImageComparator{
private :
   Mat refH; //基准直方图
   Mat inputH;//输入图像的直方图
   ColorHistogram hist; //生成直方图
   intnBins;//每个颜色通道使用的箱子数量
public:
   ImageComparator():nBins(8){
   }
   //设置比较直方图时使用的箱子数量
   voidsetNumberOfBins(intbins){
      nBins = bins;
   }
   //计算基准图像的直方图
   voidsetReferenceImage(constMat&image){
      hist.setSize(nBins);
      refH =hist.getHistogram(image);
   }
   //最后,使用compareHist函数将基准图像和指定的输入图像进行对比,返回一个分数,表示是图像相似度
   //使用BGR直方图进行比较图像
   doublecompare(constMat&image){
      inputH =hist.getHistogram(image);
      returncompareHist(refH, inputH,CV_COMP_BHATTACHARYYA);
   }
};
然后:
//转换到HSV空间
   divMat(image);
   cvtColor(image,image,CV_RGB2HSV);
   ImageComparator C;
   //设置基准图片
   C.setReferenceImage(image);
// 进行比较
floatcmp= C.compare(img);
这些是我个人调试参数范围
      //CV_COMP_INTERSECT
      //if(C.compare(img)/piexl>0.57){
      //imshow(index, img2);  //8 
      //}
      //CV_COMP_CORREL
      //if(C.compare(img) > .7){
      //imshow(index, img2); //7
      //}
      //CV_COMP_BHATTACHARYYA
      if(cmp>-0.5 && cmp<0.5){
        imshow(files[i].c_str(),img2);//8
      }

最后我们来看看运行结果

 

原图:

结果:

 

原图:

结果:

本项目源码已经上传到CSDN

http://download.csdn.net/detail/wjb820728252/9726531

 

更高级的图像检索推荐:

http://www.cnki.net/kcms/detail/Detail.aspx?dbname=CDFD1214&filename=1014266131.nh&v=&filetitle=%E5%9F%BA%E4%BA%8E%E5%86%85%E5%AE%B9%E7%9A%84%E5%9B%BE%E5%83%8F%E6%A3%80%E7%B4%A2%E4%B8%AD%E7%89%B9%E5%BE%81%E8%A1%A8%E7%A4%BA%E4%B8%8E%E6%A3%80%E7%B4%A2%E7%AD%96%E7%95%A5%E7%A0%94%E7%A9%B6

 

http://www.cnki.net/kcms/detail/Detail.aspx?dbname=CDFD1214&filename=1013146422.nh&v=&filetitle=%E5%9F%BA%E4%BA%8E%E5%86%85%E5%AE%B9%E7%9A%84%E5%9B%BE%E5%83%8F%E6%A3%80%E7%B4%A2%E8%8B%A5%E5%B9%B2%E6%8A%80%E6%9C%AF%E7%A0%94%E7%A9%B6

 

http://www.cnki.net/kcms/detail/Detail.aspx?dbname=CMFD2008&filename=2008053312.nh&v=&filetitle=%E5%9F%BA%E4%BA%8E%E5%86%85%E5%AE%B9%E7%9A%84%E5%9B%BE%E5%83%8F%E6%A3%80%E7%B4%A2%E5%92%8CSift%E7%AE%97%E6%B3%95%E7%9A%84%E5%BA%94%E7%94%A8

希望能帮助到有需要的朋友,谢谢!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值