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

《学习OpenCV(中文版)》第4章 练习5a

2013-11-24 04:07 369 查看
/*定义各种形状*/
#define SHAPE_NONE 0
#define SHAPE_LINE 1
#define SHAPE_RECT 2
#define SHAPE_CIRCLE 3
#define SHAPE_ELLIPSE 4
#define SHAPE_PLYGON 5

#define SHAPE_COUNT 6	//总的形状数,包括清空(SHAPE_NONE)
#define _ERASER 6		//橡皮擦标识

int width = 300;
int height = 300;
int shape_status = SHAPE_NONE;		//记录各种状态
CvPoint begin_point, end_point;		//鼠标摁下及松开时的坐标
void on_mouse_callback(int event, int x, int y, int flags, void* param) {
IplImage* img1 = (IplImage*)param;
switch(event) {
case CV_EVENT_LBUTTONDOWN:			//鼠标左边点击,确定行为
{
int perWidth = width/SHAPE_COUNT;	//每个按钮的宽度
if(y>height) {					//点击自定义的按钮
if(x<perWidth) {
shape_status = SHAPE_LINE;
} else if(x<2*perWidth) {
shape_status = SHAPE_RECT;
} else if(x<3*perWidth) {
shape_status = SHAPE_CIRCLE;
} else if(x<4*perWidth) {
shape_status = SHAPE_ELLIPSE;
} else if(x<5*perWidth) {
shape_status = SHAPE_PLYGON;
} else {
shape_status = SHAPE_NONE;
cvSetImageROI(img1, cvRect(0, 0, width, height));	//清空画面
cvZero(img1);
cvResetImageROI(img1);
}
} else {
//记录起点
if(shape_status != SHAPE_NONE) {
begin_point.x = x;
begin_point.y = y;
}
}
break;
}
case CV_EVENT_RBUTTONDOWN:
{
shape_status = _ERASER;
break;
}
case CV_EVENT_LBUTTONUP:		//鼠标左键起来时,各种画图
{
if(y<height) {			//在画面区域时
cvSetImageROI(img1, cvRect(0, 0, width, height));	//限定在画面区域,避免自定义按钮被覆盖或清空
//记录终点
if(shape_status != SHAPE_NONE) {
end_point.x = x;
end_point.y = y;
}
switch(shape_status) {
case SHAPE_LINE:
{
cvLine(img1, begin_point, end_point, cvScalar(255, 0, 0));	//画直线
break;
}
case SHAPE_RECT:
{
cvRectangle(img1, begin_point, end_point, cvScalar(0, 255, 0));	//画矩形
break;
}
case SHAPE_CIRCLE:
{
cvCircle(
img1, 
begin_point,	//以起点为圆心
std::sqrt(std::pow(1.0*(end_point.x-begin_point.x), 2)+std::pow(1.0*(end_point.y-begin_point.y), 2)*1.0f),	//两点距离为半径
cvScalar(0, 0, 255));
break;
}
case SHAPE_ELLIPSE:
{
cvEllipse(
img1, 
cvPoint((begin_point.x+end_point.x)/2, (begin_point.y+end_point.y)/2),	//两点中点为中心
cvSize(std::abs(end_point.x - begin_point.x), std::abs(end_point.y - begin_point.y)),	//两点为对角所确定的矩形区域
0,
0,
360,
cvScalar(255, 255, 0)
);
break;
}
case SHAPE_PLYGON:
//do nothing,还没想好怎么画

break;
}
cvResetImageROI(img1);
}
cvShowImage("Picture", img1);
break;
}
case CV_EVENT_RBUTTONUP:
{
shape_status = SHAPE_NONE;
break;
}
case CV_EVENT_MOUSEMOVE:
{
if(shape_status == _ERASER && y<height) {
for(int i=-2; i<=2; i++) {		//橡皮擦,以(x,y)为中心的大小为5的矩形橡皮擦
for(int j=-2; j<=2; j++) {
//所经过的点复原为0
*(cvPtr2D(img1, y+i, x+j)+0) = 0;
*(cvPtr2D(img1, y+i, x+j)+1) = 0;
*(cvPtr2D(img1, y+i, x+j)+2) = 0;
}
}
}
cvShowImage("Picture", img1);
break;
}
}
}
void myGUI5a() {
cvNamedWindow("Picture");
int delta = 40;
IplImage* img = cvCreateImage(cvSize(width, height+delta), IPL_DEPTH_8U, 3);	//加20用于做按钮
cvZero(img);
//自定义按钮
//cvLine(img, cvPoint(0, height), cvPoint(width, height), cvScalar(255, 255, 255));
int perWidth = width/SHAPE_COUNT;	//每个按钮的宽度
for(int i=0; i<SHAPE_COUNT; i++) {
int next_row = height + delta;
int next_col = (i+1)*perWidth;
int color = 255 - 20*i;			//按钮不同颜色
for(int row=height;row<next_row; row++) {
for(int col=i*perWidth;col<next_col; col++) {
*(cvPtr2D(img, row, col)+0) = color;
*(cvPtr2D(img, row, col)+1) = color;
*(cvPtr2D(img, row, col)+2) = color;
}
}
}

cvSetMouseCallback("Picture", on_mouse_callback, img);
cvShowImage("Picture", img);
cvWaitKey(0);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opencv CC++