改进实例1——加一个进度条控制横坐标bin
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
#define cvQueryHistValue_1D( hist, idx0 ) ((float)cvGetReal1D( (hist)->bins, (idx0)))
int hist_size= 200; //直方图横坐标——bin
int hist_height= 300; 直方图纵坐标——随意定
void on_trackbar( int pos ) ;
void main( )
{
IplImage * src= cvLoadImage("b.jpg");
IplImage* gray_plane = cvCreateImage(cvGetSize(src),8,1);
cvCvtColor(src,gray_plane,CV_BGR2GRAY);
float range[] = {0,255}; //灰度级的范围
float* ranges[]={range}; //就是用指针指向这个数组,
//然后这个指针就能访问和控制这个数组了。
cvNamedWindow( "H-S Histogram", CV_WINDOW_AUTOSIZE );
cvNamedWindow( "GraySource", CV_WINDOW_AUTOSIZE );
while(1)
{
cvCreateTrackbar( "position", "H-S Histogram",&hist_size,255, on_trackbar );//滑块位置的最大值为180.
//on_trackbar(0);——本来有这句话,怎么运行都不成功,后来发现,根本不需要好不好。cvCreateTrackbar函数运行的时候自己就会调用on_trackbar()函数。
cout <<hist_size<< endl;
CvHistogram* gray_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
//计算灰度图像的一维直方图
cvCalcHist(&gray_plane,gray_hist,0,0);
//归一化直方图
cvNormalizeHist(gray_hist,1.0);
int scale = 3;
//创建一张一维直方图的“图”,横坐标为bin
IplImage* hist_image = cvCreateImage(cvSize(hist_size*scale,hist_height),8,3);
cvZero(hist_image);
//统计直方图中的最大直方块
float max_value = 0;
cvGetMinMaxHistValue(gray_hist, 0,&max_value,0,0);
//分别将每个直方块的值绘制到图中
for(int i=0;i<hist_size;i++)
{
float bin_val = cvQueryHistValue_1D(gray_hist,i);
int intensity = cvRound(bin_val*hist_height/max_value); //要绘制的高度
cvRectangle(hist_image,
cvPoint(i*scale,hist_height-1),
cvPoint((i+1)*scale - 1, hist_height - intensity),
CV_RGB(255,255,255));
}
cvShowImage("GraySource",gray_plane);
cvShowImage( "H-S Histogram", hist_image );
if (cvWaitKey(0) == 27)break;
}
cvDestroyAllWindows();
}
void on_trackbar( int pos ) //定义一个回调函数——pos是形参,随便起一个名字
{
hist_size=pos;
}
程序运行时的问题
运行这个程序的时候,发现怎么改变滑块的值,直方图根本不变化。后来才发现,按下滑块之后,还要按【回车】键,直方图才会变化。
——不知道为什么,也没百度到答案。
while(1)是要有的,本来就是为了能够实时刷新显示直方图——结果还需要配合手动按回车键,呵呵。
改进实例2:进度条控制hsv格式的h通道的直方图
还是需要按下滑块之后,再按【回车】键,直方图才会变化。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
#define cvQueryHistValue_1D( hist, idx0 ) ((float)cvGetReal1D( (hist)->bins, (idx0)))
int hist_size= 200; //直方图横坐标——bin
int hist_height= 300; //直方图纵坐标——随意定
void on_trackbar( int pos ) ;
int main(int argc, char** argv)
{
IplImage * src= cvLoadImage("b.jpg");
IplImage* hsv = cvCreateImage(cvGetSize(src), 8, 3);
cvCvtColor(src, hsv, CV_BGR2HSV);
IplImage* h_plane = cvCreateImage(cvGetSize(src), 8, 1);
IplImage* s_plane = cvCreateImage(cvGetSize(src), 8, 1);
IplImage* v_plane = cvCreateImage(cvGetSize(src), 8, 1);
cvSplit(hsv, h_plane, s_plane, v_plane, 0);
float range[] = {0,255}; //灰度级的范围
float* ranges[]={range}; //就是用指针指向这个数组,然后这个指针就能访问和控制这个数组了。
cvNamedWindow( "H-S Histogram", CV_WINDOW_AUTOSIZE );
cvNamedWindow( "GraySource", CV_WINDOW_AUTOSIZE );
while(1)
{
cvCreateTrackbar( "position", "H-S Histogram",&hist_size,255, on_trackbar );//滑块位置的最大值为180.
// cout <<hist_size<< endl;
CvHistogram* h_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
//计算灰度图像的一维直方图
cvCalcHist(&h_plane,h_hist,0,0);
//归一化直方图
cvNormalizeHist(h_hist,1.0);
int scale = 3;
IplImage* hist_image = cvCreateImage(cvSize(hist_size*scale,hist_height),8,3);
cvZero(hist_image);
//统计直方图中的最大直方块
float max_value = 0;
cvGetMinMaxHistValue(h_hist, 0,&max_value,0,0);
//分别将每个直方块的值绘制到图中
for(int i=0;i<hist_size;i++)
{
float bin_val = cvQueryHistValue_1D(h_hist,i);
//像素i的概率
int intensity = cvRound(bin_val*hist_height/max_value); //要绘制的高度
cvRectangle(hist_image,
cvPoint(i*scale,hist_height-1),
cvPoint((i+1)*scale - 1, hist_height - intensity),
CV_RGB(255,255,255));
}
cvShowImage("GraySource",h_plane);
cvShowImage( "H-S Histogram", hist_image );
if (cvWaitKey(0) == 27)break;
}
cvDestroyAllWindows();
}
void on_trackbar( int pos )
//定义一个回调函数——pos是形参,随便起一个名字
{
hist_size=pos;
}