#include "cv.h"
#include "highgui.h"
#pragma comment(lib,"cv.lib")
#pragma comment(lib,"highgui.lib")
#pragma comment(lib,"cxcore.lib")
void my_mouse_callback(int event,int x, int y, int flag, void* param);
CvRect box = cvRect(0,0,0,0);
bool draw_box = false;
bool high_light = false;
bool b_hist = false;
void drawbox(IplImage* img, CvRect rect)
{
cvRectangle(img,cvPoint(rect.x, rect.y),cvPoint(rect.x + rect.width, rect.y+rect.height),cvScalar(0,0,0));
//cvShowImage("Box",img);
}
void highlight(IplImage* img, CvRect rect)
{
if (high_light == true)
{
//cvSetImageROI(img,rect);
for (int y = rect.y; y<rect.y + rect.height; y++)
{
uchar* ptr = (uchar*)(img->imageData+y*img->widthStep);
for (int x = rect.x; x<rect.x + rect.width; x++)
{
ptr[x*img->nChannels + 1] = 150;
ptr[x*img->nChannels + 2] = 110;
}
}
}
cvShowImage("Box",img);
}
void drawhist(IplImage* img, CvRect rect)
{
cvSetImageROI(img,rect);
IplImage* b_plane = cvCreateImage(cvSize(rect.width,rect.height),img->depth, 1);
IplImage* g_plane = cvCreateImage(cvSize(rect.width,rect.height),img->depth, 1);
IplImage* r_plane = cvCreateImage(cvSize(rect.width,rect.height),img->depth, 1);
cvSplit(img,b_plane,g_plane,r_plane,0);
IplImage* planes[] = {b_plane,g_plane,r_plane};//元素都是指针,所以类型要用指针的指针
cvResetImageROI(img);
//每个通道分成8个等级,也就是每个通道都有8个bins
int b_bins = 8;
int g_bins = 8;
int r_bins = 8;
int hist_size[] = {g_bins,g_bins,r_bins};
//每个通道的变化范围
float b_ranges[] = {0,255};
float g_ranges[] = {0,255};
float r_ranges[] = {0,255};
float* ranges[] = {b_ranges,g_ranges,r_ranges};//元素都为指针,所以要用指针的指针类型
CvHistogram* hist = cvCreateHist(3,hist_size,CV_HIST_ARRAY,ranges,1);
cvCalcHist(planes,hist,0,0);
//获取直方图统计的最大值,进行显示直方图
float max_value;
cvGetMinMaxHistValue(hist,0,&max_value,0,0);
//直方图图像的设计
int height = 240;
int width = b_bins*g_bins*r_bins*6;
//cvNamedWindow("hist",CV_WINDOW_AUTOSIZE);
IplImage* imgHist = cvCreateImage(cvSize(width,height),8,3);
int b_width = width/(b_bins*g_bins*r_bins);
//获取直方图的每一个分量,并用相应的颜色绘制直方图
for (int r = 0; r<r_bins; r++)
{
for (int g = 0; g<g_bins; g++)
{
for (int b = 0; b<b_bins; b++)
{
int i = r*g_bins + g*b_bins+ b;
float bin_value = cvQueryHistValue_3D(hist,r,g,b);
int intensity = cvRound(bin_value * height / max_value);
CvScalar color = cvScalar(r*255/r_bins, g*255/g_bins, b*255/b_bins);
cvRectangle(imgHist,cvPoint(i*b_width,height),cvPoint((i+2)*b_width,height-intensity),color,-1,8,0);
}
}
}
cvNamedWindow("histprom",CV_WINDOW_AUTOSIZE);
cvShowImage("histprom",imgHist);
}
int main(int argc, char** argv)
{
//box = cvRect(-1,-1,0,0);
IplImage* image = cvLoadImage("3_1.bmp");
assert(image != NULL);
//保留一个原图的副本,便于后续回复原始数据
//IplImage* cloneImage = cvCloneImage(image);
IplImage* copyImage = cvCreateImage(cvGetSize(image),image->depth,image->nChannels);
cvCopy(image,copyImage);
cvNamedWindow("Box",CV_WINDOW_AUTOSIZE);
//cvNamedWindow("histprom",CV_WINDOW_AUTOSIZE);
cvShowImage("Box", copyImage);
//注册鼠标事件
cvSetMouseCallback("Box",my_mouse_callback,(void*)copyImage);
while (1)
{
cvCopy(image,copyImage);//一定要在这里,画图是画在图像的副本上。负责,画出的图是连着的
if (draw_box == true)
{
drawbox(copyImage,box);
cvShowImage("Box", copyImage);
}
if (high_light == true)
{
highlight(copyImage, box);
}
if (b_hist == true)
{
drawhist(image,box);
}
if (cvWaitKey(15) == 27)
break;
}
//开始
//cvWaitKey(0);
//cvReleaseImage(&image);
//cvDestroyAllWindows();
return 1;
}
void my_mouse_callback(int event,int x, int y, int flag, void* param)
{
switch (event)
{
case CV_EVENT_LBUTTONDOWN:
high_light = false;
draw_box = true;
b_hist = false;
box = cvRect(x,y,0,0);
break;
case CV_EVENT_MOUSEMOVE:
if (draw_box == true)
{
box.width = x - box.x;
box.height = y - box.y;
}
break;
case CV_EVENT_LBUTTONUP:
draw_box = false;
high_light = true;
b_hist =TRUE;
//drawbox((IplImage*)param, box);//这句话的作用主要是将上次画在image中的矩形复制给副本,这样就能保留显示上一次所画矩形
break;
}
}