個人覺得這個比較麻煩,下一個簡單些
#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;
}