【OpenCV学习笔记】2.4制作绘图板
来源:互联网 发布:魔女之泉3 知乎 编辑:程序博客网 时间:2024/05/17 05:04
学了几天OpenCV,写个小程序把这几天的所得综合实践一下。
一、功能简介
绘图板小程序主要实现以下几个方面功能:
1. 滑动条控制画笔参数(颜色、粗细);
2. 鼠标控制绘图(停顿为实心圆,移动为平滑轨迹);
3. 设置按键功能(重来,保存,退出);
4. 调色盘显示取色。
5. 新增功能:右键漫水填充填色 2015/12/29
1.滑动条控制
设立4个滑动条控制画笔的颜色(B、G、R)和粗细(Thick)
(1)、为画笔颜色、粗细定义全局变量并赋初值
//全局变量double Brush_r = 255.0;double Brush_g = 255.0;double Brush_b = 255.0;int Brush_thick = 5;
(2)、响应滑动条的回调函数
void ON_TRACKBAR_B(int t, void*){//更改蓝色 Brush_b = t; Brush_color=Scalar(Brush_b,Brush_g,Brush_r);}void ON_TRACKBAR_G(int t, void*){//更改绿色 Brush_g = t; Brush_color = Scalar(Brush_b, Brush_g, Brush_r);}void ON_TRACKBAR_R(int t, void*){//更改红色 Brush_r = t; Brush_color = Scalar(Brush_b, Brush_g, Brush_r);//注意颜色为BGR}void ON_TRACKBAR_THICK(int t, void*){//更改画笔粗细 Brush_thick = t;}
2、鼠标控制
响应鼠标的3种事件。
(1)、鼠标左键按下开始绘图
鼠标事件:EVENT_LBUTTONDOWN
动作:改变bool值drawflag表示开始绘图,记录当前坐标Current,并画点(实心圆)circle()
(2)、在左键按下的同时移动鼠标,绘制鼠标移动的轨迹
鼠标事件:EVENT_MOUSEMOVE
动作:识别是否同时左键按下,更新上一个坐标(Pre)和当前坐标(Current),绘制轨迹线line()
(3)、左键抬起停止绘图
鼠标事件:EVENT_LBUTTONUP
动作:改变bool值drawflag表示停止绘图
void ON_MOUSE_HANDLE(int event,int x,int y,int flags,void* param){ Mat& picture = *(Mat *)param; switch (event) { case EVENT_LBUTTONDOWN://左键按下 { drawflag = 1; Current=Point(x,y); circle(picture, Current, Brush_thick/2, Brush_color, -1);//参数依据滑动条改变 break; } case EVENT_MOUSEMOVE://鼠标移动 { if (drawflag){//左键是否为按下状态 Point Pre = Current; Current = Point(x, y); line(picture, Pre, Current, Brush_color, Brush_thick);//参数依据滑动条改变 } break; } case EVENT_LBUTTONUP://左键抬起 { drawflag = 0; break; } }}
新增功能:漫水填充
case EVENT_RBUTTONDOWN: { floodFill(picture, Point(x, y), Brush_color); break; }
要特别注意每条CASE后的break语句,不然Switch的各种Case会依次执行。
3、调色盘功能
区别“=”和copyTo:
- “Mat A=B”意味着 A将指向B的同一块内存;
- “A.copyTo(B)”意味着A的内容复制给了B,B的地址不变。
Mat platte = tempImage(Rect(0, 0, 50, 50));//调色盘指向的是图像上的左上角矩形区域 Mat temp = Mat(50, 50, CV_8UC3, Scalar(Brush_b, Brush_g, Brush_r));//参数随滑动条变化 temp.copyTo(platte);//只改变调色盘的内容,即改变当前图像左上角矩形区域的颜色
第3行 不能用 “platte = temp”代替, 它会令调色盘指向了temp
4、按键功能
在程序的主循环中用waitKey()重复获取按键信息,以switch语句判别应该完成的功能,添加按键功能重来,保存,退出功能。
- waitKey()参数为n表示每等待n毫秒获取按键值一次;但当n为0时,表示无限等待。
- default项很重要,没有default,当没有输入时,主循环无法继续。
int c = waitKey(1);//不为0即可 switch (c) { case 114://按'r'键 清空绘图板 srcImage.copyTo(tempImage); imshow(WINDOW_NAME1, tempImage); break; case 115://按's'键 save图像 platte.copyTo(temp2);//暂存调色盘 temp = Mat(50, 50, CV_8UC3, Scalar(0, 0,0)); temp.copyTo(platte); imwrite("……/temp.jpg", tempImage);//保存不显示调色盘的图像 temp2.copyTo(platte); break; case 27: //按ESC键,程序退出 loopflag = 0; //退出主循环的控制值 break; default://未获取以上按键、无按键输入时的操作 break; }
二、main函数的写法
#include<opencv2/opencv.hpp>using namespace cv;#define WINDOW_NAME1 "【绘图板】 Press 'r' restart ; Press 's' save ; Press 'Esc' quit . "#define WINDOW_WIDTH 600//全局函数声明void ON_MOUSE_HANDLE(int event, int x, int y, int flags, void* param);void ON_TRACKBAR_B(int t, void*);void ON_TRACKBAR_G(int t, void*);void ON_TRACKBAR_R(int t, void*);//全局变量声明bool drawflag = 0;Point Current;double Brush_r = 255.0;double Brush_g = 255.0;double Brush_b = 255.0;int Brush_thick = 5;String trackbarname_r = "红色值";String trackbarname_g = "绿色值";String trackbarname_b = "蓝色值";String trackbarname_thick = "画笔粗细";Scalar Brush_color = Scalar(255,255,255);//入口函数int main(){ system("color 9F"); Current = Point(0, 0); Mat srcImage(600, 800, CV_8UC3), tempImage; srcImage = Scalar(0, 0, 0); srcImage.copyTo(tempImage);//保护源图 namedWindow(WINDOW_NAME1); //创建滑动条控件 int threshold_b=255; createTrackbar(trackbarname_b, WINDOW_NAME1, &threshold_b, 255, ON_TRACKBAR_B); ON_TRACKBAR_B(threshold_b,0);//响应滑动条的回调函数 int threshold_g=255; createTrackbar(trackbarname_g, WINDOW_NAME1, &threshold_g, 255, ON_TRACKBAR_G); ON_TRACKBAR_G(threshold_g, 0); int threshold_r=255; createTrackbar(trackbarname_r, WINDOW_NAME1, &threshold_r, 255, ON_TRACKBAR_R); ON_TRACKBAR_R(threshold_r, 0); int threshold_thick = 5; createTrackbar(trackbarname_thick, WINDOW_NAME1, &threshold_thick, 100, ON_TRACKBAR_THICK); ON_TRACKBAR_THICK(threshold_thick, 0); //设置鼠标操作回调函数 setMouseCallback(WINDOW_NAME1, ON_MOUSE_HANDLE, (void*)&tempImage);//tempImage是传递到回调函数中的参数param //程序主循环,当进行绘制的标识符为真时,进行绘制 bool loopflag = 1; while (loopflag)// { Mat platte = tempImage(Rect(0, 0, 50, 50));//将绘图板左上角小块矩形区域创建为调色盘 Mat temp = Mat(50, 50, CV_8UC3, Scalar(Brush_b, Brush_g, Brush_r)); temp.copyTo(platte); imshow(WINDOW_NAME1, tempImage); int c = waitKey(1);//获取按键 Mat temp2 = Mat(50, 50, CV_8UC3);//用于暂存调色盘 switch (c) { case 114://'r' srcImage.copyTo(tempImage); imshow(WINDOW_NAME1, tempImage); break; case 115://'s' platte.copyTo(temp2);//避免保存图像显示调色盘 temp = Mat(50, 50, CV_8UC3, Scalar(0, 0,0)); temp.copyTo(platte); imwrite("……/temp.jpg", tempImage); temp2.copyTo(platte); break; case 27: //esc loopflag = 0; break;//按下ESC键,程序退出 default: break; } } return 0; }
三、运行效果
从运行效果一起来看一下绘图板发展:
1、跟随鼠标轨迹
该版本错误的将绘图操作放在了主循环里,每循环一次才画一个点,导致了不连续。并且每个点都是用circle()画空心的圆。
2、平滑绘图
改在EVENT_MOUSEMOVE中用line()画极短的线。
3、加入颜色调整
该版本缺点是不知道将会出来什么样的颜色。
4、设立调色盘
同时优化保存画面时去掉调色盘。
5、加入调整粗细
同时调整笔触,落点为实心圆。
6、新增:漫水填充
增加右键功能——floodFill填充颜色
大功告成!欢迎朋友们指点……
- 【OpenCV学习笔记】2.4制作绘图板
- Html5用Canvas制作绘图板
- 绘图板
- Html5用Canvas制作绘图板<最终>
- 初学java制作了一个绘图板
- opencv 训练器的制作笔记
- 非常值得学习的java 绘图板源代码
- 非常值得学习的java 绘图板源代码
- 《学习OpenCV》 学习笔记
- Python下使用OpenCV——使用Trackbar实现绘图板
- opencv学习笔记(二十四)——相机标定板制作
- OpenCV学习笔记(三):Canny边缘检测和滚动条制作
- OpenCV 2 学习笔记(1): OpenCV 2.4.3 的安装
- OpenCV学习笔记(基于OpenCV 2.4)一:哈喽CV
- 【 OpenCV学习笔记 002】OpenCV 2.4.9组件结构解析
- 网络制作学习笔记
- 页面制作学习笔记
- OpenCV学习笔记
- dubbo使用
- 1014
- 2009
- adb 使用sqlite3查看数据库时提示 sqlite3 not found
- gfb
- 【OpenCV学习笔记】2.4制作绘图板
- 面向对象的mysqli基础
- 关于嵌入文本框设置只读后,后台获取不到值--解决办法
- 如何在JavaWeb程序中使用自定义标签(tag、tld两种)
- spring注解或依赖注入模拟MVC结构案例<五>
- 广义表-(没有测试过)
- android开发之高仿微信6.0+滑动Tab
- httpClient使用文档整理
- 计算机专业推荐国际会议