赞
踩
直方图的优点
图像直方图由于其计算代价较小,且具有图像平移、旋转、缩放不变性等众多优点,广泛地应用于图像处理的各个领域,特别是灰度图像的阈值分割、基于颜色的图像检索以及图像分类。
函数部分如下所示:
- void QuickDemo::histogram_demo(Mat &image) {
- /*图像直方图是图像像素值的统计学特征,计算代价较小,具有图像的平移、旋转、缩放不变性的优点。
- Bins是指直方图的大小范围
- */
- //三通道分离
- std::vector<Mat>bgr_plane;
- split(image, bgr_plane);
- //定义参数变量
- const int channels[1] = { 0 };
- const int bins[1] = { 256 };//一共有256个灰度级别
- float hranges[2] = { 0,255 };//每个通道的灰度级别是0-255
- const float* ranges[1] = { hranges };
- Mat b_hist;
- Mat g_hist;
- Mat r_hist;
- //计算Blue、Green、Red通道的直方图,1表示只有一张图,因为可以支持多张图多个通道;0表示只有1个通道;raanges就是直方图的取值范围0-25
- calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist,1,bins, ranges);
- calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
- calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);
- //显示直方图
- int hist_w = 512;
- int hist_h = 400;
- int bin_w = cvRound((double)hist_w / bins[0]);
- Mat histImage = Mat::zeros(hist_h, hist_w, CV_8UC3);
- //归一化直方图数据
- normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
- normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
- normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
- //绘制直方图曲线
- for (int i = 1; i < bins[0]; i++) {
- line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
- Point(bin_w * (i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);
- line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
- Point(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);
- line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
- Point(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, 8, 0);
- }
- //显示直方图
- namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
- imshow("Histogram Demo", histImage);
- }
函数部分如下所示:
- void QuickDemo::histogram_2d_demo(Mat& image) {
- //2D直方图
- Mat hsv, hs_hist;
- cvtColor(image, hsv, COLOR_BGR2HSV);
- int hbins = 30;//H一共有180,设置hbins为30可以理解为分30个类统计
- int sbins = 32;
- int hist_bins[] = { hbins,sbins };
- float h_range[] = { 0,180 };
- float s_range[] = { 0,256 };
- const float* hs_ranges[] = { h_range,s_range };
- int hs_channels[] = { 0,1 };
- calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges, true, false);
- double maxVal = 0;
- minMaxLoc(hs_hist, 0, &maxVal, 0, 0);
- int scale = 10;
- Mat hist2d_image = Mat::zeros(sbins * scale, hbins * scale, CV_8UC3);
- for (int h = 0; h < hbins; h++) {
- for (int s = 0; s < sbins; s++) {
- float binVal = hs_hist.at<float>(h, s);
- int intensity = cvRound(binVal * 255 / maxVal);
- rectangle(hist2d_image, Point(h * scale, s * scale), Point((h + 1) * scale - 1, (s + 1) * scale - 1), Scalar::all(intensity), -1);
- }
-
- }
- imshow("H-S Histogram", hist2d_image);
- imwrite("D:/hist_2d.png", hist2d_image);
-
- }
对于要显示彩色的二维直方图需要加一句话如下所示:
applyColorMap(hist2d_image, hist2d_image, COLORMAP_JET);
结果如下所示:
- Mat QuickDemo::histogram_grayImage(const Mat& image)
- {
- //定义求直方图的通道数目,从0开始索引
- int channels[] = { 0 };
- //定义直方图的在每一维上的大小,例如灰度图直方图的横坐标是图像的灰度值,就一维,bin的个数
- //如果直方图图像横坐标bin个数为x,纵坐标bin个数为y,则channels[]={1,2}其直方图应该为三维的,Z轴是每个bin上统计的数目
- const int histSize[] = { 256 };
- //每一维bin的变化范围
- float range[] = { 0,256 };
-
- //所有bin的变化范围,个数跟channels应该跟channels一致
- const float* ranges[] = { range };
-
- //定义直方图,这里求的是直方图数据
- Mat hist;
- //opencv中计算直方图的函数,hist大小为256*1,每行存储的统计的该行对应的灰度值的个数
- calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges, true, false);
-
- //找出直方图统计的个数的最大值,用来作为直方图纵坐标的高
- double maxValue = 0;
- //找矩阵中最大最小值及对应索引的函数
- minMaxLoc(hist, 0, &maxValue, 0, 0);
- //最大值取整
- int rows = cvRound(maxValue);
- //定义直方图图像,直方图纵坐标的高作为行数,列数为256(灰度值的个数)
- //因为是直方图的图像,所以以黑白两色为区分,白色为直方图的图像
- Mat histImage = Mat::zeros(rows, 256, CV_8UC1);
-
- //直方图图像表示
- for (int i = 0; i < 256; i++)
- {
- //取每个bin的数目
- int temp = (int)(hist.at<float>(i, 0));
- //如果bin数目为0,则说明图像上没有该灰度值,则整列为黑色
- //如果图像上有该灰度值,则将该列对应个数的像素设为白色
- if (temp)
- {
- //由于图像坐标是以左上角为原点,所以要进行变换,使直方图图像以左下角为坐标原点
- histImage.col(i).rowRange(Range(rows - temp, rows)) = 255;
- }
- }
- //由于直方图图像列高可能很高,因此进行图像对列要进行对应的缩减,使直方图图像更直观
- Mat resizeImage;
- resize(histImage, resizeImage, Size(256, 256));
- return resizeImage;
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。