匿名
未登录
登录
丢石头百科
搜索
查看“树莓派OpenCV系列教程8:绘图板综合项目”的源代码
来自丢石头百科
名字空间
页面
讨论
更多
更多
页面选项
查看
查看源代码
历史
←
树莓派OpenCV系列教程8:绘图板综合项目
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
在上一节中,讲解了大量的概念,比较零散,于是,在这一节,将通过一个绘图板的综合项目将上一节的知识汇总起来,此外,之前的课程主要讲解OpenCV中一些基本操作,并未涉及OpenCV的精髓内容,因此,尽量早些完成相关操作的讲解,尽快进入算法讲解的环节中。 == 1.思路分析 == 类似于液晶触摸的书写,我们来研究下如何实现绘图功能。 <blockquote style="display: block; padding: 15px 15px 15px 1rem; font-size: 0.9em; margin: 1em 0px; color: rgb(129, 145, 152); border-left: 6px solid rgb(220, 230, 240); background: rgb(242, 247, 251); overflow: auto; overflow-wrap: normal; word-break: normal;"> 本质上,绘图是绘制线条,曲线可以分解成很多直线,直线可以分解成很多点,因此,就先从绘制点开始。 绘制点时鼠标在移动,因此,要设置鼠标的回调函数,那当什么时候调用回调函数呢,显然,是鼠标左键按下并且鼠标在移动的时候。 因此,程序整体结构是:定义一个回调函数,这个回调函数用于画图;然后建立一个窗口,窗口绑定回调函数;最后将回调函数画的图显示在这个窗口上。 </blockquote> 想法有了,可以开始着手了。 == 2.写出基本结构 == 由于Python的便捷性,先采用Python实现,不用太顾及语法问题。 下面先调出第一个版本的源码。 <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> import cv2 import numpy as np # 创建一个窗口 cv2.namedWindow('image') # 创建一个黑色图像 img = np.zeros((800,600,3), np.uint8) # 定义一个回调函数,用于绘制图像 def draw_point(event,x,y,flags,param): if event == cv2.EVENT_LBUTTONDOWN: cv2.circle(img,(x,y),20,(255,0,0),-1) # 将回调函数绑定到窗口上 cv2.setMouseCallback('image', draw_point) # 主循环显示图像 while(True): cv2.imshow('image',img) if (cv2.waitKey(1) == ord('q')): break cv2.destroyAllWindows() # 保存图像 cv2.imwrite( "OpenCV_Paint.png",img) </syntaxhighlight></syntaxhighlight> 第一个版本运行效果如下图所示: [[File:20191029181044.png]] == 3.总结,改进 == 在上一版本中,鼠标按下后,只能画一个点,在此情况下,需要改进为鼠标按下后,就一直画点,于是,改进后,就有了以下代码 <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> import cv2 import numpy as np isMouseLBDown = False def draw_circle(event,x,y,flags,param): print(event) global isMouseLBDown if event == cv2.EVENT_LBUTTONDOWN: # 检测到鼠标左键按下 print("mouse down") isMouseLBDown = True cv2.circle(img,(x,y),5,(255,0,0),-1) elif event == cv2.EVENT_LBUTTONUP: # 检测到鼠标左键抬起 isMouseLBDown = False print("mouse up") elif event == cv2.EVENT_MOUSEMOVE: # 如果鼠标按下并且鼠标在移动 if isMouseLBDown: print("drawing") cv2.circle(img,(x,y),5,(255,0,0),-1) # 创建一个黑色图像,并绑定窗口和鼠标回调函数 img = np.zeros((512,512,3), np.uint8) cv2.namedWindow('image') # 设置鼠标事件回调 cv2.setMouseCallback('image',draw_circle) while(True): cv2.imshow('image',img) if cv2.waitKey(1) == ord('q'): break cv2.destroyAllWindows() cv2.imwrite("OpenCV_Paint.png", img) </syntaxhighlight></syntaxhighlight> 程序运行效果如下图所示: [[File:20191029191417.png]] 程序运行后,在黑窗中,按下鼠标左键,并且移动鼠标,即可绘制图案。 == 3.再次总结,改进 == 经过一番改进,总算是能画图了,但是,画图过程中,如果画笔速度过快,那么,将会导致出现断点,并且使用上,不能调整画笔的颜色,画笔的宽度等一系列参数。为此做了以下改进: <syntaxhighlight lang="python"> <syntaxhighlight lang="python"> import cv2 import numpy as np # 判断鼠标是否按下的标志 isMouseLBDown = False # 画笔的颜色 circleColor = (0, 0, 0) # 画笔的粗壮 circleRadius = 5 # 上一次的点 lastPoint = (0, 0) # 定义鼠标函数,用于绘图 def draw_circle(event,x,y,flags,param): global img global isMouseLBDown global color global lastPoint if event == cv2.EVENT_LBUTTONDOWN: # 检测到鼠标左键按下,按下就画圆,并且记录抬起按键之前的点 isMouseLBDown = True cv2.circle(img,(x,y), int(circleRadius/2), circleColor,-1) lastPoint = (x, y) elif event == cv2.EVENT_LBUTTONUP: # 检测到鼠标左键抬起 isMouseLBDown = False elif event == cv2.EVENT_MOUSEMOVE: # 如果鼠标左键按下,并且鼠标在移动,就画线 # 并且记录按键抬起之前的点 if isMouseLBDown: cv2.line(img, pt1=lastPoint, pt2=(x, y), color=circleColor, thickness=circleRadius) lastPoint = (x, y) # 定义滑动条回调函数,用于更改颜色 def updateCircleColor(x): global circleColor global colorPreviewImg r = cv2.getTrackbarPos('Channel_Red','image') g = cv2.getTrackbarPos('Channel_Green','image') b = cv2.getTrackbarPos('Channel_Blue','image') circleColor = (b, g, r) colorPreviewImg[:] = circleColor # 定义滑动条回调函数,用于更改线条的粗壮 def updateCircleRadius(x): global circleRadius global radiusPreview circleRadius = cv2.getTrackbarPos('Circle_Radius', 'image') radiusPreview[:] = (255, 255, 255) cv2.circle(radiusPreview, center=(50, 50), radius=int(circleRadius / 2), color=(0, 0, 0), thickness=-1) # 预览画布用的画布 img = np.ones((512,512,3), np.uint8) img[:] = (255, 255, 255) # 预览画笔颜色用的画布 colorPreviewImg = np.ones((100, 100, 3), np.uint8) colorPreviewImg[:] = (0, 0, 0) # 预览画笔粗壮用的画布 radiusPreview = np.ones((100, 100, 3), np.uint8) radiusPreview[:] = (255, 255, 255) # 预览画布用的窗口 cv2.namedWindow('image') # 预览画笔颜色用的窗口 cv2.namedWindow('colorPreview') # 预览画笔粗壮用的窗口 cv2.namedWindow('radiusPreview') # 画画的鼠标回调,绑定在预览画布窗口上 cv2.setMouseCallback('image',draw_circle) # 更改颜色用的滑条回调,绑定在预览画布用的窗口 cv2.createTrackbar('Channel_Red','image',60,255,updateCircleColor) cv2.createTrackbar('Channel_Green','image',120,255,updateCircleColor) cv2.createTrackbar('Channel_Blue','image',180,255,updateCircleColor) # 更改线条粗壮的滑条回调,绑定在预览画布用的窗口 cv2.createTrackbar('Circle_Radius','image',2,20,updateCircleRadius) while(True): # 画布 cv2.imshow('image',img) # 画笔颜色 cv2.imshow('colorPreview', colorPreviewImg) # 画笔线条粗壮 cv2.imshow('radiusPreview', radiusPreview) if cv2.waitKey(1) == ord('q'): break cv2.destroyAllWindows() cv2.imwrite("OpenCV_Paint.png", img) </syntaxhighlight></syntaxhighlight> 程序运行效如下图所示,通过该程序,即可比较方便地绘图,并且,可调整画笔的颜色以及画笔的粗细: [[File:20191029195835.png]]
返回至
树莓派OpenCV系列教程8:绘图板综合项目
。
导航
导航
首页
最近更改
随机页面
MediaWiki帮助
首页
首页
树莓派
主机
配件包
外壳
键鼠
电源
扩展板
显示屏
墨水屏
摄像模块
通信模块
继电器
电机驱动板
游戏机
产品分类
树莓派
Arduino
micro:bit
STM32
Espressif
WiFi模块
蓝牙模块
无线模块
LoRa模块
4G模块
GSM
GPRS
以太网
导航模块
北斗卫星
GPS
LCD
墨水屏
OLED
摄像头
USB模块
串口模块
RS232
RS485
CAN
传感器
温度模块
湿度模块
气压模块
继电器
电机模块
指纹模块
电平转换
音频模块
编程器
Wiki工具
Wiki工具
特殊页面
页面工具
页面工具
用户页面工具
更多
链入页面
相关更改
页面信息
页面日志