《学习OpenCV》第四章第5题

来源:互联网 发布:8051单片机内部结构图 编辑:程序博客网 时间:2024/06/01 08:00

创建一个程序,可以新建一个图像,并将图像所有像素值设置为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);    //建一个图片,用来储存前一步画好后的图片imgchar 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;}

画线:
画线

画矩形:
这里写图片描述

画圆:
这里写图片描述

画椭圆:
这里写图片描述

画多边形:
这里写图片描述

大杂烩:
这里写图片描述

原创粉丝点击