opencv+颜色直方图+相似图像比对

这个是之前学习openCV时做过的,时间长了怕找不到,还是写下来的好。

首先,图像直方图是什么?图像直方图是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。

直方图的意义:

1、直方图是图像中像素强度分布的图形表达方式。

2、它统计了每一个强度值所具有的像素个数。

openCV中封装了计算直方图的函数calcHist(),调用这个函数可以很方便的计算图像的颜色直方图。不过有一点需要注意,图像要转成HSV 格式,之后要定义bin的数目,也就是分成几个格子然后分别统计落在这些格子中的像素数。还有一些问题就直接结合代码说了。

另外,用于计算直方图相似度的函数是compareHist(),这个是CV的一个内建函数,可以直接调用。这个函数有4种距离标准可以选择。

参数:

       0--相关系数,取值[-1,1],值越大相关性越好,说明越相似。

       a= \sum_{I}^{N}(H_{1}(I)-\bar{H_{1}}})(H_{2}(I)-\bar{H_{2}}}) 公式(1)

       b= \sqrt{\sum_{I}^{N}(H_{1}(I)-\bar{H_{1}}})^{2}\sum_{I}^{N}(H_{2}(I)-\bar{H_{2}}})^{2}}

       d(H_{1},H_{2})=\frac{a}{b}

       1--卡方,值越小越相似。

       2--直方图相交,越是相似的图,这个值越大

       3--Bhattacharyya距离,越小越好。

公式不好敲,大家有兴趣的可以百度看一下。。。。。。。。。。

//标准格式,没有什么可说的。
#include
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;

int main()
{
    
    //申请用于存储图像数据的Mat容器,src表示原始图像,hsv表示转换成hsv格式的图像
    
    Mat srcImage_base,hsvImage_base;
    Mat srcImage_test1,hsvImage_test1;
    Mat srcImage_test2,hsvImage_test2;
    Mat hsvImage_halfDown;
    //我用的图,一张基准图,两张相似的测试图
    srcImage_base=imread("n01443537_84.JPEG");
    srcImage_test1=imread("n01443537_129.JPEG");
    srcImage_test2=imread("n01443537_130.JPEG");
    imshow("base",srcImage_base);
    imshow("test1",srcImage_test1);
    imshow("test2",srcImage_test2);
    //转换图像格式
    cvtColor(srcImage_base,hsvImage_base,COLOR_BGR2HSV);
    cvtColor(srcImage_test1,hsvImage_test1,COLOR_BGR2HSV);
    cvtColor(srcImage_test2,hsvImage_test2,COLOR_BGR2HSV);
//截取原始图像的半身图用于对比测试
    hsvImage_halfDown=hsvImage_base(Range(hsvImage_base.rows/2,hsvImage_base.rows-1),Range(0,hsvImage_base.cols-1));
//h,s对应的bin的数目分别是50,60,即是把h范围是(0,255)的数分成50份分别统计每一份中的像素数。
    int h_bins=50;int s_bins=60;
    int histSize[]={h_bins,s_bins};
    float h_ranges[]={0,256};
    float s_ranges[]={0,180};
    const float* ranges[]={h_ranges,s_ranges};
//只计算了h,s两个通道,所以channels是0和1
    int channels[]={0,1};
//MatND 类型的容器用于存储calcHist计算出的直方图
    MatND baseHist;
    MatND halfDownHist;
    MatND testHist1;
    MatND testHist2;
    calcHist(&hsvImage_base,1,channels,Mat(),baseHist,2,histSize,ranges,true,false);
    normalize(baseHist,baseHist,0,1,NORM_MINMAX,-1,Mat());
    calcHist(&hsvImage_halfDown,1,channels,Mat(),halfDownHist,2,histSize,ranges,true,false);
    normalize(halfDownHist,halfDownHist,0,1,NORM_MINMAX,-1,Mat());
    calcHist(&hsvImage_test1,1,channels,Mat(),testHist1,2,histSize,ranges,true,false);
    normalize(testHist1,testHist1,0,1,NORM_MINMAX,-1,Mat());
    calcHist(&hsvImage_test2,1,channels,Mat(),testHist2,2,histSize,ranges,true,false);
    normalize(testHist2,testHist2,0,1,NORM_MINMAX,-1,Mat());
//分别用上述4种基准计算直方图之间的相似度
//基准图和基准图,基准图和半身基准图,基准图和测试图1,基准图和测试图2
    for(int i=0;i<4;i++)
    {
        int compare_method=i;
        double base_base=compareHist(baseHist,baseHist,compare_method);
        double base_half=compareHist(baseHist,halfDownHist,compare_method);
        double base_test1=compareHist(baseHist,testHist1,compare_method);
        double base_test2=compareHist(baseHist,testHist2,compare_method);

        printf("method[%d]result: \n\n base-base: %f, base-halfbase: %f, base-test1: %f, base-test2: %f \n----------------------------\n",i,base_base,base_half,base_test1,base_test2);
    }
    printf("All done");
    waitKey(0);
    return 0;
}

输出的结果如下:

opencv+颜色直方图+相似图像比对_第1张图片

 

从结果分析,直方图只能做相同图像相同事物的比较,在做相似性图像的比较时效果较差,很难直接用于工业上的图像的相似性检索等工作。

你可能感兴趣的:(opencv+颜色直方图+相似图像比对)