我檢測到了 ArUco 標記并估計了姿勢。見下圖。但是,我得到的 Xt(X 翻譯)是一個正值。根據drawAxis函式,正方向遠離影像中心。所以我認為它應該是一個負值。為什么我變得積極了。
我的相機距離成像表面大約 120 毫米。但我得到的 Zt(Z 平移)在 650 毫米的范圍內。姿態估計是否給出了標記相對于物理相機或影像平面中心的姿態?我不明白為什么Zt這么高。
我在改變的同時不斷地測量 Pose Z,得到 roll、pitch、yaw。我注意到滾動(旋轉 wrt 凸輪 X 軸)的符號來回改變幅度變化 166-178,但 Xt 的符號沒有隨著滾動符號的變化而改變。關于它為什么會這樣的任何想法?有什么建議可以獲得更一致的資料嗎?
image=cv.imread(fname)
arucoDict = cv.aruco.Dictionary_get(cv.aruco.DICT_4X4_1000)
arucoParams = cv.aruco.DetectorParameters_create()
(corners, ids, rejected) = cv.aruco.detectMarkers(image, arucoDict,
parameters=arucoParams)
print(corners, ids, rejected)
if len(corners) > 0:
# flatten the ArUco IDs list
ids = ids.flatten()
# loop over the detected ArUCo corners
#for (markerCorner, markerID) in zip(corners, ids):
#(markerCorner, markerID)=(corners, ids)
# extract the marker corners (which are always returned in
# top-left, top-right, bottom-right, and bottom-left order)
#corners = corners.reshape((4, 2))
(topLeft, topRight, bottomRight, bottomLeft) = corners[0][0][0],corners[0][0][1],corners[0][0][2],corners[0][0][3]
# convert each of the (x, y)-coordinate pairs to integers
topRight = (int(topRight[0]), int(topRight[1]))
bottomRight = (int(bottomRight[0]), int(bottomRight[1]))
bottomLeft = (int(bottomLeft[0]), int(bottomLeft[1]))
topLeft = (int(topLeft[0]), int(topLeft[1]))
# draw the bounding box of the ArUCo detection
cv.line(image, topLeft, topRight, (0, 255, 0), 2)
cv.line(image, topRight, bottomRight, (0, 255, 0), 2)
cv.line(image, bottomRight, bottomLeft, (0, 255, 0), 2)
cv.line(image, bottomLeft, topLeft, (0, 255, 0), 2)
# compute and draw the center (x, y)-coordinates of the ArUco
# marker
cX = int((topLeft[0] bottomRight[0]) / 2.0)
cY = int((topLeft[1] bottomRight[1]) / 2.0)
cv.circle(image, (cX, cY), 4, (0, 0, 255), -1)
if topLeft[1]!=topRight[1] or topLeft[0]!=bottomLeft[0]:
rot1=np.degrees(np.arctan((topLeft[0]-bottomLeft[0])/(bottomLeft[1]-topLeft[1])))
rot2=np.degrees(np.arctan((topRight[1]-topLeft[1])/(topRight[0]-topLeft[0])))
rot=(np.round(rot1,3) np.round(rot2,3))/2
print(rot1,rot2,rot)
else:
rot=0
# draw the ArUco marker ID on the image
rotS=",rotation:" str(np.round(rot,3))
cv.putText(image, ("position: " str(cX) "," str(cY)),
(100, topLeft[1] - 15), cv.FONT_HERSHEY_SIMPLEX,0.5, (255, 0, 80), 2)
cv.putText(image, rotS,
(400, topLeft[1] -15), cv.FONT_HERSHEY_SIMPLEX,0.5, (255, 0, 80), 2)
print("[INFO] ArUco marker ID: {}".format(ids))
d=np.round((math.dist(topLeft,bottomRight) math.dist(topRight,bottomLeft))/2,3)
# Get the rotation and translation vectors
rvecs, tvecs, obj_points = cv.aruco.estimatePoseSingleMarkers(corners,aruco_marker_side_length,mtx,dst)
# Print the pose for the ArUco marker
# The pose of the marker is with respect to the camera lens frame.
# Imagine you are looking through the camera viewfinder,
# the camera lens frame's:
# x-axis points to the right
# y-axis points straight down towards your toes
# z-axis points straight ahead away from your eye, out of the camera
#for i, marker_id in enumerate(marker_ids):
# Store the translation (i.e. position) information
transform_translation_x = tvecs[0][0][0]
transform_translation_y = tvecs[0][0][1]
transform_translation_z = tvecs[0][0][2]
# Store the rotation information
rotation_matrix = np.eye(4)
rotation_matrix[0:3, 0:3] = cv.Rodrigues(np.array(rvecs[0]))[0]
r = R.from_matrix(rotation_matrix[0:3, 0:3])
quat = r.as_quat()
# Quaternion format
transform_rotation_x = quat[0]
transform_rotation_y = quat[1]
transform_rotation_z = quat[2]
transform_rotation_w = quat[3]
# Euler angle format in radians
roll_x, pitch_y, yaw_z = euler_from_quaternion(transform_rotation_x,transform_rotation_y,transform_rotation_z,transform_rotation_w)
roll_x = math.degrees(roll_x)
pitch_y = math.degrees(pitch_y)
yaw_z = math.degrees(yaw_z)

uj5u.com熱心網友回復:
不檢查所有代碼(看起來大致沒問題),一些關于 OpenCV 和 aruco 的基礎知識:
兩者都使用右手坐標系。拇指 X,索引 Y,中間 Z。
OpenCV 使用 X 向右,Y 向下,Z 遠,用于螢屏/相機幀。螢屏和圖片的來源是左上角。對于相機,原點是針孔模型的中心,也就是光圈的中心。我無法評論鏡頭或鏡頭系統。假設鏡頭中心是原點。這可能已經足夠接近了。
如果標記平放在桌子上,Aruco 使用 X 向右、Y 遠、Z 向上。原點位于標記的中心。標記的左上角被認為是“第一個”角。
可以認為標記具有自己的坐標系/框架。
rvec 和 tvec 給出的位姿是相機幀中標記的位姿。這意味著np.linalg.norm(tvec)為您提供從相機到標記中心的直接距離。tvec 的 Z 只是平行于光軸的分量。
如果標記位于圖片的右半部分(“一半”由相機矩陣的 cx,cy 定義),您會期望 tvec 的 X 增長。下半部分,Y 為正/增長。
相反,該轉換將標記區域坐標轉換為相機區域坐標。嘗試轉換一些標記區域點,例如原點或軸上的點。我相信這cv::transform會有所幫助。使用 OpenCVprojectPoints將 3D 空間點映射到 2D 影像點,然后您可以繪制標記的軸,或在其頂部的立方體,或任何您喜歡的東西。
假設標記筆直立并正對著相機。當您考慮標記和相機在空間(“世界”空間)中的幀三元組時,兩者都是 X“正確”,但一個的 Y 和 Z 與另一個的 Y 和 Z 相反,所以你會期望看到一個繞 X 軸旋轉半圈(旋轉 Z 和 Y)。
你可以想象轉換是這樣發生的:
- 最初,相機通過標記從標記的背面看向世界。相機將“倒置”。相機看到標記空間。
- 姿勢的旋轉組件圍繞相機的原點旋轉整個標記區域世界。從世界框架(參考點)看,相機旋轉,進入你會發現自然的姿態。
- 姿勢的平移將標記的世界移到相機前面(Z 為正),或者等效地,相機遠離標記。
如果您得到難以置信的值,請檢查aruco_marker_side_length相機矩陣。對于典型解析度(VGA-4k)和視場(60-80 度),f 約為 500-3000。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/425474.html
上一篇:檢測影像是否為負
