一、灰度直方图的认识
我们平时看到的灰度图像是由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
#include
#include
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(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
#include
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(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.
灰度直方图