[python opencv 計算機視覺零基礎到實戰] 十九、簡易繪畫板制作

一、學習目標

  1. 了解事件
  2. 編寫一個簡易繪畫板

二、了解如何制作簡易繪畫板

2.1 了解鼠標多種事件

上一節我們簡單的使用opencv的圖形繪制方法,用鼠標繪制了一些內容。上一節所響應的是簡單的雙擊事件EVENT_LBUTTONDBLCLK,在OpenCV的鼠標事件中還有很多。以下將列舉出來:

  • EVENT_MOUSEMOVE:鼠標滑動
  • EVENT_LBUTTONDOWN:左鍵單擊
  • EVENT_RBUTTONDOWN:右鍵單擊
  • EVENT_MBUTTONDOWN:中間單擊
  • EVENT_LBUTTONUP:左鍵釋放
  • EVENT_RBUTTONUP:右鍵釋放
  • EVENT_MBUTTONUP:中鍵釋放
  • EVENT_LBUTTONDBLCLK:左鍵雙擊
  • EVENT_RBUTTONDBLCLK:右鍵雙擊
  • EVENT_MBUTTONDBLCLK:中鍵雙擊

以上事件在setMouseCallback函數回調后將會傳到所執行的函數中,并且以event參數進行對應,取值通過event參數進行取值。

首先我們對一些事件進行監測,先嘗試檢測CV_EVENT_MOUSEMOVE鼠標滑動事件。代碼如下:

import cv2
import numpy as np
def listing(event,x,y,flags,param):if event==cv2.EVENT_MOUSEMOVE:print('EVENT_MOUSEMOVE',' x:',x,' y:',y)
img=np.zeros((600,600,3),np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',listening)
while(1):cv2.imshow('image',img)if cv2.waitKey(20)&0xFF==27:break
cv2.destroyAllWindows()

以上代碼使用listing作為回調后的處理,并且當事件為EVENT_MOUSEMOVE時將會輸出事件名以及當前鼠標所在的x和y坐標的位置。

結果如下:
這時我們可以對所有的事件都進行監聽,這時候修改listen函數就可以了:

def listening(event,x,y,flags,param):if event==cv2.EVENT_MOUSEMOVE:print('EVENT_MOUSEMOVE 鼠標滑動',' x:',x,' y:',y)elif event==cv2.EVENT_LBUTTONDOWN:print('EVENT_LBUTTONDOWN 左鍵單擊',' x:',x,' y:',y)elif event==cv2.EVENT_RBUTTONDOWN:print('EVENT_RBUTTONDOWN 右鍵單擊',' x:',x,' y:',y)elif event==cv2.EVENT_MBUTTONDOWN:print('EVENT_MBUTTONDOWN 中間單擊',' x:',x,' y:',y)elif event==cv2.EVENT_LBUTTONUP:print('EVENT_LBUTTONUP 左鍵釋放',' x:',x,' y:',y)elif event==cv2.EVENT_RBUTTONUP:print('EVENT_RBUTTONUP 右鍵釋放',' x:',x,' y:',y)elif event==cv2.EVENT_MBUTTONUP:print('EVENT_MBUTTONUP 中鍵釋放',' x:',x,' y:',y)elif event==cv2.EVENT_LBUTTONDBLCLK:print('EVENT_LBUTTONDBLCLK 左鍵雙擊',' x:',x,' y:',y)elif event==cv2.EVENT_RBUTTONDBLCLK:print('EVENT_RBUTTONDBLCLK 右鍵雙擊',' x:',x,' y:',y)elif event==cv2.EVENT_MBUTTONDBLCLK:print('EVENT_MBUTTONDBLCLK 中鍵雙擊',' x:',x,' y:',y)

結果如下:

2.2 制作一個簡單的繪畫板

首先我們對繪制一個拖拽繪制板功能做一個行為分析。我們正常進行拖拽畫矩形,一般是按下左鍵,并且不放手,移動鼠標進行矩形的繪制,直到拖拽至我們覺得合適的位置后,我們開始松開鼠標。

在以上的繪制行為中,一共有幾個鼠標事件。有按下鼠標左鍵事件EVENT_LBUTTONDOWN、鼠標移動事件EVENT_MOUSEMOVE、鼠標左鍵釋放事件EVENT_LBUTTONUP。我們在按下鼠標左鍵的時候,從當前鼠標的x與y坐標開始繪制矩形,直到我們松開鼠標后停止繪制。

我們寫一個函數作為回調的處理:

def draw(event,x,y,flags,param):

隨后我們在鼠標按下左鍵的時候需要記住x與y的坐標位置,并且表示開始繪制,需要一個變量表示繪制狀態開啟:

if event==cv2.EVENT_LBUTTONDOWN:drawing=Truesx,sy=x,y

注意,由于回調函數每次循環時都會進行調用,若drawing此次為True后下一次不能直接進入繪制,這個時候需要把drawing、sx、sy都設置成全局變量:

drawing=False
sx,sy=0,0

并且在回調處理的函數中需要加入關鍵字進行聲明是全局變量:

global sx,sy,drawing

接下來我們應該判斷當前是否已經是按下鼠標左鍵并且進行了拖拽移動,這兩個狀態是并列的,所以寫個elif語句進行判斷:

elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:

這個時候在該判斷中,使用if語句判斷是否已經按下左鍵后開啟了繪制,防止bug的出現,若已經開啟了繪制則進行繪制矩形:

cv2.rectangle(img,(sx,sy),(x,y),(0,255,0),-1)

如上代碼中為什么起始繪制點是sx與sy呢?那是因為我們按下了鼠標左鍵后的那個點是繪制起始點,從那個點開始繪制矩形到當前鼠標移動到的x和y坐標處,這樣由于每次都覆蓋掉原來的圖像造成一種錯覺,就是在拖拽進行繪制圖像,并且進行填充,顏色為(0,255,0)。由于繪制狀態不能一直開啟,若直接進入了按下左腳與移動時由于保留了上次繪制的繪制開啟,那么會造成初始繪制點的丟失,所以我們還需要判斷當鼠標左鍵釋放彈起后把繪制狀態改為Fasle。代碼如下:

elif event==cv2.EVENT_LBUTTONUP:drawing==False

所有完整的代碼如下:

import cv2
import numpy as npdrawing=False
sx,sy=0,0def draw(event,x,y,flags,param):global sx,sy,drawingif event==cv2.EVENT_LBUTTONDOWN:drawing=Truesx,sy=x,yelif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:if drawing==True:cv2.rectangle(img,(sx,sy),(x,y),(0,255,0),-1)elif event==cv2.EVENT_LBUTTONUP:drawing==False
img=np.zeros((600,600,3),np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw)
while(1):cv2.imshow('image',img)if cv2.waitKey(20)&0xFF==27:break
cv2.destroyAllWindows()

結果如下:
該系列首發于ebaina

三、總結

  1. 了解了多個鼠標事件
  2. 通過事件以及靈活運用繪圖函數制作了一個簡易的繪畫板

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/287466.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/287466.shtml
英文地址,請注明出處:http://en.pswp.cn/news/287466.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Web App 和 Native App,哪個是趨勢?

2019獨角獸企業重金招聘Python工程師標準>>> Web App 和 Native App,哪個是趨勢? https://www.zhihu.com/question/19558750 WebAPP與原生APP的交互設計區別 http://www.woshipm.com/ucd/132869.html Web App 開發使用哪種框架比較好&#xf…

基于天地圖的應用服務系統設計開發—以甘肅高校招生服務為例

“天地圖”是國家測繪地理信息局建設的地理信息綜合服務網站。它是“數字中國”的重要組成部分,是國家地理信息公共服務平臺的公眾版。“天地圖”的目的在于促進地理信息資源共享和高效利用,提高測繪地理信息公共服務能力和水平,改進測繪地理信息成果的服務方式,更好地滿足…

查缺補漏系統學習 EF Core 6 - 修改實體數據

推薦關注「碼俠江湖」加星標,時刻不忘江湖事這是 EF Core 系列的第六篇文章,上一篇文章講述了 EF Core 中的原始 SQL 語句查詢。這篇文章講一講 EF Core 如何修改實體數據。點擊上方或后方藍字,閱讀 EF Core 系列合集。實體狀態在開始學習 EF…

在AngularJS的controller外部直接獲取$scope

為了防止無良網站的爬蟲抓取文章,特此標識,轉載請注明文章出處。LaplaceDemon/SJQ。 http://www.cnblogs.com/shijiaqi1066/p/5560843.html 以前利用webqq的寫過一個自動發消息的腳本,由于那時webqq還直接使用類似jQuery操作DOM的技術&#x…

js pug 代碼_pug模版學習(一)

標簽按照html的縮進格式doctype htmlhtmlheadtitlebody編譯結果:文本p 這是文本| 這是文本p.這是文本編譯結果:這是文本這是文本這是文本屬性設置class名跟id名(默認是div)p.foop#foop#foo.foo.foo#foo編譯結果:其他屬性:a(href&q…

Upgrade Hole puncher Mathematical Modeling

// AntColony.cpp : 定義控制臺應用程序的入口點。 //#include<iostream> #include<math.h> #include<time.h> #include<stdio.h> #include <fstream> #include <string> #include <iostream> #include <vector>using n…

Android之提示Cannot call this method while RecyclerView is computing a layout or scrolling

1 問題 java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView{24d6f3b VFED.V... ......ID 0,657-1074,1911 #7f090143 app:id/recyclerView}, adapter:com.appsinno…

Java8新的異步編程方式 CompletableFuture(三)

前面兩篇文章已經整理了CompletableFuture大部分的特性&#xff0c;本文會整理完CompletableFuture余下的特性&#xff0c;以及將它跟RxJava進行比較。 3.6 Either Either 表示的是兩個CompletableFuture&#xff0c;當其中任意一個CompletableFuture計算完成的時候就會執行。 …

情人節,我表白了CSDN小姐姐后,竟然...【為表白寫了一個繪圖工具,讓我不再手殘】

情人節&#xff0c;我表白了CSDN小姐姐后&#xff0c;竟然…竟然有人看了這篇文。 以下圖片素材由一個還沒寫完的工具繪制&#xff0c;稍后會放在CSDN的代碼倉庫&#xff08;現在能用了&#xff0c;還沒時間改&#xff0c;顏色填充算法還沒寫&#xff0c;有能力的朋友可以修改一…

【小程序】劉一哥課堂隨機點名提問神器V1.0(附源程序)

為了能讓我們的孩子們盡量來教室上課,增強課堂的參與度,激發課堂激情,提高學習效率,一哥也是煞費苦心,于是開發出了這么一款課堂點名提問神器,跟大家分享一下。 打開神器,看到的界面是這樣子的,我很感激有勇氣按時起床并能到教室的每一位有志之士。 點擊【開始】按鈕,…

org.hibernate.HibernateException: No Session found for current thread

spring、springmvc和hibernate整合 在sessionFactory.getCurrentSession()時&#xff0c;出現以下異常 No Session found for current thread但使用sessionFactory.openSession()是沒有任何問題的 嚴重: Servlet.service() for servlet [springDispatcherServlet] in context w…

java mysbatis select_MyBatis SELECT基本查詢實現方法詳解

1、返回一個LISTselect * from tbl_employee where last_name like #{lastName}2、將查詢記錄封裝為一個Mapselect * from tbl_employee where id#{id}返回一條記錄的map&#xff1b;key就是列名&#xff0c;值就是對應的值。3、多條記錄封裝為一個mapMapKey("id")pu…

Git之怎么通過命令修改前面幾次提交的記錄

1 問題 我們平時用gitlab,github發現提交代碼上庫記錄寫錯了&#xff0c;需要修改回來。 2 解決辦法

Git客戶端TortoiseGit(Windows系統)的使用方法

本文環境&#xff1a; 操作系統&#xff1a;Windows XP SP3 Git客戶端&#xff1a;TortoiseGit-1.8.8.0-32bit 一、安裝Git客戶端 全部安裝均采用默認&#xff01; 1. 安裝支撐軟件 msysgit: https://code.google.com/p/msysgit/downloads/list?qfullinstallerofficialgit 當前…

.Net 在容器中操作宿主機

1方案描述 在 docker 容器中想操作宿主機&#xff0c;一般會使用 ssh 的方式&#xff0c;然后 .Net 通過執行遠程 ssh 指令來操作宿主機。本文將使用 交互式 .Net 容器版 中提供的鏡像演示 .Net 在容器中如何操作宿主機。2前期準備 1. 宿主機上生成 ssh key生成 ss…

【看動漫學編程】程序員在異世界生個娃 第1篇:太極村

前言 作者文筆比較水&#xff0c;還請見諒。 以下內容還將使用視頻動態漫畫表現&#xff0c;剪輯完將會貼出鏈接。 小說劇情為劇情需要&#xff0c;過渡到知識點&#xff0c;部分篇幅可能沒有技術知識點還望諒解。 由于沒有經費支持&#xff0c;所以畫出來的東西是我自己用代碼…

【ArcGIS風暴】最牛逼空間數據批處理神器來了:用戶自定義工具箱GeoStorm.tbx

【Warming up】在學習和工作的過程中,作者曾寫過很多采用ArcGIS模型構建器(Model Builder)、Python代碼等批處理方法(感興趣的GISers可以去【測繪地理信息Big風暴專】欄去交流學習指導),大大的減輕了操作壓力,提高了工作效率。今天給大家展示一款神器:自定義工具箱GeoS…

2.6. PostgreSQL表之間連接

到目前為止&#xff0c;我們的查詢一次只訪問了一個表。查詢可以一次訪問多個表&#xff0c;或者用某種方式訪問一個表&#xff0c;而同時處理該表的多個行。一個同時訪問同一個或者不同表的多個行的查詢叫連接查詢。舉例來說&#xff0c;比如你想列出所有天氣記錄以及這些記錄…

Android之Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains

1 問題 用takePhoto去照相的時候特么的一打開就報這個錯誤 2020-04-09 21:33:49.124 19016-19016/com.appsinnova.android.keepshare E/AndroidRuntime: FATAL EXCEPTION: mainProcess: com.appsinnova.android.keepshare, PID: 19016java.lang.RuntimeException: Unable to …