《学习OpenCV》练习题第四章第三题b

#include <highgui.h>
#include <cv.h>
#include "opencv_libs.h"

/*
 *《学习OpenCV》第四章第三题b
 * 完成时间:1:36 3/31 星期日 2013
 */

/* 矩形框 */
CvRect rect;

bool draw = false;   // 标记是否在画

IplImage* img;
IplImage * temp;
IplImage * original;

bool draw_hist = false;

IplImage* getHistImage(IplImage* image, CvHistogram* image_hist, 
					   CvSize image_size, CvScalar value)
{
	// 计算直方图
	cvCalcHist( &image, image_hist, 0, NULL );
	// 新建一幅3通道的图像
	IplImage* dst = cvCreateImage(image_size, IPL_DEPTH_8U, 3 );
	
	cvSet( dst, cvScalarAll(255) );
	
	float max_value = 0;
	cvGetMinMaxHistValue( image_hist, NULL, &max_value, NULL, NULL );
	double bin_width = (double)dst->width/256;
	double bin_unith = (double)dst->height/max_value;   // 高度比例

	for(int i = 0; i < 256; i++)
	{
		// 获得矩形左上角和右下角坐标
		CvPoint p0 = cvPoint( i + bin_width, dst->height );
		CvPoint p1 = cvPoint( (i+1) * bin_width, 
			dst->height - cvGetReal1D(image_hist->bins, i) *  bin_unith );
		// 画实心矩形
		cvRectangle( dst, p0, p1, value, -1, 8, 0 );
	}

	return dst;
}

void draw_rect(IplImage* img, CvRect rect)
{
	cvRectangle( img, 
		cvPoint( rect.x, rect.y ),
		cvPoint( rect.x + rect.width, rect.y + rect.height),
		cvScalar( 0x00, 0x00, 0xff) );
	printf("draw\n");

	// 在这里处理直方图
	// 设置感兴趣区域
	cvSetImageROI( img, rect);
	IplImage* src_rect = cvCreateImage ( 
		cvSize( rect.width, rect.height ), 
		img->depth, img->nChannels );
	cvCopy(img, src_rect );
	cvResetImageROI( img );

	IplImage* r_img = cvCreateImage( cvGetSize( src_rect),
		src_rect->depth, 1 );
	IplImage* g_img = cvCreateImage( cvGetSize( src_rect),
		src_rect->depth, 1 );
	IplImage* b_img = cvCreateImage( cvGetSize( src_rect),
		src_rect->depth, 1 );
	IplImage* gray_img = cvCreateImage( cvGetSize( src_rect),
		src_rect->depth, 1 );
	
	// 分离RGB分量
	cvSplit( src_rect, r_img, g_img, b_img, NULL);
	cvShowImage( "red", r_img);
	cvShowImage( "green", g_img);
	cvShowImage( "blue", b_img);
	
	// 灰度转换
	cvCvtColor( src_rect, gray_img, CV_BGR2GRAY);
	int size = 256;
	float range[] = {0, 255};
	float* ranges[] = {range};
	// 创建直方图
	CvHistogram * r_hist = cvCreateHist( 1, &size, CV_HIST_ARRAY, ranges, 1);
	CvHistogram * g_hist = cvCreateHist( 1, &size, CV_HIST_ARRAY, ranges, 1);
	CvHistogram * b_hist = cvCreateHist( 1, &size, CV_HIST_ARRAY, ranges, 1);
	CvHistogram * gray_hist = cvCreateHist( 1, &size, CV_HIST_ARRAY, ranges, 1);

	// 直方图尺寸
	CvSize image_size = cvSize( 400, 300);
	
	IplImage* r_dst = getHistImage(r_img, r_hist, image_size, cvScalar(0x00, 0x00, 0xff));
	IplImage* g_dst = getHistImage(g_img, g_hist, image_size, cvScalar(0x00, 0xff, 0x00));
	IplImage* b_dst = getHistImage(b_img, b_hist, image_size, cvScalar(0xff, 0x00, 0x00));
	IplImage* gray_dst = getHistImage( gray_img, gray_hist, image_size, cvScalar(0) );

	// 把四个直方图在一幅图片上显示出来
	IplImage* dst = cvCreateImage( cvSize( image_size.width * 2, image_size.height * 2), 8, 3 );
	cvSetZero( dst );
	// 拷贝红色分量直方图
	CvRect r_rect = cvRect( 0, 0, image_size.width, image_size.height);
	cvSetImageROI(dst, r_rect);
	cvCopy( r_dst, dst);
	// 拷贝绿色分量直方图
	CvRect g_rect = cvRect(image_size.width, 0, image_size.width, image_size.height );
	cvSetImageROI( dst, g_rect);
	cvCopy( g_dst, dst);
	// 蓝色分量
	CvRect b_rect = cvRect(0, image_size.height, image_size.width, image_size.height );
	cvSetImageROI(dst, b_rect);
	cvCopy( b_dst, dst );
	// 灰度分量
	CvRect gray_rect = cvRect( image_size.width, image_size.height, 
		image_size.width, image_size.height );
	cvSetImageROI( dst, gray_rect);
	cvCopy( gray_dst, dst);

	cvResetImageROI( dst );

	cvShowImage( "src", src_rect);
	cvShowImage( "dst", dst );

	cvWaitKey(0);

	cvDestroyAllWindows();
	cvReleaseImage( &r_img );
	cvReleaseImage(&g_img);
	cvReleaseImage(&b_img);
	cvReleaseImage(&gray_img);
	cvReleaseImage(&r_dst);
	cvReleaseImage(&g_dst);
	cvReleaseImage(&b_dst);
	cvReleaseImage(&gray_dst);
	cvReleaseImage(&src_rect);
	cvReleaseImage(&dst);
}

// 鼠标回调函数
void my_mouse_callback( int event, int x, int y, int flags, void* param)
{
	IplImage* image = (IplImage*) param;

	switch( event )
	{
	case CV_EVENT_MOUSEMOVE:
		{
			if(draw)
			{
				rect.width = x - rect.x;
				rect.height = y - rect.y;
			}

			draw_hist = false;
		}
		break;
	case CV_EVENT_LBUTTONDOWN:
		{
			draw = true;
			rect = cvRect( x, y, 0, 0 );
			draw_hist = false;
		}
		break;
	case CV_EVENT_LBUTTONUP:
		{
			draw = false;
			draw_hist = true;
			if(rect.width < 0)
			{
				rect.x += rect.width;
				rect.width *= -1;
			}
			if(rect.height < 0)
			{
				rect.y += rect.height;
				rect.height *= -1;
			}
			// draw
			draw_rect(image, rect);
		}
		break;
		// 在右键按下时清除
	case CV_EVENT_RBUTTONDOWN:
		cvCopyImage(original, img);
		printf("clear.\n");
		break;
	}
}

int main()
{
	img = cvLoadImage( "lena.bmp", 1 );

	rect = cvRect( -1, -1, 0, 0);
	
	// 副本
    temp = cvCloneImage( img );
	original = cvCloneImage(img);
	
	cvNamedWindow("draw rect");
	cvSetMouseCallback("draw rect", my_mouse_callback, (void*)img);

	while(1)
	{
		cvCopyImage(img, temp);

		if(draw_hist)
		{
			draw_rect( temp , rect );
		}

		cvShowImage( "draw rect", temp);

		if(cvWaitKey(15) == 27)
			break;
	}
	cvReleaseImage(&img);
	cvReleaseImage(&temp);
	cvDestroyAllWindows();

	return 0;
}

运行结果:



不足:在源图像上用鼠标选择矩形区域的时候,无法实时地在图像上反映出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值