认识画图函数
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
//#include<iostream>#define w 400using namespace cv;/*
大量使用 Point 和 Scalar 这两个结构:
Point数据结构表示了由其图像坐标 x 和 y 指定的2D点;
也可以用Point2f表示坐标由浮点数表示。Scalar是一个由长度为4的数组作为元素构成的结构体,Scalar最多可以存储四个值,没有提供的值默认是0;
此类型在OpenCV中被大量用于传递像素值,如用它来表示RGB颜色值(三个参数):
Scalar( a, b, c ),那么定义的RGB颜色值为: Red = c, Green = b and Blue = a
*/
/// Function Declaration
void MyEllipse(Mat img, double angle)
{int thickness = 2;int lineType = 8;//线形为8连通线型ellipse(img,Point(int(w / 2.0), int(w / 2.0)),//中心点Size(w / 4, w / 16),//大小angle,//椭圆旋转角度0,//扩展弧度起始点360,//终点Scalar(255, 0, 0), //使用Scalar类型数据设置colorthickness,lineType);
}
//void MyFilledCircle(Mat img, Point2f center);
void MyFilledCircle(Mat img, Point2f center)
{int thickness = -1; //封闭曲线,则要填充图像int lineType = 8;circle(img,center,w / 32,Scalar(0, 0, 255), //设置colorthickness,lineType);
}int main(int argc, char **argv)
{/// Windows nameschar atom_window[] = "Drawing 1: Atom";/// Create black empty images Mat atom_image = Mat::zeros(w, w, CV_8UC3); //创建Mat类的对象atom_image,使用Mat类的zeros方法//参数CV_8UC3表示unsigned 8 bits,3通道(Channels)/// 1. Draw a simple atom:/// -----------------------/// 1.a. Creating ellipses MyEllipse(atom_image, 90);MyEllipse(atom_image, 0);MyEllipse(atom_image, 45);MyEllipse(atom_image, -45);/// 1.b. Creating circlesMyFilledCircle(atom_image, Point2f(w / 2.0, w / 2.0));//PointF,由于这里(System.Drawing)的“点”设计用于屏幕显示用,//而屏幕显示以像素为单位,一般使用整数形式的Point就足够了/// 2. Display your stuff!imshow(atom_window, atom_image);imwrite("C:\\Users\\77607\\Desktop\\atom_image.jpg", atom_image);//需要将opencv*.dll拷贝一份放在和exe相同文件夹下waitKey(0);return(0);
}
使用鼠标当画笔画图
目标:
- 学习使用OpenCV处理鼠标事件
- 学习函数:cv::setMouseCallback()
void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0)winname:窗口的名字onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 这个函数的原型应该为void on_Mouse(int event, int x, int y, int flags, void* param);userdate:传给回调函数的参数
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui_c.h>
#include<opencv2\opencv.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;char *window_name = "image";
// mouse callback function
void draw_circle(int event, int x, int y, int flags, void* param);
int main()
{Mat img = Mat::zeros(512, 512, CV_8UC3);namedWindow(window_name);imshow(window_name, img);setMouseCallback(window_name, draw_circle, (void*)&img);while (1){if (cvWaitKey(20))break;}waitKey(0);return 0;
}
void draw_circle(int event, int x, int y, int flags, void* param)
{Mat depth_img = *(Mat*)param; // 先转换类型,再取数据if (event == CV_EVENT_LBUTTONDBLCLK)//位于highgui_c.h{circle(depth_img, cvPoint(x, y), 100, CV_RGB(0, 0, 255), -1);imshow(window_name, depth_img);}
}
可以通过鼠标输入改变绘图模式
#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui_c.h>
#include<opencv2\opencv.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;char *window_name = "test";
bool mode = true;
void drawByMouse(int event, int x, int y, int flags, void *param);int main(int argc, char* argv[])
{Mat img = Mat::zeros(800, 600, CV_8UC3);namedWindow(window_name);imshow(window_name, img);setMouseCallback(window_name, drawByMouse, (void*)&img);while (1){//imshow(window_name, img);int k = cvWaitKey(1);if (k == 'm')mode = !mode;else if (k == 27)break;}waitKey(0);return 0;}void drawByMouse(int event, int x, int y, int flags, void *param)
{Mat depth_img = *(Mat*)param; // 先转换类型,再取数据static CvPoint point_start, point_end;static bool draw_flag = false;switch (event){case CV_EVENT_LBUTTONDOWN://位于highgui_c.h{draw_flag = true;point_start = cvPoint(x, y);break;}case CV_EVENT_LBUTTONUP:{draw_flag = false;break;}case CV_EVENT_MOUSEMOVE:{if (draw_flag == true)if (mode == true){point_end = cvPoint(x, y);rectangle(depth_img, point_start, point_end, CV_RGB(0, 255, 0), -1);imshow(window_name, depth_img);}else{circle(depth_img, cvPoint(x, y), 3, CV_RGB(0, 0, 255), -1);imshow(window_name, depth_img);}}}
}
生产非填充的矩形
//#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui_c.h>
//#include<opencv2\imgproc\imgproc.hpp>
#include<opencv2\opencv.hpp>
#include<iostream>using namespace cv;
#define WINDOW_NAME "【程序窗口】" //为窗口标题定义的宏
//c和c++中允许用一个标识符来表示一个字符串,称为“宏”/*****************鼠标操作*****************/
Rect g_rect;
//Recg类用于创建一个矩形对象,矩形左上角的横坐标、纵坐标以及矩形的宽度、高度均为零。
bool g_DrawFlag = false;
RNG g_rng(12345);
//RNG类是opencv里C++的随机数产生器。它可产生一个64位的int随机数。
//RNG可以产生3种随机数
//RNG(int seed) 使用种子seed产生一个64位随机整数,默认 - 1
//计算机产生的随机数都是伪随机数,是根据种子seed和特定算法计算出来的。
//所以,只要种子一定,算法一定,产生的随机数是相同的
//RNG::uniform() 产生一个均匀分布的随机数
//RNG::gaussian() 产生一个高斯分布的随机数
void on_MouseHandle(int event, int x, int y, int flag, void* param);
void DrawRectangle(Mat& img, Rect box);
void main()
{//准备参数g_rect = Rect(-1, -1, 0, 0);Mat srcImage(600, 600, CV_8UC3), tempImage;srcImage.copyTo(tempImage);//image.copyTo(imageROI)。作用是把image的内容复制粘贴到imageROI上//g_rect = Rect(-1, -1, 0, 0);srcImage = Scalar::all(0);//设置鼠标操作回调函数namedWindow(WINDOW_NAME);setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage);//绘画while (1){srcImage.copyTo(tempImage);if (g_DrawFlag) {DrawRectangle(tempImage, g_rect);}imshow(WINDOW_NAME, tempImage);if (waitKey(10) == 27) break;//ESC 退出}
}
//鼠标回调事件
void on_MouseHandle(int event, int x, int y, int flag, void* param)
{Mat& image = *(Mat*)param;switch (event){case EVENT_MOUSEMOVE://移动if (g_DrawFlag) {//计算,g_rect宽高=鼠标当前位置坐标-g_rect左上角的坐标g_rect.width = x - g_rect.x;g_rect.height = y - g_rect.y;}break;case EVENT_LBUTTONDOWN://左键按下g_DrawFlag = true;//设置g_rect的初始值在同一个点g_rect = Rect(x, y, 0, 0);break;case EVENT_LBUTTONUP://左键抬起//在画填充矩形的程序中,鼠标移动时开始画,非填充矩形是左键抬起开始画g_DrawFlag = false;//当g_rect宽高小于0//起始点xy坐标置为较小靠左上角的点//宽高取绝对值if (g_rect.width < 0) {g_rect.x += g_rect.width;g_rect.width *= -1;}if (g_rect.height < 0) {g_rect.y += g_rect.height;g_rect.height *= -1;}//画矩形DrawRectangle(image, g_rect);break;}
}
//矩形绘制函数
void DrawRectangle(Mat& img, Rect box)
{//rectangle画矩形//tl左上角的点,br右下角的点//Scalar设置颜色,设置为3通道//g_rng.uniform(0, 255)随机颜色rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0, 255),g_rng.uniform(0, 255), g_rng.uniform(0, 255)));//box.tl(); //返回box的左上顶点的坐标//box.br(); //返回box的右下顶点的坐标
}