您的位置:首页 > 其它

灰度直方图的原理和计算

2016-07-11 09:43 357 查看

一、灰度直方图的认识

  我们平时看到的灰度图像是由0到255个像素组成的,像素是组成图像的基本单位,灰度直方图就是灰度图像素值的直观体现,其中bins就是衣服灰度图直方图的条数。

                                                  


                                     


二、程序1

原理大家去百度吧,在这就不具体说了。

程序中涉及到血多opencv函数,我下面简单介绍一些:

1.计算直方图:

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 );
分别表示:输入图像、输入图像的维数、输入图像的通道数、掩膜、输出直方图、输出维数、输出直方图的bins数等。

2.球直方图最大、最小块,也即是找最大和最小的bins

void minMaxLoc( const Mat& src,double* minVal,double* maxVal=0,Point* minLoc=0,Point* maxLoc=0,const Mat& mask=Mat() );
3.在图像中画矩形

void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
分别表示:原图像、左上角坐标、右下角坐标等

好,开始贴代码:

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat src, gray;
src = imread("D:\\vvoo\\lena.jpg");
cvtColor(src, gray, CV_RGB2GRAY);

int bins = 256;//一维直方图bins
int hist_size[] = { bins };

float range[] = { 0, 256 };//直方图每一个bins的范围
const float* ranges[] = { range };
MatND hist;//输出直方图

int channels[] = { 0 };//一维通道

//创建并计算直方图
calcHist(&gray, 1, channels, Mat(), // do not use mask
hist, //输出直方图
1, hist_size,
ranges,
true, // the histogram is uniform
false);

double max_val;
minMaxLoc(hist, 0, &max_val, 0, 0);//找出最大的bins值
int scale = 2;//bins之间的距离为2
int hist_height = 300;//输出直方图的高度

Mat hist_img = Mat::zeros(hist_height, bins*scale, CV_8UC3);//定义hist_img的矩阵,高度为hist_height,宽度为bins*scale

for (int i = 0; i<bins; i++)
{
float bin_val = hist.at<float>(i);

int intensity = cvRound(bin_val*hist_height / max_val);  //归一化,要绘制的高度,从上往下数

rectangle(hist_img, Point(i*scale, hist_height/* - 1*/),
Point((i + 1)*scale - 1, hist_height - intensity),
CV_RGB(0, 255, 255));
}
imshow("Source", src);
imshow("Gray Histogram", hist_img);
waitKey(500000);
return 0;
}


运行结果:

原图



直方图



三、程序2(滑动块控制量化位数)

是对程序1进行稍微更改:

滑动块函数:

CreateTrackbar(
const char* trackbar_name, //滑动条的名称
const char* window_name, //窗口的名称,滑动条不会遮挡图像
int* value, //当滑动条被拖到时,OpenCV会自动将当前位置所代表的值传给指针指向的整数
int count, //滑动条所能达到的最大值
CvTrackbarCallback on_change //可选的回调函数,回调函数可参见http://wapedia.mobi/zhtrad/回调函数
);


程序2:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

Mat srcImage, gray;
int bins = 200;
#define hist_height 500//输出直方图的高度
#define hist_width  800

static void showHelpText();
static void HIST(int, void*);

int main()
{
showHelpText();
system("color 4d");
srcImage = imread("D:\\vvoo\\lena.jpg");

if (!srcImage.data)
{
cout << "the image is error !" << endl;
return 0;
}
namedWindow("srcIamge");
imshow("srcIamge", srcImage);
cvtColor(srcImage, gray, CV_RGB2GRAY);

//调用
createTrackbar("bins", "srcIamge", &bins, 256, HIST);
HIST(0, 0);

while ((char(waitKey(1)) != 'q'))//q键退出
{
}
waitKey(0);
return 0;
}
static void HIST(int, void*)
{
int hist_size[] = { bins };

float range[] = { 0, 256 };//直方图每一个bins的范围
const float* ranges[] = { range };
MatND hist;//输出直方图

int channels[] = { 0 };//一维通道

//创建并计算直方图
calcHist(&gray, 1, channels, Mat(), // do not use mask
hist, //输出直方图
1, hist_size,
ranges,
true, // the histogram is uniform
false);

double max_val;
minMaxLoc(hist, 0, &max_val, 0, 0);//找出最大的bins值

Mat hist_img = Mat::zeros(hist_height, hist_width, CV_8UC3);//定义hist_img的矩阵

double bin_w = (double)hist_width / bins;  //bins为直方图条的个数,则 bin_w 为条的宽度

for (int i = 0; i<bins; i++)
{
float bin_val = hist.at<float>(i);

int intensity = cvRound(bin_val*hist_height / max_val);  //归一化,要绘制的高度,从上往下数

rectangle(hist_img, Point(i*bin_w, hist_height),
Point((i + 1)*bin_w, hist_height - intensity),
CV_RGB(255, 0, 255));
}
imshow("一维直方图", hist_img);
}
static void showHelpText()
{
cout << "通过滑块调节直方图量化的条数" << endl;
}


结果:



四、参考资料

1.点击打开链接
http://blog.csdn.net/sxhelijian/article/details/8042507
2.灰度直方图
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息