您的位置:首页 > 运维架构

学习opencv第四章第三题

2013-03-10 08:53 357 查看
#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;

	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: