原图:
直方图均值
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