LIRE代码剖析3——常用的特征提取与匹配方法

来源:互联网 发布:河图专辑淘宝 编辑:程序博客网 时间:2024/05/21 21:41

既然图像检索的思想是将图像处理成长度有限的特征字符串,那常用的特征和匹配方法又有哪些呢?

常用的图像特征有颜色特征、纹理特征、形状特征、空间关系特征。由于一种特征总是存在无法克服的缺陷,或者检索太慢(如纹理检索),或者匹配效果差,目前很多检索技术都是有机综合多种特征,LIRE中实现的CEDD和FCTH方法,及其组合JCD法是目前检索速度快,查全率和查准率都很高的算法。后面将单独介绍。

一 颜色特征

(一)特点:颜色特征是一种全局特征,描述了图像或图像区域所对应的景物的表面性质。一般颜色特征是基于像素点的特征,此时所有属于图像或图像区域的像素都有各自的贡献。由于颜色对图像或图像区域的方向、大小等变化不敏感,所以颜色特征不能很好地捕捉图像中对象的局部特征。

(二)常用的特征提取与匹配方法

颜色直方图

其优点在于:它能简单描述一幅图像中颜色的全局分布,即不同色彩在整幅图像中所占的比例,特别适用于描述那些难以自动分割的图像和不需要考虑物体空间位置的图像。其缺点在于:它无法描述图像中颜色的局部分布及每种色彩所处的空间位置,即无法描述图像中的某一具体的对象或物体。

最常用的颜色空间:RGB颜色空间、HSV颜色空间。

颜色直方图特征匹配方法:直方图相交法、距离法、中心距法、参考颜色表法、累加颜色直方图法。

二 纹理特征

(一)特点:纹理特征也是一种全局特征,它也描述了图像或图像区域所对应景物的表面性质。但由于纹理只是一种物体表面的特性,并不能完全反映出物体的本质属性,所以仅仅利用纹理特征是无法获得高层次图像内容的。与颜色特征不同,纹理特征不是基于像素点的特征,它需要在包含多个像素点的区域中进行统计计算。在模式匹配中,这种区域性的特征具有较大的优越性,不会由于局部的偏差而无法匹配成功。作为一种统计特征,纹理特征常具有旋转不变性,并且对于噪声有较强的抵抗能力。但是,纹理特征也有其缺点,一个很明显的缺点是当图像的分辨率变化的时候,所计算出来的纹理可能会有较大偏差。另外,由于有可能受到光照、反射情况的影响,从2-D图像中反映出来的纹理不一定是3-D物体表面真实的纹理。

(二)常用的特征提取与匹配方法

纹理特征描述方法分类

(1)统计方法统计方法的典型代表是一种称为灰度共生矩阵的纹理特征分析方法Gotlieb 和 Kreyszig 等人在研究共生矩阵中各种统计特征基础上,通过实验,得出灰度共生矩阵的四个关键特征:能量、惯量、熵和相关性。统计方法中另一种典型方法,则是从图像的自相关函数(即图像的能量谱函数)提取纹理特征,即通过对图像的能量谱函数的计算,提取纹理的粗细度及方向性等特征参数

(2)几何法

所谓几何法,是建立在纹理基元(基本的纹理元素)理论基础上的一种纹理特征分析方法。纹理基元理论认为,复杂的纹理可以由若干简单的纹理基元以一定的有规律的形式重复排列构成。在几何法中,比较有影响的算法有两种:Voronio 棋盘格特征法和结构法。

(3)模型法

模型法以图像的构造模型为基础,采用模型的参数作为纹理特征。典型的方法是随机场模型法,如马尔可夫(Markov)随机场(MRF)模型法和 Gibbs 随机场模型法

(4)信号处理法

纹理特征的提取与匹配主要有:灰度共生矩阵、Tamura 纹理特征、自回归纹理模型、小波变换等。

灰度共生矩阵特征提取与匹配主要依赖于能量、惯量、熵和相关性四个参数。Tamura 纹理特征基于人类对纹理的视觉感知心理学研究,提出6种属性,即:粗糙度、对比度、方向度、线像度、规整度和粗略度。自回归纹理模型(simultaneous auto-regressive, SAR)是马尔可夫随机场(MRF)模型的一种应用实例。

三 形状特征

  (一)特点:各种基于形状特征的检索方法都可以比较有效地利用图像中感兴趣的目标来进行检索,但它们也有一些共同的问题,

(二)常用的特征提取与匹配方法

通常情况下,形状特征有两类表示方法,一类是轮廓特征,另一类是区域特征。图像的轮廓特征主要针对物体的外边界,而图像的区域特征则关系到整个形状区域。

几种典型的形状特征描述方法:

(1)边界特征法该方法通过对边界特征的描述来获取图像的形状参数。其中Hough 变换检测平行直线方法和边界方向直方图方法是经典方法。Hough 变换是利用图像全局特性而将边缘像素连接起来组成区域封闭边界的一种方法,其基本思想是点—线的对偶性;边界方向直方图法首先微分图像求得图像边缘,然后,做出关于边缘大小和方向的直方图,通常的方法是构造图像灰度梯度方向矩阵。

(2)傅里叶形状描述符法

傅里叶形状描述符(Fouriershape descriptors)基本思想是用物体边界的傅里叶变换作为形状描述,利用区域边界的封闭性和周期性,将二维问题转化为一维问题。

由边界点导出三种形状表达,分别是曲率函数、质心距离、复坐标函数。

(3)几何参数法

形状的表达和匹配采用更为简单的区域特征描述方法,例如采用有关形状定量测度(如矩、面积、周长等)的形状参数法(shape factor)。在 QBIC 系统中,便是利用圆度、偏心率、主轴方向和代数不变矩等几何参数,进行基于形状特征的图像检索。

(二)常用的特征提取与匹配方法

提取图像空间关系特征可以有两种方法:一种方法是首先对图像进行自动分割,划分出图像中所包含的对象或颜色区域,然后根据这些区域提取图像特征,并建立索引;另一种方法则简单地将图像均匀地划分为若干规则子块,然后对每个图像子块提取特征,并建立索引。

LIRE 中实现的方法

LIRE中实现的方法大度是符合MPEG标准的方法在类DocumentBuilderFactory中,可以查看其定义的方法。比较重要的有:ColorLayout、EdgeHistogram、ScalableColor、AutoColorCorrelogram、CEDD、FCTH、ColorHistogram、Tamura、Gabor、JointHistogram等。在LIRe中主要实现的图像特征有:

1.       RGB和HSV空间的颜色直方图;

2.       MPEG-7的颜色特征,包括Scalable color,Color layout和Color layout;

3.       Tamura纹理特征,包括粗糙度(Coarseness),对比度(Contrast)和方向度(Directionality);

4.       颜色和边缘的方向性描述符(Color and edge directivitydescriptor, CEDD);

5.       模糊颜色和纹理直方图(Fuzzy color and texturehistogram, FCTH);

6.       颜色关联图(Auto color correlation);

7.       尺度不变特征变换(Scale-invariant feature transform , SIFT)。


opencv得到图像的RGB颜色直方图

图像处理中,直方图是一个很强有力的工具. 其实直方图就是对颜色像素的统计,将统计值放到相应的bin中. 这里就涉及到bin的概念了,刚开始的时候对这个概念很疑惑.

bin的概念:颜色空间划分的区间即是直方图的bin. 举个例子,灰度图有256个值,如果把每个值划分一个单独的区间,则可以说直方图有256个bin,当然bin越大,颜色区分就越细,但是同时也增加了计算的复杂性.

下面的代码实现了图像RGB三个通道直方图的获取和显示.

    #include<opencv2\opencv.hpp>      #include<iostream>      using namespace std;      using namespace cv;            class HistogramND{      private:          Mat image;//源图像          int hisSize[1],hisWidth,hisHeight;//直方图的大小,宽度和高度          float range[2];//直方图取值范围          const float *ranges;          Mat channelsRGB[3];//分离的BGR通道          MatND outputRGB[3];//输出直方图分量      public:          HistogramND(){              hisSize[0] = 256;              hisWidth = 400;              hisHeight = 400;              range[0] = 0.0;              range[1] = 255.0;              ranges = &range[0];          }                //导入图片          bool importImage(String path){              image = imread(path);              if (!image.data)                  return false;              return true;          }                //分离通道          void splitChannels(){              split(image, channelsRGB);          }                //计算直方图          void getHistogram(){              calcHist(&channelsRGB[0],1,0,Mat(),outputRGB[0],1,hisSize,&ranges);              calcHist(&channelsRGB[1],1,0,Mat(),outputRGB[1], 1, hisSize, &ranges);              calcHist(&channelsRGB[2],1,0,Mat(),outputRGB[2], 1, hisSize, &ranges);                    //输出各个bin的值              for (int i = 0; i < hisSize[0]; ++i){                  cout << i << "   B:" << outputRGB[0].at<float>(i);                  cout <<"   G:" << outputRGB[1].at<float>(i);                  cout << "   R:" << outputRGB[2].at<float>(i) << endl;              }          }                //显示直方图          void displayHisttogram(){              Mat rgbHist[3];              for (int i = 0; i < 3; i++)              {                  rgbHist[i] = Mat(hisWidth, hisHeight, CV_8UC3, Scalar::all(0));              }              normalize(outputRGB[0], outputRGB[0], 0, hisWidth - 20, NORM_MINMAX);              normalize(outputRGB[1], outputRGB[1], 0, hisWidth - 20, NORM_MINMAX);              normalize(outputRGB[2], outputRGB[2], 0, hisWidth - 20, NORM_MINMAX);              for (int i = 0; i < hisSize[0]; i++)              {                  int val = saturate_cast<int>(outputRGB[0].at<float>(i));                  rectangle(rgbHist[0], Point(i * 2 + 10, rgbHist[0].rows), Point((i + 1) * 2 + 10, rgbHist[0].rows - val), Scalar(0, 0, 255), 1, 8);                  val = saturate_cast<int>(outputRGB[1].at<float>(i));                  rectangle(rgbHist[1], Point(i * 2 + 10, rgbHist[1].rows), Point((i + 1) * 2 + 10, rgbHist[1].rows - val), Scalar(0, 255, 0), 1, 8);                  val = saturate_cast<int>(outputRGB[2].at<float>(i));                  rectangle(rgbHist[2], Point(i * 2 + 10, rgbHist[2].rows), Point((i + 1) * 2 + 10, rgbHist[2].rows - val), Scalar(255, 0, 0), 1, 8);              }                    cv::imshow("R", rgbHist[0]);              imshow("G", rgbHist[1]);              imshow("B", rgbHist[2]);              imshow("image", image);          }      };                  int main(){          string path = "E:\\VS2013\\bran.jpg";          HistogramND hist;          if (!hist.importImage(path)){              cout << "Import Error!" << endl;              return -1;          }          hist.splitChannels();          hist.getHistogram();          hist.displayHisttogram();          waitKey(0);          return 0;      }  
结果截图:



0 0
原创粉丝点击