/*定义各种形状*/ #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(中文版)》第4章 练习5a
最新推荐文章于 2024-09-22 22:54:23 发布