立即注册 找回密码

微雪课堂

搜索
微雪课堂 首页 树莓派 树莓派OpenCV教程 查看内容

树莓派OpenCV系列教程8:绘图板综合项目

2019-10-29 20:02| 发布者: Tornado| 查看: 1187| 评论: 0

摘要: 在上一节中,讲解了大量的概念,比较零散,于是,在这一节,将通过一个绘图板的综合项目将上一节的知识汇总起来,此外,之前的课程主要讲解OpenCV中一些基本操作,并未涉及OpenCV的精髓内容,因此,尽量早些完成相关 ...

在上一节中,讲解了大量的概念,比较零散,于是,在这一节,将通过一个绘图板的综合项目将上一节的知识汇总起来,此外,之前的课程主要讲解OpenCV中一些基本操作,并未涉及OpenCV的精髓内容,因此,尽量早些完成相关操作的讲解,尽快进入算法讲解的环节中。

1.思路分析

类似于液晶触摸的书写,我们来研究下如何实现绘图功能。

本质上,绘图是绘制线条,曲线可以分解成很多直线,直线可以分解成很多点,因此,就先从绘制点开始。

绘制点时鼠标在移动,因此,要设置鼠标的回调函数,那当什么时候调用回调函数呢,显然,是鼠标左键按下并且鼠标在移动的时候。

因此,程序整体结构是:定义一个回调函数,这个回调函数用于画图;然后建立一个窗口,窗口绑定回调函数;最后将回调函数画的图显示在这个窗口上。

想法有了,可以开始着手了。

2.写出基本结构

由于Python的便捷性,先采用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)

第一个版本运行效果如下图所示:

3.总结,改进

在上一版本中,鼠标按下后,只能画一个点,在此情况下,需要改进为鼠标按下后,就一直画点,于是,改进后,就有了以下代码

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)

程序运行效果如下图所示:

程序运行后,在黑窗中,按下鼠标左键,并且移动鼠标,即可绘制图案。

3.再次总结,改进

经过一番改进,总算是能画图了,但是,画图过程中,如果画笔速度过快,那么,将会导致出现断点,并且使用上,不能调整画笔的颜色,画笔的宽度等一系列参数。为此做了以下改进:

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)

程序运行效如下图所示,通过该程序,即可比较方便地绘图,并且,可调整画笔的颜色以及画笔的粗细:


73

顶一下

刚表态过的朋友 (73 人)

相关阅读

最新评论

基础入门
OpenCV
littleGL

微雪官网|产品资料|手机版|小黑屋|微雪课堂. ( 粤ICP备05067009号 )

GMT+8, 2020-7-7 01:36 , Processed in 0.019321 second(s), 19 queries .

返回顶部