个人觉得这个比较麻烦,下一个简单些
#include<opencv2\opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
class Historam1D//定义一个专门处理单通道的灰度图的类
{
private:
int histSize[1];//项的数量
float hranges[2];//像素的最小及最大值
const float*ranges[1];
int channels[1];//仅用到1个通道
public:
Historam1D()//1D直方图的参数
{
histSize[0] = 256;
hranges[0] = 0.0;
hranges[1] = 255.0;
ranges[0] = hranges;
channels[0] = 0;
}
cv::MatND getHistogram(const cv::Mat &image)
{
cv::MatND hist;
//计算直方图
cv::calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);
return hist;
}
cv::MatND getHistogramImg(const cv::Mat &image)
{
//计算直方图
cv::MatND hist=getHistogram(image);
//获取最大值与最小值
//cv::calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);
double maxVal = 0;
double minVal = 0;
cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0);
//显示直方图图像
cv::Mat histImg(histSize[0], histSize[0],CV_8U, Scalar(255));
//设置最高点为nbins的90%
int hpt = static_cast<int>(0.9*histSize[0]);
//每个条目都绘制一条垂直线
for (int h = 0; h < histSize[0]; h++)
{
float binVal = hist.at<float>(h);
int intensity = static_cast<int>(binVal*hpt / maxVal);
//两点之间绘制一条线
cv::line(histImg, Point(h, histSize[0]), Point(h, histSize[0] - intensity), Scalar::all(0));
}
return histImg;
}
};
int main()
{
Mat src = imread("group.jpg",0);
Historam1D h;
cv::MatND histo = h.getHistogram(src);
// for (int i = 0; i < 256; i++ )
// cout << "Vaule" << i << "=" << histo.at<float>(i) << endl;
namedWindow("Histogram");
imshow("Histogram", h.getHistogramImg(src));//显示直方图
imshow("src", src);
waitKey(0);
return 0;
}
这是没用到类的。
#include<opencv2\opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
Mat image = imread("group.jpg", 0);
if (!image.data){cout << "error" << endl;return 0;}
MatND hist; //MatND表示多维矩阵》3维
int dims = 1;
float hranges[] = { 0, 255 };
const float *ranges[] = { hranges }; // 这里需要为const类型
int size = 256;
int channels = 0;
// 计算图像的直方图
calcHist(&image, 1, &channels, Mat(), hist, dims, &size, ranges);
Mat imageShow(size , size, CV_8U, Scalar(255));//创建白色背景
// 获取最大值和最小值
double minVal = 0;
double maxVal = 0;
minMaxLoc(hist, &minVal, &maxVal, 0, 0); // minMaxLoc寻找矩阵中最小值和最大值的位置.
//显示直方图的图像
int hpt = static_cast<int>(0.9 * size);
for (int i = 0; i < 256; i++)
{
float value = hist.at<float>(i); // 注意hist中是float类型
int intensity = static_cast<int>(value * hpt / maxVal);//绘制的高度
//recentangle表示绘制矩形
rectangle(imageShow, Point(i, size - 1), Point((i + 1) - 1, size - intensity), Scalar(0));
}
namedWindow("showImage");
imshow("showImage", imageShow);
waitKey(0);
return 0;
}
二维直方图
#include<opencv2\opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
Mat image = imread("group.jpg", 1);
if (!image.data)
{
cout << "fail to load image" << endl;
return 0;
}
MatND hist; // 在cv中用CvHistogram *hist = cvCreateHist
int dims = 2;
float r_hranges[] = { 0, 255 };
float g_hranges[] = { 0, 255 };
const float *ranges[] = { r_hranges, g_hranges }; // 这里需要为const类型
int size[2] = { 256, 256 };
int channels[] = { 0, 1 }; //代表 r g通道 2代表b通道
// 计算图像的直方图
calcHist(&image, 1, channels, Mat(), hist, dims, size, ranges); // cv 中是cvCalcHist
int scale = 1;
Mat imageShow(size[0] * scale, size[1] * scale, CV_8UC3, Scalar(255));
// 获取最大值和最小值
double minVal = 0;
double maxVal = 0;
minMaxLoc(hist, &minVal, &maxVal, 0, 0);
//显示直方图的图像
//int hpt = saturate_cast<int>(0.9 * size[]);
for (int i = 0; i < 256; i++)
{
for (int j = 0; j < 256; j++)
{
float value = hist.at<float>(i, j); // 注意直方图的值是float类型
int realValue = saturate_cast<int>(value * size[0] / maxVal);
rectangle(imageShow, Point(i*scale, j*scale), Point(((i + 1)*scale - 1), (j + 1)*scale - 1), Scalar(realValue, realValue, realValue));
}
}
namedWindow("baboon");
namedWindow("showImage");
imshow("showImage", imageShow);
imshow("baboon", image);
waitKey(0);
return 0;
}