灰度直方图:
C++: void calcHist(const Mat*images, intnimages, const int*channels, InputArraymask, OutputArrayhist, intdims, const int*histSize, const float**ranges, booluniform=true, boolaccumulate=false)¶
|
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src,gray;
src = imread("lena.png");
if (!src.data)
cout << "error:load image error!" << endl;
cvtColor(src, gray, CV_BGR2GRAY);
imshow("d", gray);
Mat hist;
int histSize = 256;
float histRange[] = { 0, 255 };
const float *range[] = { histRange };
calcHist(&gray, 1,0, Mat(), hist, 1, &histSize, range, true, false);
double max;
minMaxLoc(hist, 0, &max, 0, 0);
Mat hist_img (histSize, histSize, CV_8U, Scalar(255));
int hh = static_cast(0.9*histSize);
for (int i = 0; i < histSize; ++i)
{
float binVal = hist.at(i);
int intensity = static_cast(binVal*hh / max);
line(hist_img, Point(i, histSize), Point(i, histSize - intensity), Scalar::all(0));
}
imshow("dd", hist_img);
waitKey(0);
return 0;
}
计算彩色空间直方图:B,G,R
#include
using namespace cv;
int main()
{
Mat src;
src = imread("lena.png");
if (!src.data)
{
return -1;
}
vector bgr_plane;
split(src, bgr_plane);
//imshow("f", bgr_plane[2]);
int histSize = 256;
float histRange[] = { 0, 255 };
const float*ranges[] = { histRange };
Mat hist_b, hist_g, hist_r;
calcHist(&bgr_plane[0], 1, 0, Mat(), hist_b, 1, &histSize, ranges, true, false);
calcHist(&bgr_plane[1], 1, 0, Mat(), hist_g, 1, &histSize, ranges, true, false);
calcHist(&bgr_plane[2], 1, 0, Mat(), hist_r, 1, &histSize, ranges, true, false);
int hist_w = 600; int hist_h = 400;
int bin_w = cvRound((double)hist_w / histSize);
Mat hist_image(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));
normalize(hist_b, hist_b, 0, hist_image.rows, NORM_MINMAX, -1, Mat());
normalize(hist_g, hist_g, 0, hist_image.rows, NORM_MINMAX, -1, Mat());
normalize(hist_r, hist_r, 0, hist_image.rows, NORM_MINMAX, -1, Mat());
Mat img_bgr[3];
for (int i = 0; i < 3; i++)
{
img_bgr[i] = Mat(hist_h, hist_w, CV_8UC3, Scalar::all(0));
}
for (int i = 1; i < histSize; i++)
{
line(hist_image, Point(bin_w*(i - 1), hist_h -cvRound( hist_b.at(i - 1))), Point(bin_w*i, hist_h -cvRound( hist_b.at(i))), Scalar(255, 0, 0), 2, 8, 0);
line(hist_image, Point(bin_w*(i - 1), hist_h - cvRound(hist_g.at(i - 1))), Point(bin_w*i, hist_h - cvRound(hist_g.at(i))), Scalar(0, 255, 0), 2, 8, 0);
line(hist_image, Point(bin_w*(i - 1), hist_h - cvRound(hist_r.at(i - 1))), Point(bin_w*i, hist_h - cvRound(hist_r.at(i))), Scalar(0, 0, 255), 2, 8, 0);
}
for (int j = 0; j < histSize; j++)
{
int val = static_cast(hist_b.at(j));
rectangle(img_bgr[0], Point(j * 2 + 10, img_bgr[0].rows), Point((j + 1) * 2 + 10, img_bgr[0].rows - val),Scalar(255,0,0), 1, 8);
val = static_cast(hist_g.at(j));
rectangle(img_bgr[1], Point(j * 2 + 10, img_bgr[1].rows), Point((j + 1) * 2 + 10, img_bgr[1].rows - val),Scalar(0,255,0), 1, 8);
val = static_cast(hist_r.at(j));
rectangle(img_bgr[2], Point(j * 2 + 10, img_bgr[2].rows), Point((j + 1) * 2 + 10, img_bgr[2].rows - val),Scalar(0,0,255), 1, 8);
}
namedWindow("hist DEMO", CV_WINDOW_AUTOSIZE);
imshow("hist DEMO", hist_image);
imshow("B", img_bgr[0]);
imshow("G", img_bgr[1]);
imshow("R", img_bgr[2]);
waitKey(0);
return 0;
}
归一化normalize:
void normalize(InputArray src, OutputArray dst, double alpha=1, doublebeta=0, intnorm_type=NORM_L2, int dtype=-1, InputArraymask=noArray())
Parameter s: |
|
---|
channels参数:
参考:http://blog.csdn.net/ljbkiss/article/details/7420429
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函数计算时就按照这个顺序来统计直方图。
可以看出channels不为0时narrays可以和dims不相等,只要保证arrays中至少有channels指定的通道就可以。