演示代码:
#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespace cv; using namespace std; int main(int argc, char** argv) { Mat src, dst; src = imread("e:/girl.png"); //分通道显示 vector<Mat> bgrAry; split(src, bgrAry); imshow("b", bgrAry[0]); imshow("g", bgrAry[1]); imshow("r", bgrAry[2]); int histSize = 256; float range[] = { 0,256 }; const float* histRanges = { range }; Mat bHist, gHist, rHist; calcHist(&bgrAry[0], 1, 0, Mat(), bHist, 1, &histSize, &histRanges, true, false); calcHist(&bgrAry[1], 1, 0, Mat(), gHist, 1, &histSize, &histRanges, true, false); calcHist(&bgrAry[2], 1, 0, Mat(), rHist, 1, &histSize, &histRanges, true, false); //归一化 int h = 400; int w = 512; int binWidth = w / histSize; Mat histImg(w, h, CV_8UC3, Scalar(0, 0, 0)); normalize(bHist, bHist, 0, h, NORM_MINMAX, -1, Mat()); normalize(gHist, rHist, 0, h, NORM_MINMAX, -1, Mat()); normalize(rHist, rHist, 0, h, NORM_MINMAX, -1, Mat()); //这里啥都看不见 imshow("bhist", bHist); imshow("ghist", gHist); imshow("rhist", rHist); /* 归一化后的bHist其实是一个只有256个元素的数组,并不是原图的像素数组,所以你什么都看不到。 bhist的数据显示出来是下面这样的。 bhist= [1 x 256] [3.7676611; 2.9304032; 2.3024592; 1.4652015; 2.0931449; 6.9073782; 3.5583467; 6.6980639; 6.6980639; 6.9073782; 10.884354; 9.0005236; 10.675039; 12.349555; 15.279958; 15.907901; 22.605965; 18.001045; 21.140762; 20.512819; 22.815279; 24.071167; 25.745682; 25.327053; 26.373625; 38.095238; 34.955521; 31.606487; 36.00209; 31.187859; 39.351124; 38.513866; 49.816849; 42.700157; 56.096283; 56.305599; 52.328625; 67.399269; 66.352692; 67.817894; 75.562531; 65.096809; 69.073784; 54.421768; 61.957088; 64.050232; 55.049713; 57.980114; 59.863945; 53.793823; 57.980114; 63.422295; 59.236; 57.142857; 60.282574; 61.53846; 60.701202; 61.119831; 57.142857; 61.119831; 59.654629; 64.678177; 60.49189; 59.445316; 65.096809; 63.840919; 60.073257; 61.119831; 58.817371; 57.352169; 57.770802; 66.980637; 58.817371; 66.771324; 69.073784; 77.237045; 76.81842; 74.934586; 77.86499; 77.655678; 83.097855; 82.051285; 79.748825; 84.144424; 75.143906; 74.306648; 70.329666; 66.980637; 72.632126; 71.585556; 62.79435; 63.840919; 61.957088; 63.840919; 60.910519; 62.166405; 60.073257; 60.49189; 49.816849; 45.839874; 39.141811; 45.211929; 37.885921; 36.630035; 33.07169; 37.676609; 29.931973; 25.954996; 26.16431; 23.233908; 29.304028; 23.652536; 24.489796; 21.350079; 23.024593; 15.070643; 18.62899; 24.280481; 19.675562; 25.745682; 19.466248; 24.489796; 20.931448; 19.466248; 26.582939; 24.69911; 21.768707; 23.233908; 25.327053; 25.745682; 22.815279; 25.117739; 31.187859; 27.838827; 27.210884; 26.373625; 31.187859; 29.094713; 33.908947; 39.56044; 39.979069; 37.676609; 44.583988; 48.560963; 48.351646; 47.933018; 55.677654; 62.79435; 51.072735; 48.142334; 48.142334; 59.445316; 66.352692; 74.097328; 65.724754; 60.701202; 78.702248; 80.586082; 80.586082; 79.958138; 98.377815; 101.51753; 102.77341; 96.284668; 95.447411; 87.074829; 74.515961; 80.16745; 97.959183; 99.424385; 102.14547; 104.86656; 127.0539; 154.47411; 145.47359; 140.24072; 151.75302; 166.61435; 185.45265; 158.6604; 130.61226; 133.33334; 141.49661; 147.35741; 139.61278; 140.86867; 154.05548; 184.40608; 154.47411; 149.24124; 152.17165; 164.10257; 153.84616; 147.35741; 145.89221; 168.49817; 168.49817; 174.5683; 203.87233; 191.52277; 201.77917; 199.68604; 206.80273; 223.54788; 296.80795; 275.45786; 230.45526; 258.92203; 251.1774; 257.2475; 266.45734; 243.01413; 312.92517; 293.66824; 285.08633; 303.71533; 303.92465; 400; 391.41809; 311.04132; 338.67084; 317.53009; 318.78598; 150.49713; 109.68079; 102.5641; 74.725273; 51.282051; 42.90947; 32.653061; 32.653061; 37.467293; 38.30455; 44.374672; 48.770275; 52.119308; 72.004189; 78.911568; 76.609108; 75.143906; 74.725273; 68.864471; 55.259026; 43.328098; 29.513344; 29.094713; 26.582939; 20.512819; 12.977499; 9.0005236; 3.9769754; 4.1862898; 0.8372579; 0.41862893; 0; 1.4652015]*/ //画直方图视图 for (int i = 1; i < histSize; i++) { line(histImg, Point((i-1)*binWidth,h-cvRound(bHist.at<float>(i-1))), Point(i*binWidth,h-cvRound(bHist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA); //b 蓝色 line(histImg, Point((i - 1) * binWidth,h- cvRound(gHist.at<float>(i - 1))), Point(i * binWidth, h - cvRound(gHist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA); //g 绿色 line(histImg, Point((i - 1) * binWidth,h- cvRound(rHist.at<float>(i - 1))), Point(i * binWidth, h - cvRound(rHist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA); //r 红色 } imshow("histimg", histImg); waitKey(0); return 0; }
(split拆出来的, b, g, r 三个通道的图像)
(绘制的b,g,r三通道的直方图)
代码说明:
上述直方图概念是基于图像像素值,其实对图像梯度、每个像素的角度、等一切图像的属性值,我们都可以建立直方图。这个才是直方图的概念真正意义,不过是基于图像像素灰度直方图是最常见的。
直方图最常见的几个属性:
- dims 表示维度,对灰度图像来说只有一个通道值dims=1
- bins 表示在维度中子区域大小划分,bins=256,划分为256个级别
- range 表示值得范围,灰度值范围为[0~255]之间
API学习
split(// 把多通道图像分为多个单通道图像 const Mat &src, //输入图像 Mat* mvbegin)// 输出的通道图像数组
calcHist( const Mat* images,//输入图像指针 int images,// 图像数目 const int* channels,// 通道数 InputArray mask,// 输入mask,可选,不用 OutputArray hist,//输出的直方图数据 int dims,// 维数 const int* histsize,// 直方图级数 const float* ranges,// 值域范围 bool uniform,// true by default bool accumulate// false by defaut )
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文章代码及资料部分或全部来自贾志刚老师的视频,勇哥只是在个人理解的基础上做学习笔记,转载请附上博文链接!

