灰度直方图的显示

    写在前面:入门OpenCV的时候,找了很多资料,发现各种教材深浅不一,对于新手来说总是难以上手。最近看了《OpenCV2 计算机视觉编程手册》,发现该书难度适中,很适合自己。现在将自己学习该书的过程整理如下,便于以后回过头来复习。

    灰度直方图是OpenCV中一种简单实用的工具,这一篇我们来学习怎样显示一幅图像的灰度直方图。

1.直方图的定义

    灰度直方图是灰度级的函数,它表示图像中具有某种灰度级的像素的个数,反映了图像中某种灰度出现的频率。如果将图像总像素亮度(灰度级别)看成是一个随机变量,则其分布情况就反映了图像的统计特性,这可用probability density function(PDF)来刻画和描述,表现为灰度直方图。【百度百科】

2.构造直方图

class Histogram1D{
private:
	int histSize[1];//项的数量
	float hranges[2]; //像素的最小及最大值
	const float*ranges[1];
	int channels[1];  //仅用到一个通道

public:
	Histogram1D(){
       //准备1D直方图的参数
		histSize[0] = 256;
		hranges[0] = 0.0;
		hranges[1] = 255.0;
		ranges[0] = hranges;
		channels[0] = 0; //默认情况,我们考察0号通道
	}

       //方法:计算1D直方图
	MatND getHistogram(const Mat &image){
		MatND hist;
               //计算直方图
		calcHist(&image,
			1,        //计算单张图像的直方图
			channels, //通道数量
			Mat(),    //不使用图像作为掩码
			hist,     //返回的直方图
			1,        //这是1D的直方图
			histSize, //项的数量
			ranges    //像素值的范围
			);
		return hist;
	}
       //方法:直方图可视化
	Mat getHistogramImage(const Mat &image){
                //首先计算直方图
                MatND hist = getHistogram(image);
                //获取最大值和最小值
                double maxVal = 0;
		double minVal = 0;
		
		minMaxLoc(hist, &minVal, &maxVal, 0, 0);
                //显示直方图的图像
		Mat histImg(histSize[0], histSize[0], CV_8U, Scalar(255));

                //设置最高点为nbins的90%
		int hpt = static_cast<int>(0.9*histSize[0]);

                //每个条目都绘制一条垂直线
		for (int h = 0; h < histSize[0]; h++){
			float binVal = hist.at<float>(h);
			int intensity = static_cast<int>(binVal*hpt / maxVal);
                       //两点之间绘制一条线 
                        line(histImg, Point(h, histSize[0]), Point(h, histSize[0] - intensity), Scalar::all(0));
		}
		return histImg;
	}

};

    这个类中定义了一维直方图中参数、计算直方图的方法及将直方图可视化的方法。

3. 实例

//------------------------------------【程序功能】-----------------------------------------------
//  描述:显示灰度图的一维直方图
//-----------------------------------------------------------------------------------------------

//----------------------------------【头文件包含部分】-------------------------------------------
//  描述:包含程序所依赖的文件
//-----------------------------------------------------------------------------------------------
#include <iostream>
#include "highgui.h"
#include <opencv2/opencv.hpp>

<pre name="code" class="cpp">//-----------------------------------【命名空间声明】--------------------------------------------
//  描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------
using namespace cv;
using namespace std;

// 定义直方图的类
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] = 255.0;
		ranges[0] = hranges;
		channels[0] = 0;
	}

	MatND getHistogram(const Mat &image){
		MatND hist;
		calcHist(&image,
			1,
			channels,
			Mat(),
			hist,
			1,
			histSize,
			ranges
			);
		return hist;
	}
	Mat getHistogramImage(const Mat &image){
		MatND hist = getHistogram(image);
		double maxVal = 0;
		double minVal = 0;
		
		minMaxLoc(hist, &minVal, &maxVal, 0, 0);

		Mat histImg(histSize[0], histSize[0], CV_8U, Scalar(255));

		int hpt = static_cast<int>(0.9*histSize[0]);

		for (int h = 0; h < histSize[0]; h++){
			float binVal = hist.at<float>(h);
			int intensity = static_cast<int>(binVal*hpt / maxVal);
			line(histImg, Point(h, histSize[0]), Point(h, histSize[0] - intensity), Scalar::all(0));
		}
		return histImg;
	}

}
//-------------------------------------【main()函数】-----------------------------------------------
//描述:控制台应用程序的入口
//--------------------------------------------------------------------------------------------------
int main(){

    Mat image = imread("sky-lancer.jpg", 0);  //默认读入灰度图
    namedWindow("sky-lancer1");
    imshow("sky-lancer1", image);
    waitKey(5000);

    Histogram1D h;   
    namedWindow("Histogram");
    imshow("Histogram", h.getHistogramImage(image));
    waitKey(5000);

}

原图


读入的灰度图


显示的灰度直方图

4. 多维直方图

  要获得彩色图像的其他通道的直方图,可以从所定义的类入手,修改其通道数,也可以使用Split(Mat &src,Mat &dst)函数,先将彩色图像分为3个通道,再分别调用getHistogramImage方法。

代码如下:

int main(){

       vector<Mat> mv;
	Mat image0 = imread("sky-lancer.jpg", 1);
	

	split(image0,mv);
	namedWindow("通道0");
	imshow("通道1", mv.at(0));
	waitKey(5000);

	Histogram1D h;
	namedWindow("Histogram1");
	imshow("Histogram1", h.getHistogramImage(mv.at(0)));
	waitKey(5000);
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值