【opencv学习之二十八】直方图补充及直方图匹配

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/abcvincent/article/details/79223377

之前有写过直方图,这里补充一些实验代码和总结,另外补充直方图匹配的代码;

分通道计算和绘制直方图:

void imgHistogram()//直方图-一维灰度直方图
{
    ///一维灰度直方图
    //1.计算直方图
    Mat srcImg = imread("D:/2.jpg");
    //    Mat srcImg = imread("D:/ImageTest/pic3.png");
    int channels=0;//需要统计通道的索引
    Mat mask = Mat();
    Mat histImg;//存放输出的直方图
    int dims = 1;//需要计算的直方图的维度
    int histSize = 256;//计算的直方图的分组数
    float range[] = { 0, 256 };//表示直方图每一维度的取值范围[0,256)
    const float* ranges[] = { range };//参数形式需要,表示每一维度数值的取值范围
    //计算直方图
    calcHist(&srcImg,        //输入的图像的指针,可以是多幅图像,所有的图像必须有同样的深度
             1,                      //输入的图像的个数
             &channels,        //图像channels的数组,Mat存储顺序是:BGR
             mask,               //掩码。
             histImg,            //计算出来的直方图
             dims,                //计算出来的直方图的维数。
             &histSize,        //在每一维上直方图的个数
             ranges);          //用来进行统计的范围
    
    //    原函数:void calcHist( InputArrayOfArrays images,
    //                                const std::vector<int>& channels,
    //                                InputArray mask, OutputArray hist,
    //                                const std::vector<int>& histSize,
    //                                const std::vector<float>& ranges,
    //                                bool accumulate = false );
    //    calcHist函数的channels参数和narrays以及dims共同来确定用于计算直方图的图像;
    //    首先dims是最终的直方图维数,narrays指出了arrays数组中图像的个数,
    //    其中每一幅图像都可以是任意通道的【只要最终dims不超过32即可】
    //    如果channels参数为0,则narrays和dims必须相等,否则弹出assert,
    //    此时计算直方图的时候取数组中每幅图像的第0通道。
    //    当channels不是0的时候,用于计算直方图的图像是arrays中由channels指定的通道的图像,
    //    channels与arrays中的图像的对应关系,如channels的参数说明的,
    //    将arrays中的图像从第0幅开始按照通道摊开排列起来,
    //    然后channels中的指定的用于计算直方图的就是这些摊开的通道;
    //    假设有arrays中只有一幅三通道的图像image,那么narrays应该为1,
    //    如果是想计算3维直方图【最大也只能是3维的】,想将image的通道2作为第一维,
    //    通道0作为第二维,通道1作为第三维,则可以将channels设置为channesl={2,0,1};
    //    这样calcHist函数计算时就按照这个顺序来统计直方图。
    
    //2.绘制直方图
    double minValue = 0;
    double maxValue = 0;
    minMaxLoc(histImg,&minValue,&maxValue);//得到计算出的直方图中的最小值和最大值
    int width = histSize*2;//定义绘制直方图的宽度,令其等于histSize
    int height = 256*2;//定义绘制直方图的高度
    Mat dstImg = Mat::zeros(Size(width,height),CV_8UC3);//宽为histSize,高为height
    for (int i = 0; i < histSize;i++)//遍历histImg
    {
        float binValue = histImg.at<float>(i);//得到histImg中每一分组的值
        //        cout <<"i: "<<i<<" ,binValue: "<<binValue<< endl;
        float realValue = (binValue / maxValue)*height;//归一化数据,缩放到图像的height之内
        //        cout << "i: " << i << " ,realValue: " << realValue << endl;
        //用直线方法绘制直方图,注意两端点坐标的计算
        line(dstImg, Point(i*2, height - 1), Point(i*2, height - 1 - realValue), Scalar(255,0,0), 1);//统计的是第一通道蓝色
    }
    imshow("srcImg",srcImg);
    imshow("Histogram", dstImg);
    waitKey(0);
}
效果:



分将bgr像素分开统计:

void imgHistogram3()//直方图-直方图
{
    //    Mat srcImg = imread("D:/2.jpg");
    Mat srcImg = imread("D:/ImageTest/pic3.png");
    /// 分割成3个单通道图像 (B, G 和 R )
    vector<Mat> bgr_planes;
    split(srcImg, bgr_planes );
    /// 设定bin数目
    int histSize = 256;
    /// 设定取值范围 ( B,G,R) )
    float range[] = { 0, 255 } ;
    const float* histRange = { range };
    bool uniform = true;
    bool accumulate = false;
    Mat b_hist, g_hist, r_hist;
    /// 计算直方图:
    calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
    calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
    calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
    // 创建直方图画布
    int hist_h =256;
    int hist_w = histSize*3;
    //    int bin_w = cvRound( (double) hist_w/histSize );
    Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );
    /// 将直方图归一化到范围 [ 0, histImage.rows ]
    normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    /// 在直方图画布上画出直方图
    for( int i = 1; i < histSize; i++ )
    {
        line( histImage, Point( i,hist_h-1) ,Point( i, hist_h-cvRound(b_hist.at<float>(i)) ), Scalar( 255, 0, 0),1 );
        line( histImage, Point( histSize+i,hist_h-1) ,Point(histSize+i, hist_h-cvRound(g_hist.at<float>(i)) ), Scalar( 0, 255, 0),1 );
        line( histImage, Point( histSize*2+i,hist_h-1) ,Point(  histSize*2+i, hist_h-cvRound(r_hist.at<float>(i)) ), Scalar( 0, 0, 255),1 );
    }
    /// 显示直方图
    imshow("RGB Histogram", histImage );//窗口中显示直方图
    imshow("original image", srcImg );//窗口中显示原图
    waitKey(0);
}
效果:


直方图匹配:

void HistogramCompare()//直方图匹配
{
//    Mat srcImg = imread("D:/ImageTest/mubiao.jpg");
//    Mat srcImg2 = imread("D:/ImageTest/mubiao1.jpg");
    Mat srcImg = imread("D:/ImageTest/2.jpg");
    Mat srcImg2 = imread("D:/ImageTest/lena.png");
    imshow("original image1", srcImg );//窗口中显示原图
    imshow("original image2", srcImg2 );//窗口中显示原图
    cvtColor(srcImg,srcImg, CV_BGR2GRAY);
    cvtColor(srcImg2,srcImg2, CV_BGR2GRAY);
    int histSize = 256;
    /// 设定取值范围 ( B,G,R) )
    float range[] = { 0, 255 } ;
    const float* histRange = { range };
    bool uniform = true;
    bool accumulate = false;
    Mat hist1, hist2;
    /// 计算直方图:
    calcHist( &srcImg, 1, 0, Mat(), hist1, 1, &histSize, &histRange, uniform, accumulate );
    calcHist( &srcImg2, 1, 0, Mat(), hist2, 1, &histSize, &histRange, uniform, accumulate );

    //直方图对比,注意是依据两源图像所计算出的直方图进行相似度对比.
    double num1 = compareHist(hist1, hist2, CV_COMP_CORREL);//相关性方法(值越大匹配度越高)
    double num2 = compareHist(hist1, hist2, CV_COMP_CHISQR);//卡方测量法(值越小匹配度越高)
    double num3 = compareHist(hist1, hist2, CV_COMP_INTERSECT);//直方图相交法(值越大匹配度越高)
    double num4 = compareHist(hist1, hist2, CV_COMP_BHATTACHARYYA);//Bhattacharyya测量法(小)
    cout << "CV_COMP_CORREL(max_best): " << num1 << endl;
    cout << "CV_COMP_CHISQR(min_best): " << num2 << endl;
    cout << "CV_COMP_INTERSECT(max_best): " << num3 << endl;
    cout << "CV_COMP_BHATTACHARYYA(min_best): " << num4 << endl;

    // 创建直方图画布
    int hist_h =256*2;
    int hist_w = histSize*2*2;
    Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );
    /// 将直方图归一化到范围 [ 0, histImage.rows ]
    normalize(hist1, hist1, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(hist2, hist2, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    /// 在直方图画布上画出直方图
    for( int i = 1; i < histSize; i++ )
    {
        line( histImage, Point( i*2,hist_h-1) ,Point( i*2, hist_h-cvRound(hist1.at<float>(i)) ), Scalar( 255, 255, 0),1 );
        line( histImage, Point( histSize*2+i*2,hist_h-1) ,Point(histSize*2+i*2, hist_h-cvRound(hist2.at<float>(i)) ), Scalar( 0, 255, 255),1 );
    }

    //    //添加文字
    QString strg1=QString::number(num1,10,3);
    QString str1=QString("CV_COMP_CORREL(max_best):%1").arg(strg1);
    QByteArray cStr1 = str1.toLocal8Bit(); // 注意,这个QByteArray 对象一定要建立
    char *p1 = cStr1.data();
    putText(histImage,p1, Point(30, 30),CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(0, 0, 255), 1, 8);

    QString strg2=QString::number(num2,10,3);
    QString str2=QString("CV_COMP_CHISQR(min_best):%1").arg(strg2);
    QByteArray cStr2 = str2.toLocal8Bit(); // 注意,这个QByteArray 对象一定要建立
    char *p2 = cStr2.data();
    putText(histImage,p2, Point(30, 30*2),CV_FONT_HERSHEY_COMPLEX,0.8, Scalar(0, 0, 255), 1, 8);

    QString strg3=QString::number(num3,10,3);
    QString str3=QString("CV_COMP_INTERSECT(max_best):%1").arg(strg3);
    QByteArray cStr3 = str3.toLocal8Bit(); // 注意,这个QByteArray 对象一定要建立
    char *p3 = cStr3.data();
    putText(histImage,p3, Point(30, 30*3),CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(0, 0, 255), 1, 8);

    QString strg4=QString::number(num4,10,3);
    QString str4=QString("CV_COMP_BHATTACHARYYA(min_best):%1").arg(strg4);
    QByteArray cStr4 = str4.toLocal8Bit(); // 注意,这个QByteArray 对象一定要建立
    char *p4 = cStr4.data();
    putText(histImage,p4, Point(30, 30*4),CV_FONT_HERSHEY_COMPLEX, 0.8, Scalar(0, 0, 255), 1, 8);

    /// 显示直方图
    imshow("RGB Histogram", histImage );//窗口中显示直方图
    waitKey(0);
}
相似图像组效果:



非相似图匹配效果:





猜你喜欢

转载自blog.csdn.net/abcvincent/article/details/79223377