我正在使用 OpenCV 對物件的位置進行三角測量,并嘗試創建某種公式來傳遞我獲得的坐標,以拖動拉箭頭,投擲釣魚竿。我嘗試在非常高的程度上使用多項式回歸,但由于回歸無法考慮到 (x,y) 輸出的 (x,y) 輸入,而只是 x 的 x 輸入,所以它仍然不準確輸出等。為了清楚起見,我在下面附上了螢屏截圖,以及我從回歸中獲得的公式。任何幫助/想法/建議將不勝感激,謝謝。
編輯:
xy 坐標從著陸位置組織到箭頭被拉到以使浮子著陸的位置。這是因為釣魚 blob 是輸入,而箭頭拉結束位置來自 blob 位置。我正在使用 OpenCV 來獲取 x,y 坐標,我認為這只是 2d 螢屏的 x,y 坐標系。
分身位置被鎖定,投棒按鈕位于絕對位置(957,748)。
攝像機位置被鎖定,沒有旋轉或移動。
我相信桿的投射角度可能與它被拉到的位置相反 1:1。例如:如果將桿拉到 225 度,它會以 45 度拋投。我不是 100% 肯定,但我認為強度是線性的。我部分使用了線性回歸,因為我對此不確定。沒有影響演員陣容的海拔差異/坡度/風。著陸位置的唯一影響因素是箭頭被拖動到的位置。箭頭不會從側面拖過 180/360 度位置(相對于投射按鈕),如果將其保持在 x 方向,則只會將投射角度鎖定在 x 方向。
xy 資料是通過一個簡單的程式收集的,將滑鼠移動到相同的位置 (957,748) 并拖動箭頭以使用不同的拖動強度/位置來投射桿,以創建某種最適合鑄造通用公式的線竿。包含的 triang_x 和 y 函式是 x 和 y 坐標分別運行以對箭頭的結束拖動坐標進行三角測量。這不能很好地作業,因為匹配 x-to-x 和 y-to-y 不考慮每個公式中的 x 和 y 資料,只是 x-to-x 等。
左欄是釣魚點坐標,右欄是箭頭被拖動到的位置以擊中魚點。
(1133,359) to (890,890)
(858,334) to (886, 900)
(755,579) to (1012,811)
(1013,255) to (933,934)
(1166,469) to (885,855)
(1344,654) to (855,794)
(804,260) to (1024,939)
(1288,287) to (822,918)
(624,422) to (1075,869)
(981,460) to (949,851)
(944,203) to (963,957)
(829,367) to (1005,887)
(1129,259) to (885,932)
(773,219) to (1036,949)
(1052,314) to (919,908)
(958,662) to (955,782)
(1448,361) to (775,906)
(1566,492) to (751,837)
(1275,703) to (859,764)
(1210,280) to (852,926)
(668,513) to (1050,836)
(830,243) to (1011,939)
(688,654) to (1022,792)
(635,437) to (1072,864)
(911,252) to (976,935)
(1499,542) to (785,825)
(793,452) to (1017,860)
(1309,354) to (824,891)
(1383,522) to (817,838)
(1262,712) to (867,758)
(927,225) to (980,983)
(644,360) to (1097,919)
(1307,648) to (862,798)
(1321,296) to (812,913)
(798,212) to (1026,952)
(1315,460) to (836,854)
(700,597) to (1028,809)
(868,573) to (981,811)
(1561,497) to (758,838)
(1172,588) to (896,816)
顯示在函式內執行的機器人操作以及如何使用公式。
coeffs_x = np.float64([
-7.9517089428836911e 005,
4.1678460255861210e 003,
-7.5075555590709371e 000,
4.2001528427460097e-003,
2.3767929866943760e-006,
-4.7841176483548307e-009,
6.1781765539212100e-012,
-5.2769581174002655e-015,
-4.3548777375857698e-019,
2.5342561455214514e-021,
-1.4853535063513160e-024,
1.5268121610772846e-027,
-2.9667978919426497e-031,
-9.5670287721717018e-035,
-2.0270490020866057e-037,
-2.8248895597371365e-040,
-4.6436110892973750e-044,
6.7719507722602512e-047,
7.1944028726480678e-050,
1.2976299392064562e-052,
7.3188205383162127e-056,
-6.3972284918241943e-059,
-4.1991571617797430e-062,
2.5577340340980386e-066,
-4.3382682133956009e-068,
1.5534384486024757e-071,
5.1736875087411699e-075,
7.8137258396620031e-078,
2.6423817496804479e-081,
2.5418438527686641e-084,
-2.8489136942892384e-087,
-2.3969101111450846e-091,
-3.3499890707855620e-094,
-1.4462592756075361e-096,
6.8375394909274851e-100,
-2.4083095685910846e-103,
7.0453288171977301e-106,
-2.8342463921987051e-109
])
triang_x = np.polynomial.Polynomial(coeffs_x)
coeffs_y = np.float64([
2.6215449742035207e 005,
-5.7778572049616614e 003,
5.1995066291482431e 001,
-2.3696608508824663e-001,
5.2377319234985116e-004,
-2.5063316505492962e-007,
-9.2022083686040928e-010,
3.8639053124052189e-013,
2.7895763914453325e-015,
7.3703786336356152e-019,
-1.3411964395287408e-020,
1.5532055573746500e-023,
-6.9719956967963252e-027,
1.9573598517734802e-029,
-3.3847482160483597e-032,
-5.5368209294319872e-035,
7.1463648457003723e-038,
4.6713369979545088e-040,
-7.5070219026265008e-043,
-4.5089676791698693e-047,
-3.2970870269153785e-049,
1.6283636917056585e-051,
-1.4312555782661719e-054,
7.8463441723355399e-058,
1.9439588820918080e-060,
2.1292310369635749e-063,
-1.4191866473449773e-065,
-2.1353539347524828e-070,
2.5876946863828411e-071,
-1.6182477348921458e-074
])
triang_y = np.polynomial.Polynomial(coeffs_y)
def bot_actions(rectangles):
if len(rectangles) > 0:
# finds x,y location of fish
targets = vision.get_click_points(rectangles)
target = wincap.get_screen_position(targets[0])
target_pos = (target[0],target[1])
x1=target[0]
y1 = target[1]
print('1st target at x:{} y:{}'.format(x1,y1))
sleep(2)
# sleeps 2 seconds and finds location again to see if fish stopped moving
targets = vision.get_click_points(rectangles)
target = wincap.get_screen_position(targets[0])
target_pos = (target[0],target[1])
x2 = target[0]
y2 = target[1]
print('2nd target at x:{} y:{}'.format(x2,y2))
xres = abs(x1-x2)
yres = abs(y1-y2)
# determines if stopped within tolerance
if xres yres <= 25:
print('Fish stopped')
# calculates arrow drag position
new_x = triang_x(x2)
new_y = triang_y(y2)
print(new_x,new_y)
# executes arrow drag
pyautogui.moveTo(957,748)
pyautogui.click()
pyautogui.dragTo(new_x,new_y,.5)
sleep(3)
#checks dialogue box to see if fish caught
pixelRGB = ImageGrab.grab().getpixel((811,335))
print(pixelRGB)
if pixelRGB[0] == 255:
print('got em!')
pyautogui.moveTo(1149,480)
pyautogui.click()
elif pixelRGB[0] != 255:
print('didnt get em!')
uj5u.com熱心網友回復:
首先你需要澄清幾件事:
xy
資料_是您想要擊中的物件的位置還是使用特定輸入資料(在這種情況下缺失)時擊中的位置?
在什么坐標系中?你的頭像是什么位置?
視圖是如何定義的?
它是具有 6DOF 的完全 3D 還是僅相對于化身固定(無旋轉或移動)?
你的鑄棒的物理/邏輯是什么
是角度(一還是二),強度?
強度與距離成線性關系嗎?
投擲是否考慮了化身和目標之間的高度差異?
地面高程(坡度)是否起作用?
是否還有其他因素,例如風,桿管等?
您共享了 xy 資料,但您想要關聯或為其制定公式有什么用?這沒有任何意義,您顯然忘記添加類似每個位置的內容是在什么條件下進行的?
我將通過以下方式解決這個問題(在您澄清上述內容之前沒有進一步的細節):
將目標 xy 轉換為與地面對齊的玩家相對坐標系
計算方位角(幾何)
簡單
atan2(y,x)
就可以,但您需要考慮您的坐標系符號。計算仰角和強度(幾何)
應該應用簡單的彈道物理,但取決于游戲的物理或您撰寫的任何用途。
調整額外的東西
你知道例如風可以稍微改變你的角度和力量
如果你有真實的物理和資料,你可以同時做#3、#4。觀點差不多:
我轉換了你的笛卡爾點:
int ava_x=957,ava_y=748; // avatar int data[]= // target(x1,y1) , drag(x0,y0) { 1133,359,890,890, 858,334,886, 900, 755,579,1012,811, 1013,255,933,934, 1166,469,885,855, 1344,654,855,794, 804,260,1024,939, 1288,287,822,918, 624,422,1075,869, 981,460,949,851, 944,203,963,957, 829,367,1005,887, 1129,259,885,932, 773,219,1036,949, 1052,314,919,908, 958,662,955,782, 1448,361,775,906, 1566,492,751,837, 1275,703,859,764, 1210,280,852,926, 668,513,1050,836, 830,243,1011,939, 688,654,1022,792, 635,437,1072,864, 911,252,976,935, 1499,542,785,825, 793,452,1017,860, 1309,354,824,891, 1383,522,817,838, 1262,712,867,758, 927,225,980,983, 644,360,1097,919, 1307,648,862,798, 1321,296,812,913, 798,212,1026,952, 1315,460,836,854, 700,597,1028,809, 868,573,981,811, 1561,497,758,838, 1172,588,896,816, };
進入相對于
ava_x,ava_y
使用atan2
和 2D 距離公式的極坐標,并簡單地列印角度差 180deg 和線條大小之間的比率(即螢屏截圖左側的黃色文本)首先是序數,然后是角度差 [deg],然后是線條長度之間的比率...如您所見,角度差
/-10.6deg
和長度比<2.5,3.6>
可能是由于 OpenCV 發現的不準確以及游戲邏輯本身對釣魚竿鑄件的一些隨機性。如您所見,極坐標最適合此。對于初學者,您可以這樣做:
// wanted target in polar (obtained by CV) x = target_x-ava_x; y = target_y-ava_y; a = atan2(y,x); l = sqrt((x*x) (y*y)); // aiming drag in polar a = 3.1415926535897932384626433832795; // =180 deg l /= 3.0; // "avg" ratio between line sizes // aiming drag in cartesian aim_x = ava_x l*cos(a); aim_y = ava_y l*sin(a);
您可以將其優化為:
aim_x = ava_x - ((target_x-ava_x)/3); aim_y = ava_y - ((target_y-ava_y)/3);
現在為了提高精度,您可以測量依賴性或線比和線大小(它可能不是線性的),對于更大的線,角度差異可能更大......
另請注意,第二次演員表(序數 2)可能是一個錯誤(CV 錯誤地檢測到 x,y),如果您渲染 2 行,您會看到它們不匹配,因此您不應該考慮這一點并將它們從資料集中丟棄。
另請注意,我使用 C 撰寫代碼,因此我的測角學使用弧度(不確定是否適用于 python,如果不是,則需要轉換為度數),方程可能需要對坐標系進行一些額外的調整(否定 y?)