opencv-compareHist直方图比较

对输入的两张图像进行直方图均衡化及直方图计算步骤后,可以对两个图像的直方图进行对比 

步骤

a.先用cvtColor()把图像从RGB色彩空间转换到HSV色彩空间;

b.计算图像的直方图,然后归一化到[0~1]之间,用到函数 calcHist() 和 normalize() ;

c.使用四种方法之一进行比较,用到函数compareHist()

 

实例

lm.jpg

 

 lm1.jpg

 

 lm2.jpg

 

 

#include<opencv2/opencv.hpp>
#include<iostream>


int main(int argc, char** argv) {

    cv::Mat src1 = cv::imread("D:/bb/tu/lm.jpg");
    cv::Mat src2 = cv::imread("D:/bb/tu/lm1.jpg");
    cv::Mat src3 = cv::imread("D:/bb/tu/lm2.jpg");
    if (!src1.data || !src2.data || !src3.data)
    {
        std::cout << "图片导入错误";
        return -1;
    }
    imshow("【src1原图】", src1);
    imshow("【src2原图】", src2);
    imshow("【src3原图】", src3);

    //从RGB色彩空间转化为HSV色彩空间,对 HS 两通道进行直方图统计
    cvtColor(src1, src1, cv::COLOR_BGR2HSV);
    cvtColor(src3, src3, cv::COLOR_BGR2HSV);
    cvtColor(src2, src2, cv::COLOR_BGR2HSV);

    //定义直方图计算所需要的各种参数
    int h_bins = 50;  //H通道分成50份
    int s_bins = 60;  //S通道分成60份
    int histSize[] = { h_bins,s_bins };
    float h_ranges[] = { 0,180 };  //H通道x轴取值范围0-180
    float s_ranges[] = { 0,256 };  //S通道x轴取值范围0-256
    const float* ranges[] = { h_ranges, s_ranges };

    int channels[] = { 0,1 };//对H和S两个通道进行直方图计算

    //MatND 是 Mat的别名,方便区分经过直方图计算处理后和输入图像
    cv::MatND hist_src1;
    cv::MatND hist_src2;
    cv::MatND hist_src3;

    //计算直方图并归一化处理
    calcHist(&src1, 3, channels, cv::Mat(), hist_src1, 2, histSize, ranges, true, false);
    /*
    参数2:由于图像是3通道的彩色图像,每个通道看做一个图像,所以是3
    参数5: 【 h_bins行,s_bins = 60列  】
    参数7:H通道的x轴被分成180分,S通道的x轴被分成255分
    参数8:H通道的x轴取值范围是r1,S通道的x轴取值范围是r2
    */
    normalize(hist_src1, hist_src1, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());

    calcHist(&src2, 3, channels, cv::Mat(), hist_src2, 2, histSize, ranges, true, false);
    normalize(hist_src2, hist_src2, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());

    calcHist(&src3, 3, channels, cv::Mat(), hist_src3, 2, histSize, ranges, true, false);
    normalize(hist_src3, hist_src3, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());

    
    double src1_src1 = cv::compareHist(hist_src1, hist_src1, cv::HISTCMP_CORREL);//直方图比较
    /*
    参数1:比较图像1
    参数2:比较图像2
    参数3:比较方法
            cv::HISTCMP_CORREL-->相关性比较(Correlation),取值为[0,1],越接近1,直方图相似度越高
            cv::HISTCMP_CHISQR-->卡方Chi-square,取值为[0,1],越接近0,直方图相似度越高
            cv::HISTCMP_INTERSECT-->相交Intersection,
            cv::HISTCMP_BHATTACHARYYA-->巴氏距离Bhattacharyya,在直方图相似度计算时,巴氏距离获得的
                    效果最好,但计算是最为复杂的。巴氏距离的计算结果,其值完全匹配为1,完全不匹配则为0

    */
    std::cout << "src1与src1相关性比较结果:" << src1_src1 << std::endl;  // 1

    double src1_src2 = cv::compareHist(hist_src1, hist_src2, cv::HISTCMP_CORREL);
    std::cout << "src1与src2相关性比较结果:" << src1_src2 << std::endl; //0.0287919

    double src1_src3 = cv::compareHist(hist_src1, hist_src3, cv::HISTCMP_CORREL);
    std::cout << "src1与src3相关性比较结果:" << src1_src3 << std::endl; //0.0287075

    

    cv::waitKey(0);
    return 0;
}

 

 

比较方法:

相关性比较(Correlation)

相关性比较公式如下:

 

 其中

 

 如果H1 = H2,即两个图的直方图一样,分子等于分母,值为1,所以在不严格的情况下,当值为1时,可以认为两个图是一样的。但是也有可能会出现两个图不一样,但是两个图的直方图是一样的情况。因为直方图计算的是像素点个数的分布情况,但是不会显示像素点的位置,所以有可能会出现两幅图片不一样,但是相同像素的个数完全一样,那他们的直方图也是一样的,不过这种情况不常有

 

 

 

posted @ 2022-01-16 08:49  天子骄龙  阅读(230)  评论(0编辑  收藏  举报