OpenCV直方图操作综合

原图:

直方图均值

equalizeHist(gray_src,dst);

效果:

直方图计算,显示

#include <iostream>
#include <opencv.hpp>
using namespace cv;
using namespace std;

int main()
{
    const int histszie=256;
    float range[]={0,255};
    const float *ransize={range};
    Mat dst;
    Mat src=imread("E:/opencv/cv_1/luff.jpg");
    Mat gray_src;
    cvtColor(src,gray_src,CV_BGR2GRAY);

    equalizeHist(gray_src,dst);

    imshow("dst",dst);
    //imwrite("hist.jpg",dst);

    vector<Mat>gray_planes;
    Mat my_hist,oth_hist;

    Mat hist_image(512,400,CV_8UC3,Scalar(0,0,0));//初始化对象
    //计算直方图
    //传入的单通道图像,不需要split
    calcHist(&gray_src,1,0,Mat(),my_hist,1,&histszie,&ransize,true,false);
    calcHist(&dst,1,0,Mat(),oth_hist,1,&histszie,&ransize,true,false);
    int hist_h=400;
    //归一化
    normalize(my_hist,my_hist,0,hist_h,NORM_MINMAX,-1,Mat());
    normalize(oth_hist,oth_hist,0,hist_h,NORM_MINMAX,-1,Mat());
    for(int i=1;i<histszie;i++)
    {
        //绿色my_hist表示原图直接转为灰度后的直方图
        line(hist_image,Point((i-1)*2,hist_h-cvRound(my_hist.at<float>(i-1))),
             Point((i)*2,hist_h-cvRound(my_hist.at<float>(i))),Scalar(0,255,0),1,LINE_AA);
        //红色oth_hist表示原图灰度后,直方图均值后的直方图效果
        line(hist_image,Point((i-1)*2,hist_h-cvRound(oth_hist.at<float>(i-1))),
             Point((i)*2,hist_h-cvRound(oth_hist.at<float>(i))),Scalar(0,0,255),1,LINE_AA);
    }

    imwrite("hist_image.jpg",hist_image);
    imshow("Hist",hist_image);
    imshow("gray",gray_src);
    //imshow("dst",dst);
    waitKey(0);
    return 0;
}

效果:

直方图比较:

#include <iostream>
#include <opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
    Mat hsv_1,hsv_2;
    Mat src_1=imread("E:\\opencv\\cv_1\\luff.jpg");
    Mat src_2=imread("E:\\opencv\\cv_1\\luff2.jpg");
    //转为HSV
    cvtColor(src_1,hsv_1,CV_RGB2HSV);
    cvtColor(src_2,hsv_2,CV_RGB2HSV);

    int my_channels[]={0,1};
    //直方图计算
    Mat dst_1,dst_2;
    const int histsize[]={30,32};
    float Hrangs[]={0,180};
    float Srangs[]={0,256};
    const float *ransize[]={Hrangs,Srangs};
    calcHist(&hsv_1,1,my_channels,Mat(),dst_1,2,histsize,ransize,true,false);
    calcHist(&hsv_2,1,my_channels,Mat(),dst_2,2,histsize,ransize,true,false);
    //归一化
    normalize(dst_1,dst_1,0,1,NORM_MINMAX);
    normalize(dst_2,dst_2,0,1,NORM_MINMAX);
    //直方比较
    double result=compareHist(dst_1,dst_2,CV_COMP_CORREL);
    cout<<"相关性:"<<result<<endl;
    result=compareHist(dst_1,dst_2,CV_COMP_CHISQR);
    cout<<"卡方:"<<result<<endl;
    result=compareHist(dst_1,dst_2,CV_COMP_BHATTACHARYYA);
    cout<<"巴氏系数:"<<result<<endl;
    result=compareHist(dst_1,dst_2,CV_COMP_INTERSECT);
    cout<<"相交系数:"<<result<<endl;
    imshow("input",src_1);
    imshow("compare",src_2);


    waitKey(0);
    return 0;
}

对比图:

补充:

函数参数解释:直方图计算:calcHist             //注:转一位博主的注释

CV_EXPORTS void calcHist( const Mat* images, int nimages,
                          const int* channels, InputArray mask,
                          OutputArray hist, int dims, const int* histSize,
                          const float** ranges, bool uniform = true, bool accumulate = false );

images:输入图像                                              nimages:输入图像个数

channels:需要计算的直方图的通道                  mask: 掩膜,//不是太懂,直接Mat();

hist: 要承载输出直方图的容器                          dims:需要统计的通道数,这个与channels对应

histSize: 直方图的区间可以理解为x坐标上面的范围          ranges: 统计像素值的区间,同上,理解为y

uniform:默认=true,对直方图归一化                accumulate:在多个图像时,是否累计计算像素值得个数,默认false否

归一化函数:normalize

CV_EXPORTS_W void normalize( InputArray src, InputOutputArray dst, double alpha = 1, double beta = 0,
                             int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray());

alpha:归一化后的最小值

beta:归一化后的最大值

norm_type:归一化的模式,一般选择NORM_MINMAX;

归一化的原理也很简单,应该是:在原来未归一化的比例*归一化设置的最大值(也就是beta)

直方图比较compareHist:

CV_EXPORTS_W double compareHist( InputArray H1, InputArray H2, int method );

method有以下几种:

至于取值和什么时候最接近,最相似,网上查一下对应的计算公式,即可得到

1.相关系数的标准(method=CV_COMP_CORREL) 值越大,相关度越高,最大值为1,最小值为0
2 卡方系数的标准(method=CV_COMP_CHISQR) 值越小,相关度越高,最大值无上界,最小值0
3 相交系数的标准(method=CV_COMP_INTERSECT)值越大,相关度越高,最小值为0
4 巴氏系数的标准(method=CV_COMP_BHATTACHARYYA)值越小,相关度越高,最大值为1,最小值为0

RGB与HSV:

详情转:

https://blog.csdn.net/yangdashi888/article/details/53782481

我这里就简单讲一下注意点:

HSV:H->色相(hue),S->饱和度(saturation),V->明暗(value)

HSV更适合我们常规,网上有很多关于它的图像,呈圆锥状

H取值范围0~360度,S取值范围0~1,V取值范围0~255;

但不同的软件进行量化的取值范围是不同的,例如PS软件里的h取值为0-360、s取值为0-1、v取值为0-1.而opencv里cvSplit使用的图像是32F则其取值是h为0-360、s取值为0-1、v取值为0-255。如果是8UC则取值范围是h为0-180、s取值为0-255、v取值是0-255.  其中h色调对图像的分辨是很准的,这也就是为什么这样写:

    const int histsize[]={30,30};
    float Hrangs[]={0,180};
    float Srangs[]={0,256};
    const float *ransize[]={Hrangs,Srangs};
    calcHist(&hsv_1,1,my_channels,Mat(),dst_1,2,histsize,ransize,true,false);
    //H,S两个通道,取值分贝是0~180,0~256

猜你喜欢

转载自blog.csdn.net/shuiyihang0981/article/details/82960665