Title :
- OpenCV灰度直方圖
Theory :
從圖形上看,灰度直方圖是一個二維圖:
圖像的灰度直方圖是一個離散函數,它表示圖像每一灰度級與該灰度級出現頻率的對應關系。假設一幅圖像的像素總數為 N,灰度級總數為 L,其中灰度級為 g 的像素總數為 Ng,則這幅數字圖像的灰度直方圖橫坐標即為灰度 g ( 0 ≤ g ≤ L-1 ),縱坐標則為灰度值出現的次數 Ng。實際上,用 N 去除各個灰度值出現的次數 Ng 即可得到各個灰度級出現的概率 Pg = Ng / N = Ng / ∑Ng ,從而得到歸一化的灰度直方圖,其縱坐標為概率 Pg 。
Quote : ( From [OpenCV 2 Computer Vision Application Programming Cookbook (Robert Langaniere, 2011) ], 引用作直方圖的解釋 )
- A histogram is a simple table that gives the number of pixels that have a given value in an image (or sometime a set of images). The histogram of a gray-level image will therefore have 256 entries (or bins).
- Histograms can also be normalized such that sum of the bins equals 1. In that case, each bin gives the percentage of pixels having this specific value in the image.
Implementation :
利用 OpenCV 提供的 calcHist 函數 :
void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false );
這個函數用於計算直方圖是很強大的,在這里就實現一個最簡單的灰度圖像的直方圖計算。
Code :
1: int main()2: {
3: Mat img = imread("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);4:
5: Mat* arrays = &img;
6: int narrays = 1;7: int channels[] = { 0 };8: InputArray mask = noArray();
9: Mat hist;
10: int dims = 1;11: int histSize[] = { 256 };12: float hranges[] = { 0.0, 255.0 };13: const float *ranges[] = { hranges };14: //調用 calcHist 計算直方圖, 結果存放在 hist 中15: calcHist(arrays, narrays, channels, mask, hist, dims, histSize, ranges);
16:
17: //調用一個我自己寫的簡單的函數用於獲取一張顯示直方圖數據的圖片,18: //輸入參數為直方圖數據 hist 和期望得到的圖片的尺寸19: Mat histImg = ggicci::getHistogram1DImage(hist, Size(600, 420));
20: imshow("lena gray image histogram", histImg);21: waitKey();
22: }
23:
24: Mat ggicci::getHistogram1DImage(const Mat& hist, Size imgSize)25: {
26: Mat histImg(imgSize, CV_8UC3);
27: int Padding = 10;28: int W = imgSize.width - 2 * Padding;29: int H = imgSize.height - 2 * Padding;30: double _max;31: minMaxLoc(hist, NULL, &_max);
32: double Per = (double)H / _max;33: const Point Orig(Padding, imgSize.height-Padding);34: int bin = W / (hist.rows + 2);35:
36: //畫方柱37: for (int i = 1; i <= hist.rows; i++)38: {
39: Point pBottom(Orig.x + i * bin, Orig.y);
40: Point pTop(pBottom.x, pBottom.y - Per * hist.at<float>(i-1));41: line(histImg, pBottom, pTop, Scalar(255, 0, 0), bin);
42: }
43:
44: //畫 3 條紅線標明區域45: line(histImg, Point(Orig.x + bin, Orig.y - H), Point(Orig.x + hist.rows * bin, Orig.y - H), Scalar(0, 0, 255), 1);
46: line(histImg, Point(Orig.x + bin, Orig.y), Point(Orig.x + bin, Orig.y - H), Scalar(0, 0, 255), 1);
47: line(histImg, Point(Orig.x + hist.rows * bin, Orig.y), Point(Orig.x + hist.rows * bin, Orig.y - H), Scalar(0, 0, 255), 1);
48: drawArrow(histImg, Orig, Orig+Point(W, 0), 10, 30, Scalar::all(0), 2);
49: drawArrow(histImg, Orig, Orig-Point(0, H), 10, 30, Scalar::all(0), 2);
50:
51: return histImg;52: }
Result :
End :
Author : Ggicci
歡迎閱讀, 如有錯誤, 希望指正!
--OpenCV 初學者