# 有關opencv的學習（10）—彩色圖像的直方圖顯示

#ifndef ColorHistogramND_h
#define ColorHistogramND_h

#endif /* ColorHistogramND_h */

class ColorHistogramND {

private:

cv::Mat image;
int histSize[1],hisWidth,hisHeight;     //直方圖的大小及寬度、高度
float range[2];    //值範圍
const float *ranges;
cv::Mat channelsBGR[3];     //分離的BGR通道
cv::MatND outputBGR[3];     //輸出直方圖分量

public:

ColorHistogramND()
{
//準備用於彩色圖像的默認參數

histSize[0]=256;
//每個維度256個箱子
hisWidth=500;
hisHeight=500;
range[0]=0.0;//從0開始（含）
range[1]=255.0;//到256(不含)
ranges=&range[0];

}

//導入圖片
bool importImage(cv::String path){
if (!image.data)
return false;
return true;
}

//分離通道
void splitChannels()
{
split(image, channelsBGR);
};

//計算直方圖
void getColorHistogram()
{
calcHist(&channelsBGR[0], 1, 0, cv::Mat(), outputBGR[0], 1, histSize, &ranges);
calcHist(&channelsBGR[1], 1, 0, cv::Mat(), outputBGR[1], 1, histSize, &ranges);
calcHist(&channelsBGR[2], 1, 0, cv::Mat(), outputBGR[2], 1, histSize, &ranges);

for(int i=0;i<histSize[0];i++)
{
std::cout << i << "B:" << outputBGR[0].at<float>(i);
std::cout <<"G:" << outputBGR[1].at<float>(i);
std::cout << "R:" << outputBGR[2].at<float>(i) << std::endl;
}
}
//顯示直方圖
void displayColorHisttogram()
{
cv::Mat bgrHist[3];
for (int i = 0; i < 3; i++)
{
bgrHist[i] = cv::Mat(hisWidth, hisHeight, CV_8UC3, cv::Scalar::all(0));
}

normalize(outputBGR[0], outputBGR[0], 0, hisWidth - 20, cv::NORM_MINMAX);
normalize(outputBGR[1], outputBGR[1], 0, hisWidth - 20, cv::NORM_MINMAX);
normalize(outputBGR[2], outputBGR[2], 0, hisWidth - 20, cv::NORM_MINMAX);

for (int i = 0; i < histSize[0]; i++)
{
int val = cv::saturate_cast<int>(outputBGR[0].at<float>(i));
rectangle(bgrHist[0], cv::Point(i * 2 + 10, bgrHist[0].rows), cv::Point((i + 1) * 2 + 10, bgrHist[0].rows - val), cvScalar(255, 0, 0), 1, 8);

val = cv::saturate_cast<int>(outputBGR[1].at<float>(i));
rectangle(bgrHist[1], cv::Point(i * 2 + 10, bgrHist[1].rows), cv::Point((i + 1) * 2 + 10, bgrHist[1].rows - val), cvScalar(0, 255, 0), 1, 8);

val = cv::saturate_cast<int>(outputBGR[2].at<float>(i));
rectangle(bgrHist[2], cv::Point(i * 2 + 10, bgrHist[2].rows), cv::Point((i + 1) * 2 + 10, bgrHist[2].rows - val), cvScalar(0, 0, 255), 1, 8);

}

cv::imshow("B", bgrHist[0]);
imshow("G", bgrHist[1]);
imshow("R", bgrHist[2]);
imshow("image", image);

}

};

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include "ColorHistogramND.h"

using namespace cv;
using namespace std;

int main()
{
//if(image.empty())
//{
//return -1;
//}

string path="/Users/zhangxiaoyu/Desktop/lena.jpg";

ColorHistogramND hist;
if(!hist.importImage(path))
{
cout<<"Import error!!"<<endl;
return -1;
}
hist.splitChannels();
hist.getColorHistogram();
hist.displayColorHisttogram();

waitKey(0);
return 0;

}