图像是由不同数值的颜色像素组成,像素值在整幅图像中的分布情况是该图像的一个重要属性。直方图(Histogram)是一幅图像分布的精确图形表示。因此,灰度图像的直方图有256个项目。
OpenCV可以简单地调用 cv:calcHist 函数来进行直方图计算,我们创建一个专用类来处理单通道灰度图像的类。
class Histogram1D {
private:
int histSize[1];
float hranges[2];
const float* ranges[1];
int channels[1];
public:
Histogram1D() {
histSize[0] = 256;
hranges[0] = 0.0;
hranges[1] = 256.0;
ranges[0] = hranges;
channels[0] = 0;
}
Mat getHistogram(const Mat &image) {
Mat hist;
calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);
return hist;
}
Mat getHistogramImage(const Mat &image, int zoom = 1) {
Mat hist = getHistogram(image);
return getImageOfHistogram(hist, zoom);
}
static Mat getImageOfHistogram(const Mat &hist, int zoom) {
double maxVal = 0;
double minVal = 0;
minMaxLoc(hist, &minVal, &maxVal, 0, 0);
int histSize = hist.rows;
Mat histImg(histSize*zoom, histSize*zoom, CV_8U, Scalar(255));
int hpt = static_cast(0.9*histSize);
for (int h = 0; h < histSize; h++) {
float binVal = hist.at(h);
if (binVal > 0) {
int intensity = static_cast(binVal*hpt / maxVal);
line(histImg, Point(h*zoom, histSize*zoom),
Point(h*zoom, (histSize - intensity)*zoom), Scalar(0), zoom);
}
}
return histImg;
}
};
所使用的图片如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M9HaoMqo-1582555944898)(https://i.imgur.com/4dMKhGF.png)]
主函数编辑:
int main()
{
Mat image = imread("Fig3.15(a)1top.BMP", 0);
Histogram1D h;
Mat histo = h.getHistogram(image);
for (int i = 0; i < 256; i++)
{
cout << "Value " << i << " = " << histo.at(i) << endl;
}
namedWindow("Histogram");
imshow("Histogram", h.getHistogramImage(image));
waitKey(0);
return 0;
}
输出的值非0的结果:
Value 12 = 477
Value 13 = 16986
Value 14 = 379
Value 15 = 572
Value 16 = 1917
Value 17 = 8955
Value 18 = 2129
Value 19 = 16228
Value 20 = 10188
Value 21 = 3327
Value 22 = 5751
Value 23 = 1406
Value 24 = 4224
Value 25 = 1266
Value 26 = 4332
Value 27 = 2539
Value 28 = 2830
Value 29 = 5529
Value 30 = 2141
Value 31 = 3653
Value 32 = 2187
Value 33 = 4142
Value 34 = 3227
Value 35 = 5808
Value 36 = 3019
Value 37 = 4913
Value 38 = 6980
Value 39 = 4303
Value 40 = 3729
Value 41 = 4048
Value 42 = 6398
Value 43 = 1849
Value 44 = 6581
Value 45 = 1762
Value 46 = 6731
Value 47 = 9532
Value 48 = 3374
Value 49 = 5324
Value 50 = 2989
Value 51 = 4945
Value 52 = 3840
Value 53 = 3528
Value 54 = 3609
Value 55 = 5614
Value 56 = 5712
Value 57 = 1385
Value 58 = 4312
Value 59 = 2731
Value 60 = 3788
Value 61 = 1018
Value 62 = 3184
Value 63 = 863
Value 64 = 1910
Value 65 = 3471
Value 66 = 2638
Value 67 = 697
Value 68 = 2341
Value 69 = 1434
Value 70 = 1339
Value 71 = 1378
Value 72 = 1744
Value 73 = 971
Value 74 = 2267
Value 75 = 1460
Value 76 = 861
Value 77 = 909
Value 78 = 158
Value 79 = 141
Value 80 = 16
Value 81 = 9
Value 82 = 1
Value 83 = 1
直方图显示如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pq3f3EX7-1582555944899)(https://i.imgur.com/mUPmfn1.png)]
OpenCV提供了一个直方图均衡化的函数 cv::equalizeHist(image,result),我们通过使用这个函数来实现直方图均衡化,通过修改下面main函数:
int main()
{
Mat image = imread("Fig3.15(a)1top.BMP", 0);
Histogram1D h;
Mat histo = h.getHistogram(image);
for (int i = 0; i < 256; i++)
{
if (histo.at(i) != 0)
cout << "Value " << i << " = " << histo.at(i) << endl;
}
namedWindow("Histogram");
imshow("Histogram", h.getHistogramImage(image));
/*namedWindow("Cell");
imshow("Cell", image);
equalizeHist(image, image);
namedWindow("CellequalizeHist");
imshow("CellequalizeHist", image);
namedWindow("Histogram2");
imshow("Histogram2", h.getHistogramImage(image));*/
waitKey(0);
return 0;
}
最终效果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HrH9bNF4-1582555944900)(https://i.imgur.com/mItsC9D.png)]