创建一个程序,可以新建一个图像,并将图像所有像素值设置为0,然后将其显示出来。允许用户通过鼠标左键画线、矩形、圆、椭圆以及多边形。并使其能在右击鼠标时,实现橡皮擦功能。
#include<iostream>
#include"highgui.h"
#include"cv.h"
using namespace std;
using namespace cv;
#define WIDTH 512
#define HEIGHT 512
//用来记录多边形的每个点
typedef struct Node {
CvPoint p;
Node *next;
}Node;
CvPoint point_start; //建一个全体量,用来作为各个图形的开始点
CvPoint point_end; //建一个全体量,用来作为各个图形的结束点
int g_rnd, r_rnd, b_rnd; //颜色RGB三值随机变量
IplImage *img = cvCreateImage(cvSize(WIDTH, HEIGHT), 8, 3); //建一个图片,在其上进行画图操作
IplImage *img_copy = cvCreateImage(cvSize(WIDTH, HEIGHT), 8, 3); //建一个图片,用来储存前一步画好后的图片img
char flag; //建一个标志,确定当前状态
int flagmove = 0; //用来判断是否按过左键,来决定移动鼠标是否有响应
int flagstart = 1; //或多边形操作时,判断是否是第一个点
CvPoint** ps = (CvPoint**)malloc(sizeof(CvPoint*)); //用来存放多边形顶点的二维CvPoint数组
Node *head, *pnode; //Node类型节点,存放顶点数据
int count1 = 0; //记录多边形顶点个数
int a[1]; //存放count1
//先介绍画图操作
void introduce() {
cout << "按下L键,开始画直线" << endl;
cout << "按下R键,开始画矩形" << endl;
cout << "按下C键,开始画圆" << endl;
cout << "按下E键,开始画椭圆" << endl;
cout << "按下P键,开始画多边形(按下左键确定顶点,之后右键完成多边形)" << endl;
cout << "右键清除" << endl;
}
//随机获得一个颜色画图
void getColor() {
r_rnd = (int)(rand()) % 256;
b_rnd = (int)(rand()) % 256;
g_rnd = (int)(rand()) % 256;
}
//画线函数
void drawLine() {
cvLine(img, point_start, point_end, CV_RGB(r_rnd, g_rnd, b_rnd),2);
}
//画矩形函数
void drawRectangle() {
cvRectangle(img, point_start, point_end, CV_RGB(r_rnd, g_rnd, b_rnd),2);
}
//画圆函数
void drawCircle() {
int x, y, r;
//避免出现负数
if (point_start.x < point_end.x)
x = point_end.x - point_start.x;
else
x = point_start.x - point_end.x;
if (point_start.y < point_end.y)
y = point_end.y - point_start.y;
else
y = point_start.y - point_end.y;
r = (int)sqrt(x*x + y*y); //半径
cvCircle(img, cvPoint(point_start.x / 2 + point_end.x / 2, point_start.y / 2 + point_end.y / 2),
r, CV_RGB(r_rnd, g_rnd, b_rnd),2);
}
//画椭圆函数
void drawEllipse() {
int x, y;
if (point_start.x < point_end.x)
x = point_end.x - point_start.x;
else
x = point_start.x - point_end.x;
if (point_start.y < point_end.y)
y = point_end.y - point_start.y;
else
y = point_start.y - point_end.y;
cvEllipse(img, cvPoint(point_start.x / 2 + point_end.x / 2, point_start.y / 2 + point_end.y / 2),
cvSize(x / 2, y / 2), 0, 0, 360, CV_RGB(r_rnd, g_rnd, b_rnd),2);
}
//画多边形函数
void drawPolygon() {
int i;
//取出链表中的数据,放入ps中
pnode = head;
ps[0] = (CvPoint*)malloc(sizeof(CvPoint) * count1);
for (i = 0; pnode != NULL; i++, pnode = pnode->next) {
ps[0][i] = cvPoint(pnode->p.x, pnode->p.y);
}
ps[0][i] = cvPoint(head->p.x, head->p.y);
cvPolyLine(img, ps, a, 1, 1, CV_RGB(r_rnd, g_rnd, b_rnd),2);
}
//判断当前为何种操作
void draw() {
if (flag == 'l' || flag == 'L') drawLine();
else if (flag == 'c' || flag == 'C') drawCircle();
else if (flag == 'r' || flag == 'R') drawRectangle();
else if (flag == 'e' || flag == 'E') drawEllipse();
else if (flag == 'p' || flag == 'P') drawPolygon();
}
//鼠标响应函数
void on_my_mouse(int event, int x, int y, int flags, void* userdata) {
//因为多边形操作不同,单独提出
if (flag == 'p' || flag == 'P')
switch (event) {
//每当按下左键,记录下当前坐标,若是起始点,将head复制为pnode,同时计数点值0
case CV_EVENT_LBUTTONDOWN: cvCopy(img_copy, img); if (flagstart) {
head = new Node;
pnode = new Node;
count1 = 0;
head = pnode;
getColor();
point_start = cvPoint(x,y);
pnode->p.x = x;
pnode->p.y = y;
pnode->next = new Node;
pnode = pnode->next;
count1++;
}
flagmove = 1;
flagstart = 0;
break;
case CV_EVENT_MOUSEMOVE: if (flagmove) {
cvCopy(img_copy,img);
point_end = cvPoint(x, y);
cvLine(img, point_start, point_end, CV_RGB(r_rnd, g_rnd, b_rnd), 2);
cvShowImage("test", img);
}
break;
case CV_EVENT_LBUTTONUP: cvCopy( img,img_copy); point_start = cvPoint(x, y); flagmove = 0;
pnode->p.x = x;
pnode->p.y = y;
pnode->next = new Node;
pnode = pnode->next;
count1++; break;
//按下右键,画出多边形,以及清除功能
case CV_EVENT_RBUTTONDOWN: if (pnode == NULL) {
cvZero(img);
cvCopy(img, img_copy);
}
else {
pnode->next = NULL; a[0] = count1; draw();
cvCopy(img, img_copy); flagstart = 1;
}
break;
}
//其余的操作响应
else
switch (event) {
//按下左键,记录点坐标到起始点point_start中,并将flagmove值1,代表鼠标移动有响应
case CV_EVENT_LBUTTONDOWN: cvCopy(img_copy, img); point_start = cvPoint(x, y);
getColor(); flagmove = 1; break;
//flagmove为1时,将鼠标坐标值入结束点point_end中,动态展现当前作图情况
case CV_EVENT_MOUSEMOVE: if (flagmove) {
cvCopy(img_copy, img);
point_end = cvPoint(x, y);
draw();
cvShowImage("test", img);
}break;
//抬起左键,flagmove值0,鼠标移动相应结束
case CV_EVENT_LBUTTONUP: cvCopy(img, img_copy); flagmove = 0; break;
//点击右键,图片清除
case CV_EVENT_RBUTTONDOWN: cvZero(img); cvZero(img_copy); break;
}
}
int main(void) {
//初始化造作
char c;
cvNamedWindow("test");
cvZero(img);
cvZero(img_copy);
introduce();
setMouseCallback("test", on_my_mouse);
while (1) {
cvShowImage("test", img);
c = cvWaitKey(30);
//判断选择的操作情况
if (c == 'P' || c == 'p' || c == 'C' || c == 'c' || c == 'e' ||
c == 'E' || c == 'l' || c == 'L' || c == 'R' || c == 'r')
flag = c;
if ((int)(c) == 27)
break;
}
return 0;
}
画线:
画矩形:
画圆:
画椭圆:
画多边形:
大杂烩: