Angle Finder(角度测量)
目錄
一 前言
二 實(shí)現(xiàn)步驟
1 需要的第三方庫
2 讀取圖像
3 獲取鼠標(biāo)點(diǎn)
(1)打印鼠標(biāo)點(diǎn)擊的位置(演示,不一定要實(shí)現(xiàn))
(2)創(chuàng)建列表存儲坐標(biāo)并將點(diǎn)擊生成的點(diǎn)繪制出來
4 計(jì)算三個(gè)點(diǎn)組成的角的度數(shù)
5 潤色(繪制線段構(gòu)成角度)?
三 整體代碼
四 結(jié)束語
一 前言
? ? ? ?在本次項(xiàng)目中,我們將會使用鼠標(biāo)構(gòu)建一個(gè)角,并顯示這個(gè)角的度數(shù);即通過點(diǎn)擊鼠標(biāo)來生成兩條線,如果這兩條線相交就會形成一個(gè)夾角,我們要做的就是測量這個(gè)夾角的度數(shù)。和之前的項(xiàng)目一樣,本項(xiàng)目也是博主在Github中找到的比較有趣的項(xiàng)目,大家如果感興趣可以嘗試著復(fù)現(xiàn)一遍,如果對其他項(xiàng)目感興趣可以關(guān)注下面這專欄,有時(shí)間我會更新一些比較有趣的項(xiàng)目分享給大家:
GitHub 計(jì)算機(jī)視覺項(xiàng)目實(shí)踐
Now, let's start!
二 實(shí)現(xiàn)步驟
? ? ? ?先來簡單介紹一下本次的任務(wù),我們要通過點(diǎn)擊鼠標(biāo)生成三個(gè)點(diǎn),而這三個(gè)點(diǎn)剛好能夠組成兩條相交的射線,接下我們使用一些簡單的數(shù)學(xué)知識就可以得出這個(gè)角的度數(shù)了。不難看出,本次的項(xiàng)目并沒有太大的難度,主要是使用數(shù)學(xué)方法計(jì)算角度。
1 需要的第三方庫
? ? ? ?在本次項(xiàng)目中首先是要對圖像中的角度進(jìn)行測量,所以需要的第一個(gè)庫是?OpenCV;然后需要計(jì)算角度,免不了數(shù)學(xué)計(jì)算,因此還需要 math 庫,使用這兩個(gè)庫就可以實(shí)現(xiàn)本次項(xiàng)目了。
2 讀取圖像
? ? ? ?本項(xiàng)目是在圖像中測量角度,所以第一步需要做的是讀取目標(biāo)圖像。本次實(shí)驗(yàn)中我使用的是隨便找的一幅圖像,只要是使用 CV2 第三方庫能夠讀取就到圖像就可以。
讀取圖像的代碼比較簡單,如下:
import cv2 import mathpath = 'test.jpg' #圖像讀取路徑 img = cv2.imread(path) #讀取圖像如果你想將圖像顯示出來也可以:
3 獲取鼠標(biāo)點(diǎn)
? ? ? ? 讀取圖像之后我們要操作的是能夠讓鼠標(biāo)的點(diǎn)擊在圖像中起作用(點(diǎn)擊左鍵就可以創(chuàng)建一個(gè)點(diǎn),通過三次點(diǎn)擊不同的點(diǎn)得到一個(gè)角)。在這里我們創(chuàng)建一個(gè) mousepoint() 函數(shù)來完成這個(gè)任務(wù)。
(1)打印鼠標(biāo)點(diǎn)擊的位置(演示,不一定要實(shí)現(xiàn))
? ? ? ?通過下面的函數(shù)就可以實(shí)現(xiàn)鼠標(biāo)點(diǎn)的檢測并將點(diǎn)擊的坐標(biāo),本過程只是顯示鼠標(biāo)的點(diǎn)擊位置,在項(xiàng)目中不一定實(shí)現(xiàn)
def mousePoints(event, x, y, flags, params):if event == cv2.EVENT_LBUTTONDOWN: #檢測是否有鼠標(biāo)左鍵按下print(x, y)cv2.setMouseCallback('Image', mousePoints) #鼠標(biāo)的點(diǎn)擊返回到圖像中通過點(diǎn)擊就可以打印出鼠標(biāo)的位置?
(2)創(chuàng)建列表存儲坐標(biāo)并將點(diǎn)擊生成的點(diǎn)繪制出來
每測量一個(gè)角度我們要生成不止一個(gè)點(diǎn),所以我們可以將這些點(diǎn)的坐標(biāo)存儲到一個(gè)列表中。
pointsList = [] #創(chuàng)建列表來存儲鼠標(biāo)點(diǎn)擊的坐標(biāo)點(diǎn)(這行代碼并不在定義的函數(shù)中)pointsList.append([x, y])#將坐標(biāo)點(diǎn)存儲在列表中(這行代碼應(yīng)該在函數(shù)中)cv2.circle(img, (x, y), 5, (0, 0, 255), cv2.FILLED) #在鼠標(biāo)的點(diǎn)擊處繪制一個(gè)實(shí)心圓#上面的代碼都是實(shí)現(xiàn)功能的方式,并不會全都排列在一起將存有坐標(biāo)點(diǎn)的列表打印下來如下:?
4 計(jì)算三個(gè)點(diǎn)組成的角的度數(shù)
? ? ? ?當(dāng)我們的列表中存儲的點(diǎn)的個(gè)數(shù)達(dá)到3的倍數(shù)(即圖像中的出現(xiàn)完整的角度時(shí),我們該計(jì)算這些角的度數(shù)并將其繪制在圖中)
計(jì)算一個(gè)角的度數(shù)的方式如下(通過三角函數(shù)誘導(dǎo)公式就能得到):
創(chuàng)建一個(gè)函數(shù)來計(jì)算角的度數(shù):
#------------------------------ #定義函數(shù)計(jì)算兩點(diǎn)之間的斜率 #------------------------------ def gradient(pt1, pt2):return (pt2[1] - pt1[1]) / (pt2[0] - pt1[0])#---------------------------- #定義函數(shù)計(jì)算角的度數(shù) #--------------------------- def getAngle(pointsList):pt1, pt2, pt3 = pointsList[-3:] #列表中最后的三個(gè)坐標(biāo)點(diǎn)m1 = gradient(pt1, pt2) #計(jì)算第一個(gè)點(diǎn)和第二個(gè)點(diǎn)之間的斜率m2 = gradient(pt1, pt3) #計(jì)算第一個(gè)點(diǎn)和第三個(gè)點(diǎn)之間的斜率angR = math.atan((m2 - m1) / (1 + (m2 * m1))) #計(jì)算正切值angD = round(math.degrees(angR)) #將弧度轉(zhuǎn)化為角度cv2.putText(img, str(angD), (pt1[0] - 40, pt1[1] - 20), cv2.FONT_HERSHEY_COMPLEX,1.5, (0, 0, 255), 2) #繪制文本5 潤色(繪制線段構(gòu)成角度)?
? ? ? ?其實(shí)到第四步我們的目標(biāo)已經(jīng)達(dá)成了,將前面的代碼整合起來就可以實(shí)現(xiàn)測量角度了,但我們可以在添加一些來繪制線段構(gòu)成角度,代碼如下:
# -------------------#繪制線段構(gòu)成一個(gè)角度# -------------------size = len(pointsList)if size != 0 and size % 3 != 0:cv2.line(img, tuple(pointsList[round((size - 1) / 3) * 3]), (x, y), (0, 0, 255), 2)通過以上的步驟就能實(shí)現(xiàn)本次的角度測量了
由于線段寬度以及一些因素的影響,誤差在所難免,感興趣可以簡單嘗試一下。?
三 整體代碼
整體代碼如下:
?
四 結(jié)束語
? ? ? ?本次項(xiàng)目的實(shí)現(xiàn)較為簡單,大家都可以嘗試一下,原理也是使用高中的知識就能搞懂,簡單的不達(dá)鳥,簡單的一塌糊涂啊!!
總結(jié)
以上是生活随笔為你收集整理的Angle Finder(角度测量)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 科学计算库 Numpy (
- 下一篇: 如何查看numpy库数组的:类型、数据类