opencv画图_c++

认识画图函数

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc.hpp>
//#include<iostream>

#define w 400

using 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类型数据设置color
		thickness,
		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), //设置color
		thickness,
		lineType);
}

int main(int argc, char **argv) 
{
	/// Windows names
	char 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 circles
	MyFilledCircle(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);
}

使用鼠标当画笔画图

目标:

  1. 学习使用OpenCV处理鼠标事件
  2. 学习函数: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的右下顶点的坐标 
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值