#python #opencv #camera-calibration
Вопрос:
Я пытаюсь откалибровать камеру, используя известные данные с изображения (положения пикселей) и положения в реальном мире.
Вот о чем я знаю:
Камера
focal_length = 3.9
image_height = 3456
image_width = 4608
esl_height = 35
sensor_height = 4.69
sensor_width = 6.26
pixel_size = 1.34/1000
FOV_x = 71.9
FOV_y = 56.7
F_x = image_width /(2 * tan(FOV_x* pi / 360))
F_y = image_height /(2 * tan(FOV_y* pi / 360))
C_x = image_width / 2
C_y = image_height / 2
row1 = [F_x,0,C_x]
row2 = [0,F_y, C_y]
row3 = [0,0,1]
camera_matrix = np.matrix([row1,row2,row3])
что дает:
matrix([[3.17701054e 03, 0.00000000e 00, 2.30400000e 03],
[0.00000000e 00, 3.20254589e 03, 1.72800000e 03],
[0.00000000e 00, 0.00000000e 00, 1.00000000e 00]])
Данные
У меня есть набор данных,содержащий 49 точек, для которых у меня есть обе позиции в реальном мире (x, y) (у меня также есть значения z, но меня действительно интересует только позиция (x,y). Кроме того, у меня есть положения пикселей для всех этих точек на изображении (они являются центрами ограничивающей рамки в определении объекта, которое я выполняю.
id manual.location.x manual.location.y manual.location.z
0 0 32.9878 41.9033 0.215
1 1 32.9878 44.4404 0.215
2 2 32.9878 44.4404 0.215
3 3 32.9878 44.4404 0.565
4 4 32.9878 44.4404 0.565
5 5 32.9878 44.4404 0.565
6 6 32.9878 44.4404 0.565
7 7 32.9878 44.4404 0.565
8 8 32.9878 41.9033 0.753
9 9 32.9878 44.4404 0.779
10 10 32.9878 44.4404 0.779
11 11 32.9878 44.4404 0.779
12 12 32.9878 41.9033 1.024
13 13 32.9878 44.4404 1.024
14 14 32.9878 42.7490 1.100
15 15 32.9878 43.5947 1.100
16 16 32.9878 43.5947 1.100
17 17 32.9878 43.5947 1.100
18 18 32.9878 43.5947 1.100
19 19 32.9878 44.4404 1.231
20 20 32.9878 44.4404 1.231
21 21 32.9878 44.4404 1.231
22 22 32.9878 44.4404 1.231
23 23 32.9878 42.7490 1.320
24 24 32.9878 43.5947 1.412
25 25 32.9878 42.7490 1.412
26 26 32.9878 43.5947 1.412
27 27 32.9878 44.4404 1.412
28 28 32.9878 44.4404 1.458
29 29 32.9878 44.4404 1.458
30 30 32.9878 44.4404 1.458
31 31 32.9878 44.4404 1.458
32 32 32.9878 42.7490 1.620
33 33 32.9878 42.7490 1.620
34 34 32.9878 43.5947 1.620
35 35 32.9878 43.5947 1.620
36 36 32.9878 42.7490 1.620
37 37 32.9878 44.4404 1.651
38 38 32.9878 44.4404 1.651
39 39 32.9878 44.4404 1.651
40 40 32.9878 44.4404 1.651
41 41 32.9878 44.4404 1.651
42 42 32.9878 42.7490 1.850
43 43 32.9878 42.7490 NaN
44 44 32.9878 44.4404 NaN
45 45 32.9878 44.4404 NaN
46 46 32.9878 44.4404 1.850
47 47 32.9878 43.5947 1.850
48 48 32.9878 44.4404 1.850
bbox_center_x bbox_center_y
0 4269.5 2914.0
1 1035.0 2883.5
2 843.5 2880.0
3 1516.5 2529.0
4 1247.5 2527.0
5 1730.0 2525.5
6 987.0 2522.0
7 765.5 2520.0
8 4435.0 2356.5
9 1196.0 2257.0
10 938.5 2255.0
11 704.5 2250.0
12 4547.0 1998.0
13 1291.0 1980.0
14 3681.0 1864.5
15 2394.0 1856.0
16 1931.5 1854.0
17 2043.0 1853.5
18 2043.0 1853.5
19 1620.0 1676.0
20 1267.0 1675.5
21 847.0 1672.5
22 593.5 1669.5
23 3783.5 1452.0
24 1931.5 1446.5
25 3346.5 1443.5
26 2878.0 1443.0
27 1632.0 1350.0
28 1409.0 1346.5
29 945.0 1339.5
30 727.0 1334.0
31 534.5 1332.0
32 4349.0 1109.0
33 3859.0 1101.0
34 1920.5 1097.5
35 2878.0 1090.5
36 3364.0 1087.0
37 1460.5 1037.0
38 1290.5 1036.0
39 1065.5 1034.0
40 748.0 1032.5
41 473.0 1029.0
42 4262.0 726.0
43 3683.5 713.0
44 1375.0 710.0
45 1094.5 708.0
46 850.0 705.0
47 3103.5 702.5
48 375.5 701.5
To make things easier, I am willing to let the z-coordinate ( manual.location.z
) of realworld positions be 0.
Now, I trried the following thing using cv.calibrateCamera
on data with z-coordinate = 0. So, I did the following:
manual.location.x manual.location.y manual.location.z bbox_center_x
0 32.9878 41.9033 0 4269.5
1 32.9878 44.4404 0 1035.0
2 32.9878 44.4404 0 843.5
3 32.9878 44.4404 0 1516.5
4 32.9878 44.4404 0 1247.5
5 32.9878 44.4404 0 1730.0
6 32.9878 44.4404 0 987.0
7 32.9878 44.4404 0 765.5
8 32.9878 41.9033 0 4435.0
9 32.9878 44.4404 0 1196.0
10 32.9878 44.4404 0 938.5
11 32.9878 44.4404 0 704.5
12 32.9878 41.9033 0 4547.0
13 32.9878 44.4404 0 1291.0
14 32.9878 42.7490 0 3681.0
15 32.9878 43.5947 0 2394.0
16 32.9878 43.5947 0 1931.5
17 32.9878 43.5947 0 2043.0
18 32.9878 43.5947 0 2043.0
19 32.9878 44.4404 0 1620.0
20 32.9878 44.4404 0 1267.0
21 32.9878 44.4404 0 847.0
22 32.9878 44.4404 0 593.5
23 32.9878 42.7490 0 3783.5
24 32.9878 43.5947 0 1931.5
25 32.9878 42.7490 0 3346.5
26 32.9878 43.5947 0 2878.0
27 32.9878 44.4404 0 1632.0
28 32.9878 44.4404 0 1409.0
29 32.9878 44.4404 0 945.0
30 32.9878 44.4404 0 727.0
31 32.9878 44.4404 0 534.5
32 32.9878 42.7490 0 4349.0
33 32.9878 42.7490 0 3859.0
34 32.9878 43.5947 0 1920.5
35 32.9878 43.5947 0 2878.0
36 32.9878 42.7490 0 3364.0
37 32.9878 44.4404 0 1460.5
38 32.9878 44.4404 0 1290.5
39 32.9878 44.4404 0 1065.5
40 32.9878 44.4404 0 748.0
41 32.9878 44.4404 0 473.0
42 32.9878 42.7490 0 4262.0
46 32.9878 44.4404 0 850.0
47 32.9878 43.5947 0 3103.5
48 32.9878 44.4404 0 375.5
bbox_center_y
0 2914.0
1 2883.5
2 2880.0
3 2529.0
4 2527.0
5 2525.5
6 2522.0
7 2520.0
8 2356.5
9 2257.0
10 2255.0
11 2250.0
12 1998.0
13 1980.0
14 1864.5
15 1856.0
16 1854.0
17 1853.5
18 1853.5
19 1676.0
20 1675.5
21 1672.5
22 1669.5
23 1452.0
24 1446.5
25 1443.5
26 1443.0
27 1350.0
28 1346.5
29 1339.5
30 1334.0
31 1332.0
32 1109.0
33 1101.0
34 1097.5
35 1090.5
36 1087.0
37 1037.0
38 1036.0
39 1034.0
40 1032.5
41 1029.0
42 726.0
46 705.0
47 702.5
48 701.5
and prepared the data for calibration of the cammera:
data = df_p.to_numpy()
pts3d = data[:, 0:3]
pts2d = data[:, 3:5]
pts3d = pts3d.reshape(1,-1, 3)
pts2d = pts2d.reshape(1,-1, 2)
image_height = 3456
image_width = 4608
w = image_width
h = image_height
pts3d = pts3d.astype('float32')
pts2d = pts2d.astype('float32')
size = (w,h)
и, наконец,:
image_height = 3456
image_width = 4608
tvec = np.array([0, 0, 0], dtype=np.float32) #Camera is static
rvec = np.array([0, 0, 0], dtype=np.float32) #Camera is static
distCoeffs =np.array([0,0,0,0,0], dtype=np.float32)
cv.calibrateCamera([pts3d], [pts2d],size,camera_matrix,None,None,None,None,flags=cv.CALIB_FIX_K1 cv.CALIB_FIX_K2 cv.CALIB_FIX_K3 cv.CALIB_FIX_K4 cv.CALIB_FIX_K5)
Но это возвращается:
---------------------------------------------------------------------------
error Traceback (most recent call last)
<ipython-input-374-406d179adbf6> in <module>
17 distCoeffs =np.array([0, 0, 0,0,0], dtype=np.float32)
18
---> 19 cv.calibrateCamera([pts3d], [pts2d],size,camera_matrix,None,None,None,None,flags=cv.CALIB_FIX_K1 cv.CALIB_FIX_K2 cv.CALIB_FIX_K3 cv.CALIB_FIX_K4 cv.CALIB_FIX_K5)
error: OpenCV(4.5.3) :-1: error: (-5:Bad argument) in function 'calibrateCamera'
> Overload resolution failed:
> - argument for calibrateCamera() given by name ('flags') and position (8)
> - argument for calibrateCamera() given by name ('flags') and position (8)
Даже это:
cv.calibrateCamera([pts3d], [pts2d],size,camera_matrix,distCoeffs,None,None,None,flags=cv.CALIB_FIX_K1 cv.CALIB_FIX_K2 cv.CALIB_FIX_K3 cv.CALIB_FIX_K4 cv.CALIB_FIX_K5)
возвращает ту же ошибку.
Я понятия не имею, что я делаю не так.
Чего я хочу? Я хочу иметь возможность получить коэффициенты искажения для моей камеры. Таким образом или любым другим способом, который дает мне удовлетворительные результаты.
Комментарии:
1.
CALIB_FIX_*
означает, что названные коэффициенты искажения не изменяются в процессе калибровки. Таким образом, в настоящее время вы предоставляете вектор искажения с 5 элементами. Пожалуйста, убедитесь, что при калибровке используется 5 коэффициентов, я думаю, что их может быть больше, например, 7 или sth. Если вы хотите исправить 5 из них, вам все равно придется указать все 7 (или любое другое необходимое число). И вы уверены, что флаги объединяются путем сложения? Можете ли вы попробовать побитовую операцию И? добавление такое же, как и побитовое, И только для одного горячего кодирования.
Ответ №1:
Я предполагаю, что это как-то связано с флагами, используемыми в:
cv.calibrateCamera([pts3d], [pts2d],size,camera_matrix,distCoeffs,None,None,None,flags=cv.CALIB_FIX_K1 cv.CALIB_FIX_K2 cv.CALIB_FIX_K3 cv.CALIB_FIX_K4 cv.CALIB_FIX_K5)
Если вы измените его на:
cv.calibrateCamera([pts3d], [pts2d],size,camera_matrix,distCoeffs,None,None,None,flags=cv.CALIB_USE_INTRINSIC_GUESS)
или просто оставьте флаги стандартным способом, и это больше не приведет к этой ошибке, чем к несоответствию между camera_matrix
используемыми флагами и флагами.
Может быть, вам тоже нужно добавить cv.CALIB_FIX_K6
?
Вы можете ознакомиться с подробным описанием здесь: https://docs.opencv.org/3.4/d9/d0c/group__calib3d.html#gga7b31a379c097fb87997d28266762f12fab4ac5ea2d2f2636ca8a384a5b717dd35
Комментарии:
1. Вам удалось дать мне что-то, что не возвращает ошибку.
rms, CaMt, distCoefficients, rvec, tvec = cv.calibrateCamera([pts3d], [pts2d],size,camera_matrix,None,None,None,flags=cv.CALIB_USE_INTRINSIC_GUESS)
возвращает новую внутреннюю матрицу камеры, коэффициенты искажения иtvec´´´ as well as ´´´rvec
. Я подожду несколько дней, прежде чем определенно приму ваш ответ, потому что я предпочел бы сохранить оригинальную матрицу камеры.