- 灰度直方圖
- 彩色直方圖
- C++: void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, SparseMat& hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )
-
- images – 是一個圖像數組,簡單起見,我們都只傳一個圖像.
- nimages – 圖片數組大小,我們固定爲1
- channels – 是一個數組,灰度圖像爲0就可以,彩色圖像要0,1,2
- mask – 這裏我們不需要,傳Mat()就可以
- hist – 輸出的直方圖
- dims – 計算彩色RGB要3,gray傳1
- histSize – 是一個數組,一般來說內容就是256
- ranges – 是一個二維數組,每個數組包括的都是一個範圍,[0,255]最常用,下面會看到
- uniform – 在這裏用默認就足夠.
- accumulate – 在這裏用默認就足夠.
float hranges[2]; // min and max pixel value
const float* ranges[1];
int channels[1]; // only 1 channel used here
histSize[0]= 256;
hranges[0]= 0.0;
hranges[1]= 255.0;
ranges[0]= hranges;
channels[0]= 0; // by default, we look at channel 0
// Computes the 1D histogram.
Mat hist;
// Compute histogram
calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);
class Histogram1D {
private:
int histSize[1]; // number of bins
float hranges[2]; // min and max pixel value
const float* ranges[1];
int channels[1]; // only 1 channel used here
public:
Histogram1D() {
histSize[0]= 256;
hranges[0]= 0.0;
hranges[1]= 255.0;
ranges[0]= hranges;
channels[0]= 0; // by default, we look at channel 0
}
// Computes the 1D histogram.
Mat getHistogram(const cv::Mat &image) {
Mat hist;
// Compute histogram
calcHist(&image,1,channels,Mat(),hist,1,histSize,ranges);
return hist;
}
Mat getHistogramImage(const cv::Mat &image){
// Compute histogram first
Mat hist= getHistogram(image);
// Get min and max bin values
double maxVal=0;
double minVal=0;
minMaxLoc(hist, &minVal, &maxVal, 0, 0);
// Image on which to display histogram
Mat histImg(histSize[0], histSize[0],CV_8U,Scalar(255));
// set highest point at 90% of nbins
int hpt = static_cast<int>(0.9*histSize[0]);
// Draw a vertical line for each bin
for( int h = 0; h < histSize[0]; h++ ) {
float binVal = hist.at<float>(h);
int intensity = static_cast<int>(binVal*hpt/maxVal);
// This function draws a line between 2 points
line(histImg,Point(h,histSize[0]),
Point(h,histSize[0]-intensity),
Scalar::all(0));
}
return histImg;
}
};
然後,主函數調用
Mat image,gray;
image = imread( argv[1], 1 );
if( !image.data )
return -1;
cvtColor(image, gray, CV_BGR2GRAY);
Histogram1D h;
namedWindow("Histogram");
imshow("Histogram",h.getHistogramImage(gray));
灰度直方圖已經畫好,下面畫彩色直方圖
/// Separate the image in 3 places ( B, G and R )
vector<Mat> bgr_planes;
split( src, bgr_planes );
現在,你就有了3個Mat存放在bgr_planes,再次強調下,OpenCV裏面彩色圖像的第一個通道是blue,BGR哦#include <cv.h>
#include <highgui.h>
using namespace cv;
int main( int argc, char** argv )
{
Mat src, hsv;
if( argc != 2 || !(src=imread(argv[1], 1)).data )
return -1;
cvtColor(src, hsv, CV_BGR2HSV);
// Quantize the hue to 30 levels
// and the saturation to 32 levels
int hbins = 30, sbins = 32;
int histSize[] = {hbins, sbins};
// hue varies from 0 to 179, see cvtColor
float hranges[] = { 0, 180 };
// saturation varies from 0 (black-gray-white) to
// 255 (pure spectrum color)
float sranges[] = { 0, 256 };
const float* ranges[] = { hranges, sranges };
MatND hist;
// we compute the histogram from the 0-th and 1-st channels
int channels[] = {0, 1};
calcHist( &hsv, 1, channels, Mat(), // do not use mask
hist, 2, histSize, ranges);
double maxVal=0;
minMaxLoc(hist, 0, &maxVal, 0, 0);
int scale = 10;
Mat histImg = Mat::zeros(sbins*scale, hbins*10, CV_8UC3);
for( int h = 0; h < hbins; h++ )
for( int s = 0; s < sbins; s++ )
{
float binVal = hist.at<float>(h, s);
int intensity = cvRound(binVal*255/maxVal);
rectangle( histImg, Point(h*scale, s*scale),
Point( (h+1)*scale - 1, (s+1)*scale - 1),
Scalar::all(intensity),
CV_FILLED );
}
namedWindow( "Source", 1 );
imshow( "Source", src );
namedWindow( "H-S Histogram", 1 );
imshow( "H-S Histogram", histImg );
waitKey();
}