溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python+OpenCV如何實(shí)現(xiàn)角度測(cè)量

發(fā)布時(shí)間:2022-03-05 14:02:19 來(lái)源:億速云 閱讀:547 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要為大家展示了“Python+OpenCV如何實(shí)現(xiàn)角度測(cè)量”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Python+OpenCV如何實(shí)現(xiàn)角度測(cè)量”這篇文章吧。

最終實(shí)現(xiàn)效果:在圖片上用鼠標(biāo)確認(rèn)三點(diǎn),程序?qū)?huì)顯示由此三點(diǎn)確定的角度,如下圖所示。

Python+OpenCV如何實(shí)現(xiàn)角度測(cè)量

1、鼠標(biāo)選點(diǎn)

# -*- coding: utf-8 -*-
 
import cv2
 
path = "picture_mqa\\angle_measure.bmp"
img = cv2.imread(path)
pointsList = []
 
def mousePoints(event,x,y,flags,params):
    if event  == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(img,(x,y),5,(0,0,255),cv2.FILLED)
        print(x,y)
 
while True:
    cv2.imshow('Image', img)
    cv2.setMouseCallback('Image',mousePoints)
    
    key_scan = cv2.waitKey(1) & 0xff 
    
    if key_scan == ord("q"):
        pointsList = []
        img = cv2.imread(path)
    elif key_scan == ord("s"):
        break
    
cv2.destroyAllWindows()

while循環(huán)內(nèi)cv2.setMouseCallback('Image',mousePoints)為鼠標(biāo)中斷觸發(fā)事件的開啟函數(shù),作用是當(dāng)在Image圖片上鼠標(biāo)觸發(fā)中斷事件時(shí),程序跳轉(zhuǎn)到mousePoints()中斷服務(wù)函數(shù)內(nèi),并給mousePoints()的五個(gè)入口參數(shù)event,x,y,flags,params賦值。其中, event是cv2_EVENT_* (MouseEventTypes)類型的變量,為鼠標(biāo)觸發(fā)中斷事件的類型;x和y為鼠標(biāo)觸發(fā)中斷事件時(shí)在image圖像的橫縱坐標(biāo);flags是cv2_EVENT_FLAG_* (MouseEventFlags)類型的變量,為特殊中斷事件的標(biāo)志位;param是用戶自定義的參數(shù)。本文的程序中使用 EVENT_LBUTTONDOW#左鍵點(diǎn)擊觸發(fā)事件,當(dāng)鼠標(biāo)左鍵點(diǎn)擊時(shí),標(biāo)注該點(diǎn)并記錄其坐標(biāo)。

event的賦值:

  • EVENT_MOUSEMOVE             #滑動(dòng)

  • EVENT_LBUTTONDOWN         #左鍵點(diǎn)擊

  • EVENT_RBUTTONDOWN        #右鍵點(diǎn)擊

  • EVENT_MBUTTONDOWN       #中鍵點(diǎn)擊

  • EVENT_LBUTTONUP               #左鍵放開

  • EVENT_RBUTTONUP              #右鍵放開

  • EVENT_MBUTTONUP              #中鍵放開

  • EVENT_LBUTTONDBLCLK      #左鍵雙擊

  • EVENT_RBUTTONDBLCLK     #右鍵雙擊

  • EVENT_MBUTTONDBLCLK    #中鍵雙擊

2、角度計(jì)算 

由1可以得到鼠標(biāo)點(diǎn)擊位置處的坐標(biāo),我們將其放入pointList列表內(nèi)。當(dāng)列表內(nèi)的坐標(biāo)數(shù)目為3的倍數(shù)時(shí)調(diào)用getAngle()函數(shù),計(jì)算出三點(diǎn)確定的兩條直線的夾角。

def gradient(pt1,pt2):
    return ((pt2[1]-pt1[1])/(pt2[0]-pt1[0]))
 
def getAngle(pointsList):
    pt1,pt2,pt3 = pointsList[-3:] 
    m1 = gradient(pt1, pt2)
    m2 = gradient(pt1, pt3)
    angR = abs(math.atan((m2-m1)/(1+m2*m1)))
    angD = round(math.degrees(angR))
    
    cv2.putText(img,str(angD),(pt1[0]-40,pt1[1]-20),cv2.FONT_HERSHEY_COMPLEX,
                1.5,(0,0,255))

由直線的兩點(diǎn)式方程可得直線的傾斜角為angle = arctan(y2-y1,x2-x1),則兩條直線的夾角為angle0 =angle1-angle2 = arctan(y2-y1,x2-x1) - arctan(y2-y3,x2-x3)。以上函數(shù)便可根據(jù)三點(diǎn)的坐標(biāo)值求其形成夾角的角度。

3、完整程序

# -*- coding: utf-8 -*-
'''
測(cè)量鼠標(biāo)點(diǎn)擊過(guò)的三點(diǎn)形成的角度
'''
import cv2
import math
 
path = "picture_mqa\\angle_measure.bmp"  #圖片路徑
img = cv2.imread(path)
pointsList = []
 
#鼠標(biāo)中斷觸發(fā)函數(shù),將鼠標(biāo)觸發(fā)事件位置處描點(diǎn)并將該點(diǎn)的坐標(biāo)值紀(jì)錄入pointList列表內(nèi)
#連接相鄰三點(diǎn)使其形成一個(gè)夾角
def mousePoints(event,x,y,flags,params):
    if event  ==cv2.EVENT_LBUTTONDOWN:
        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))
        cv2.circle(img,(x,y),5,(0,0,255),cv2.FILLED)
        pointsList.append([x,y])
 
#由兩點(diǎn)的坐標(biāo)值計(jì)算兩點(diǎn)所在直線的斜率        
def gradient(pt1,pt2):
    return ((pt2[1]-pt1[1])/(pt2[0]-pt1[0]))
 
#根據(jù)相鄰的三點(diǎn)計(jì)算出其形成夾角的角度值
def getAngle(pointsList):
    pt1,pt2,pt3 = pointsList[-3:] 
    m1 = gradient(pt1, pt2)
    m2 = gradient(pt1, pt3)
    angR = abs(math.atan((m2-m1)/(1+m2*m1)))
    angD = round(math.degrees(angR))
    
    cv2.putText(img,str(angD),(pt1[0]-40,pt1[1]-20),cv2.FONT_HERSHEY_COMPLEX,
                1.5,(0,0,255))       
 
 
while True:
    cv2.imshow('Image', img) #圖片顯示
    cv2.setMouseCallback('Image',mousePoints) #鼠標(biāo)觸發(fā)事件開啟
    
    if len(pointsList) % 3 ==0 and len(pointsList)!=0: #鼠標(biāo)每觸發(fā)中斷3次計(jì)算一次其形式夾角的角度值
        getAngle(pointsList)
    
    key_scan = cv2.waitKey(1) & 0xff #鍵盤掃描
    if key_scan == ord("q"):  #輸入'q'時(shí)圖片刷新
        pointsList = []
        img = cv2.imread(path)
        
    elif key_scan == ord("s"): #輸入's'時(shí)退出程序
        break
    
cv2.destroyAllWindows()

以上是“Python+OpenCV如何實(shí)現(xiàn)角度測(cè)量”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI