天天看點

python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位

轉載自:https://www.it610.com/article/1291934151255072768.htm

python下使用aruco标記進進行三維姿勢估計

  • 視覺機器人
  • python3
  • aruco
  • python
  • opencv
  • 計算機視覺
  • aruco
python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位

ArUco标記

python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位

首先什麼是aruco标記呢?

aruco标記是可用于錄影機姿态估計的二進制方形基準标記。它的主要優點是檢測簡單、快速,并且具有很強的魯棒性。ArUco 标記是由寬黑色邊框和确定其辨別符(id)的内部二進制矩陣組成的正方形标記。aruco标記的黑色邊框有助于其在圖像中的快速檢測,内部二進制編碼用于識别标記和提供錯誤檢測和糾正。aruco标記尺寸的大小決定内部矩陣的大小,例如尺寸為 4x4 的标記由 16 位二進制數組成。

通俗地說,aruco标記其實就是一種編碼,就和我們日常生活中的二維碼是相似的,隻不過由于編碼方式的不同,導緻它們存儲資訊的方式、容量等等有所差異,是以在應用層次上也會有所不同。由于單個aruco标記就可以提供足夠的對應關系,例如有四個明顯的角點及内部的二進制編碼,是以aruco标記被廣泛用來增加從二維世界映射到三維世界時的資訊量,便于發現二維世界與三維世界之間的投影關系,進而實作姿态估計、相機矯正等等應用。

OpenCV中的ArUco子產品包括了對aruco标記的建立和檢測,以及将aruco标記用于姿勢估計和相機矯正等應用的相關API,同時還提供了标記闆等等。本次筆記中主要先整理aruco标記的建立與檢測。

首先我們建立aruco标記時,需要先指定一個字典,這個字典表示的是建立出來的aruco标記具有怎樣的尺寸、怎樣的編碼等等内容,我們使用APIgetPredefinedDictionary()來聲明我們使用的字典。在OpenCV中,提供了多種預定義字典,我們可以通過PREDEFINED_DICTIONARY_NAME來檢視有哪些預定義字典。而且字典名稱表示了該字典的aruco标記數量和尺寸,例如DICT_7X7_50表示一個包含了50種7x7位标記的字典。

ArUco标記生成器

線上aruco标記生成器:http://aruco.dgut.top/

(備用):https://chev.me/arucogen/

python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位

在OpenCV中生成ArUco标記

opencv-python生成aruco标記

确定好我們需要的字典後,就可以通過API

drawMarker()

來繪制出aruco标記,其參數含義如下:

import cv2
import numpy as np
# 生成aruco标記
# 加載預定義的字典
dictionary = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)

# 生成标記
markerImage = np.zeros((200, 200), dtype=np.uint8)
markerImage = cv2.aruco.drawMarker(dictionary, 22, 200, markerImage, 1)
cv2.imwrite("marker22.png", markerImage)
           
opencv的aruco子產品共有25個預定義的标記詞典。每個詞典中所有的Aruco标記均包含相同數量的塊或位(例如4×4、5×5、6×6或7×7),且每個詞典中Aruco标記的數量固定(例如50、100、250或1000)。

cv2.aruco.Dictionary_get()

函數會加載

cv2.aruco.DICT_6X6_250

包含250個标記的字典,其中每個标記都是6×6位二進制模式

cv2.aruco.drawMarker(dictionary, 22, 200, markerImage, 1)

中的第二個參數

22

是aruco的标記id(0~249),第三個參數決定生成的标記的大小,在上面的示例中,它将生成

200×200

像素的圖像,第四個參數表示将要存儲aruco标記的對象(上面的

markerImage

),最後,第五個參數是邊界寬度參數,它決定應将多少位(塊)作為邊界添加到生成的二進制圖案中。

執行後将會生成這樣的标記:标記id分别是

22

python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位

展開所支援的标記字典

展開檢視的内容;
DICT_4X4_50 
Python: cv.aruco.DICT_4X4_50
DICT_4X4_100 
Python: cv.aruco.DICT_4X4_100
DICT_4X4_250 
Python: cv.aruco.DICT_4X4_250
DICT_4X4_1000 
Python: cv.aruco.DICT_4X4_1000
DICT_5X5_50 
Python: cv.aruco.DICT_5X5_50
DICT_5X5_100 
Python: cv.aruco.DICT_5X5_100
DICT_5X5_250 
Python: cv.aruco.DICT_5X5_250
DICT_5X5_1000 
Python: cv.aruco.DICT_5X5_1000
DICT_6X6_50 
Python: cv.aruco.DICT_6X6_50
DICT_6X6_100 
Python: cv.aruco.DICT_6X6_100
DICT_6X6_250 
Python: cv.aruco.DICT_6X6_250
DICT_6X6_1000 
Python: cv.aruco.DICT_6X6_1000
DICT_7X7_50 
Python: cv.aruco.DICT_7X7_50
DICT_7X7_100 
Python: cv.aruco.DICT_7X7_100
DICT_7X7_250 
Python: cv.aruco.DICT_7X7_250
DICT_7X7_1000 
Python: cv.aruco.DICT_7X7_1000
DICT_ARUCO_ORIGINAL 
Python: cv.aruco.DICT_ARUCO_ORIGINAL
DICT_APRILTAG_16h5 
Python: cv.aruco.DICT_APRILTAG_16h5
4x4 bits, minimum hamming distance between any two codes = 5, 30 codes
           

批量生成aruco标記

import cv2
import numpy as np
# 生成aruco标記
# 加載預定義的字典
dictionary = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)

# 生成标記
markerImage = np.zeros((200, 200), dtype=np.uint8)
for i in range(30):
    markerImage = cv2.aruco.drawMarker(dictionary, i, 200, markerImage, 1);

    firename='armark/'+str(i)+'.png'
    cv2.imwrite(firename, markerImage);
           

在armark檔案夾下會生成一系列的6*6

aruco标記

python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位

Aruco标記的檢測和定位

靜态檢測

在環境中圖像檢測Aruco标記,環境中有7個标記

python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位
import numpy as np
import time
import cv2
import cv2.aruco as aruco
#讀取圖檔
frame=cv2.imread('IMG_3739.jpg')
#調整圖檔大小
frame=cv2.resize(frame,None,fx=0.2,fy=0.2,interpolation=cv2.INTER_CUBIC)
#灰階話
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#設定預定義的字典
aruco_dict = aruco.Dictionary_get(aruco.DICT_6X6_250)
#使用預設值初始化檢測器參數
parameters =  aruco.DetectorParameters_create()
#使用aruco.detectMarkers()函數可以檢測到marker,傳回ID和标志闆的4個角點坐标
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray,aruco_dict,parameters=parameters)
#畫出标志位置
aruco.drawDetectedMarkers(frame, corners,ids)


cv2.imshow("frame",frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
           
對于每次成功檢測到标記,将按從左上,右上,右下和左下的順序檢測标記的四個角點。在C ++中,将這4個檢測到的角點存儲為點矢量,并将圖像中的多個标記一起存儲在點矢量容器中。在Python中,它們存儲為Numpy 數組。

detectMarkers()

函數用于檢測和确定标記角點的位置。
  • 第一個參數

    image

    是帶有标記的場景圖像。
  • 第二個參數

    dictionary

    是用于生成标記的字典。成功檢測到的标記将存儲在markerCorners中,其ID存儲在markerIds中。先前初始化的DetectorParameters對象作為傳遞參數。
  • 第三個參數

    parameters

    DetectionParameters

    類的對象,該對象包括在檢測過程中可以自定義的所有參數;
  • 傳回參數

    corners

    :檢測到的aruco标記的角點清單,對于每個标記,其四個角點均按其原始順序傳回(從右上角開始順時針旋轉),第一個角是右上角,然後是右下角,左下角和左上角。
  • 傳回

    ids

    :檢測到的每個标記的 id,需要注意的是第三個參數和第四個參數具有相同的大小;
  • 傳回參數

    rejectedImgPoints

    :抛棄的候選标記清單,即檢測到的、但未提供有效編碼的正方形。每個候選标記也由其四個角定義,其格式與第三個參數相同,該參數若無特殊要求可以省略。
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray,aruco_dict,parameters=parameters)
           

當我們檢測到aruco标簽之後,為了友善觀察,我們需要進行可視化操作,把标簽标記出來:使用

drawDetectedMarkers()

這個API來繪制檢測到的aruco标記,其參數含義如下:

  • 參數image: 是将繪制标記的輸入 / 輸出圖像(通常就是檢測到标記的圖像)
  • 參數corners:檢測到的aruco标記的角點清單
  • 參數ids:檢測到的每個标記對應到其所屬字典中的id,可選(如果未提供)不會繪制ID。
  • 參數borderColor:繪制标記外框的顔色,其餘顔色(文本顔色和第一個角顔色)将基于該顔色進行計算,以提高可視化效果。
  • 無傳回值
aruco.drawDetectedMarkers(image, corners,ids,borderColor)
           

效果示範:

python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位
python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位
python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位
python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位

動态檢測

利用攝像頭進行一個實時動态監測aruco标記并且估計姿勢,攝像頭的内參需要提前标定,如何标定請看我另一篇文章

import numpy as np
import time
import cv2
import cv2.aruco as aruco



# mtx = np.array([
#         [2946.48,       0, 1980.53],
#         [      0, 2945.41, 1129.25],
#         [      0,       0,       1],
#         ])
# #我的手機拍棋盤的時候圖檔大小是 4000 x 2250
# #ip攝像頭拍視訊的時候設定的是 1920 x 1080,長寬比是一樣的,
# #ip攝像頭設定分辨率的時候注意一下
#
#
# dist = np.array( [0.226317, -1.21478, 0.00170689, -0.000334551, 1.9892] )


#相機糾正參數

# dist=np.array(([[-0.51328742,  0.33232725 , 0.01683581 ,-0.00078608, -0.1159959]]))
#
# mtx=np.array([[464.73554153, 0.00000000e+00 ,323.989155],
#  [  0.,         476.72971528 ,210.92028],
#  [  0.,           0.,           1.        ]])
dist=np.array(([[-0.58650416 , 0.59103816, -0.00443272 , 0.00357844 ,-0.27203275]]))
newcameramtx=np.array([[189.076828   ,  0.    ,     361.20126638]
 ,[  0 ,2.01627296e+04 ,4.52759577e+02]
 ,[0, 0, 1]])
mtx=np.array([[398.12724231  , 0.      ,   304.35638757],
 [  0.       ,  345.38259888, 282.49861858],
 [  0.,           0.,           1.        ]])



cap = cv2.VideoCapture(0)


font = cv2.FONT_HERSHEY_SIMPLEX #font for displaying text (below)

#num = 0
while True:
    ret, frame = cap.read()
    h1, w1 = frame.shape[:2]
    # 讀取攝像頭畫面
    # 糾正畸變
    newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (h1, w1), 0, (h1, w1))
    dst1 = cv2.undistort(frame, mtx, dist, None, newcameramtx)
    x, y, w1, h1 = roi
    dst1 = dst1[y:y + h1, x:x + w1]
    frame=dst1


    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    aruco_dict = aruco.Dictionary_get(aruco.DICT_6X6_250)
    parameters =  aruco.DetectorParameters_create()
    dst1 = cv2.undistort(frame, mtx, dist, None, newcameramtx)
    '''
    detectMarkers(...)
        detectMarkers(image, dictionary[, corners[, ids[, parameters[, rejectedI
        mgPoints]]]]) -> corners, ids, rejectedImgPoints
    '''

    #使用aruco.detectMarkers()函數可以檢測到marker,傳回ID和标志闆的4個角點坐标
    corners, ids, rejectedImgPoints = aruco.detectMarkers(gray,aruco_dict,parameters=parameters)

#    如果找不打id
    if ids is not None:

        rvec, tvec, _ = aruco.estimatePoseSingleMarkers(corners, 0.05, mtx, dist)
        # 估計每個标記的姿态并傳回值rvet和tvec ---不同
        # from camera coeficcients
        (rvec-tvec).any() # get rid of that nasty numpy value array error

#        aruco.drawAxis(frame, mtx, dist, rvec, tvec, 0.1) #繪制軸
#        aruco.drawDetectedMarkers(frame, corners) #在标記周圍畫一個正方形

        for i in range(rvec.shape[0]):
            aruco.drawAxis(frame, mtx, dist, rvec[i, :, :], tvec[i, :, :], 0.03)
            aruco.drawDetectedMarkers(frame, corners)
        ###### DRAW ID #####
        cv2.putText(frame, "Id: " + str(ids), (0,64), font, 1, (0,255,0),2,cv2.LINE_AA)


    else:
        ##### DRAW "NO IDS" #####
        cv2.putText(frame, "No Ids", (0,64), font, 1, (0,255,0),2,cv2.LINE_AA)


    # 顯示結果架構
    cv2.imshow("frame",frame)

    key = cv2.waitKey(1)

    if key == 27:         # 按esc鍵退出
        print('esc break...')
        cap.release()
        cv2.destroyAllWindows()
        break

    if key == ord(' '):   # 按空格鍵儲存
#        num = num + 1
#        filename = "frames_%s.jpg" % num  # 儲存一張圖像
        filename = str(time.time())[:10] + ".jpg"
        cv2.imwrite(filename, frame)
           

效果

python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位
python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位
python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位
python下使用aruco标記進進行三維姿勢估計(轉載)python下使用aruco标記進進行三維姿勢估計ArUco标記ArUco标記生成器在OpenCV中生成ArUco标記Aruco标記的檢測和定位

部落格位址:https://blog.dgut.top/2020/07/15/python-aruco/

本文參考:

1.https://blog.csdn.net/sinat_17456165/article/details/105649131

2.https://www.learnopencv.com/augmented-reality-using-aruco-markers-in-opencv-c-python/

繼續閱讀