OpenCV之图像处理(二十六) 直方图比较

直方图比较方法-概述
    对输入的两张图像计算得到直方图H1与H2,归一化到相同的尺度空间,然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度进
        而比较图像本身的相似程度。Opencv提供的比较方法有四种:
            Correlation 相关性比较
                CV_COMP_CORREL   计算结果范围为 -1到1  -1很不相关,1完全一样     
            Chi-Square 卡方比较
                CV_COMP_CHISQR   计算结果越接近0,两个直方图越相似
            Intersection 十字交叉性
                CV_COMP_INTERSECT   计算公式为取两个直方图每个相同位置的值的最小值,然后求和,这个比较方式不是很好,不建议使用
            Bhattacharyya distance 巴氏距离
                CV_COMP_BHATTACHARYYA   比较结果是很准的,计算结果范围为 0-1 ,0表示两个直方图非常相关,1最不相似

图像深度是指存储每个像素(单通道或多通道)所用的位数。

灰度图:
    Gray Scale Image 或是Grey Scale Image,又称灰阶图。把白色与黑色之间按对数关系分为若干等级,称为灰度。灰度分为256阶。

    任何颜色都有红、绿、蓝三原色组成,假如原来某点的颜色为RGB(R,G,B),那么,我们可以通过下面几种方法,将其转换为灰度:
        1.浮点算法:Gray=R*0.3+G*0.59+B*0.11;
        2.整数方法:Gray=(R*30+G*59+B*11)/100;
        3.移位方法:Gray =(R*76+G*151+B*28)>>8;
        4.平均值法:Gray=(R+G+B)/3;
        5.仅取绿色:Gray=G;

HSV 颜色空间:   RGB 与 HSV 空间互相转换算法,参考百度百科
    HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。
    这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。

    颜色模型
        色调H
            用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°
        饱和度S
            饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,
            颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。
            通常取值范围为0%~100%,值越大,颜色越饱和。
        明度V
            明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)

    HSV模型的三维表示从RGB立方体演化而来。设想从RGB沿立方体对角线的白色顶点向黑色顶点观察,就可以看到立方体的六边形外形。
        六边形边界表示色彩,水平轴表示纯度,明度沿垂直轴测量。

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

计算比较步骤:
    首先把图像从RGB色彩空间转换到HSV色彩空间 cvtColor
    计算图像的直方图,然后归一化到[0~1]之间calcHist和normalize
    使用上述四种比较方法之一进行比较 compareHist

compareHist(
    InputArray h1, // 直方图数据,下同
    InputArray H2,
    int method// 比较方法,上述四种方法之一
)

代码

    #include "../common/common.hpp"

    static std::string convertToString(double d);

    void main(int argc, char** argv)
    {
        Mat base, test1, test2, hsvBase, hsvTest1, hsvTest2;
        base = imread(getCVImagesPath("images/lena.jpg"), IMREAD_COLOR);
        test1 = imread(getCVImagesPath("images/lena.png"), IMREAD_COLOR);
        test2 = imread(getCVImagesPath("images/lenanoise.png"), IMREAD_COLOR);

        cvtColor(base, hsvBase, CV_BGR2HSV);//转换为 HSV 颜色空间,也是3通道
        cvtColor(test1, hsvTest1, CV_BGR2HSV);
        cvtColor(test2, hsvTest2, CV_BGR2HSV);

        int h_bins = 50, s_bins = 60;
        int histBins[] = { h_bins, s_bins };
        // hue varies from 0 to 179, saturation from 0 rto 255
        float h_ranges[] = { 0, 180 };
        float s_ranges[] = { 0, 256 };
        const float * ranges[] = { h_ranges, s_ranges };
        // use the o-th and 1-st channels
        int channels[] = { 0, 1 };
        // ND 表示二维或多维的Mat ,typedef Mat MatND; 源码中MatND的声明。 Mat表示二维的数组
        MatND hist_base, hist_test1, hist_test2;

        calcHist(&hsvBase, 1, channels, Mat(), hist_base, 2, histBins, ranges, true, false);//计算多维的直方图
        normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat());//归一化到 0-1 之间

        calcHist(&hsvTest1, 1, channels, Mat(), hist_test1, 2, histBins, ranges, true, false);
        normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());

        calcHist(&hsvTest2, 1, channels, Mat(), hist_test2, 2, histBins, ranges, true, false);
        normalize(hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat());

        int compareType = CV_COMP_BHATTACHARYYA;//比较的算法 CV_COMP_CORREL CHISQR INTERSECT BHATTACHARYYA
        double basebase = compareHist(hist_base, hist_base, compareType);//base与base比较
        double basetest1 = compareHist(hist_base, hist_test1, compareType);//base与test1比较
        double basetest2 = compareHist(hist_base, hist_test2, compareType);//base与test2比较
        double tes1test2 = compareHist(hist_test1, hist_test2, compareType);//test1与test2比较
        printf("test1 compare with test2 correlation value :%f", tes1test2);

        Mat test12;
        test2.copyTo(test12);
        //将比较的结果转换为string,然后以文字的方式绘制到图形上
        putText(base, convertToString(basebase), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, 
            Scalar(0, 0, 255), 1, LINE_AA);
        putText(test1, convertToString(basetest1), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, 
            Scalar(0, 0, 255), 1, LINE_AA);
        putText(test2, convertToString(basetest2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, 
            Scalar(0, 0, 255), 1, LINE_AA);
        putText(test12, convertToString(tes1test2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, 
            Scalar(0, 0, 255), 1, LINE_AA);

        imshow("basebase", base);
        imshow("basetest1", test1);
        imshow("basetest2", test2);
        imshow("tes1test2", test12);

        waitKey(0);
    }

    std::string convertToString(double d)
    {
        ostringstream os;
        if (os << d) // << 运算符重载了,将double转成string
            return os.str();
        return "invalid conversion";
    }

效果图

这里写图片描述

猜你喜欢

转载自blog.csdn.net/huanghuangjin/article/details/81175339