OpenCV - инвертируются ли коэффициенты искажения линз для баллов проекта?

Доброго времени суток ребята,

Я пытаюсь имитировать и изображать с искажением тубуса объектива. Я создаю виртуальную шахматную доску (только углы), а затем проецирую ее на свою плоскость изображения с помощью OpenCV. Идея состоит в том, чтобы спроецировать эти точки с известными коэффициентами искажения, а затем попытаться выполнить калибровку искажения объектива (с calibrateCamera) и посмотреть, получены ли те же коэффициенты.

Мой вопрос касается функции projectPoints, которая принимает distCoeffs в качестве входных данных. Это те же коэффициенты, которые необходимо использовать для неискажения изображения (вывод calibrateCamera)? Это означает, что функция должна будет вычислить обратное для этой операции. Или он использует эти коэффициенты для непосредственного искажения точек объекта? Это означает, что на выходе, например, не будет никакой корреляции. calibrateCamera.

Я спрашиваю, потому что заметил, что моя симуляция искажает подушкообразную подушку, когда я ожидаю ствола, и наоборот. Кажется, что искажение ведет к противоположному тому, что я думаю.

Минимальный рабочий код, который я использовал для имитации изображения (на Python):

# The distortion matrix that I vary
distortion = np.array([0.3, 0.001, 0.0, 0.0, 0.01])

# Generate Grid of Object Points
grid_size, square_size = [20, 20], 0.2
object_points = np.zeros([grid_size[0] * grid_size[1], 3])
mx, my = [(grid_size[0] - 1) * square_size / 2, (grid_size[1] - 1) * square_size / 2]
for i in range(grid_size[0]):
    for j in range(grid_size[1]):
        object_points[i * grid_size[0] + j] = [i * square_size - mx, j * square_size - my, 0]

# Setup the camera information
f, p = [5e-3, 120e-8]
intrinsic = np.array([[f/p, 0, 0], [0, f/p, 0], [0, 0, 1]])
rvec = np.array([0.0, 0.0, 0.0])
tvec = np.array([0.0, 0.0, 3.0])

# Project the points
image_points, jacobian = cv2.projectPoints(object_points, rvec, tvec, intrinsic, distortion)

# Plot the points (using PyPlot)
plt.scatter(*zip(*image_points[:, 0, :]), marker='.')
plt.axis('equal')
plt.xlim((-4000, 4000))
plt.ylim((-4000, 4000))
plt.grid()
plt.show()

Дополнительное объяснение:

Мой вопрос касается создания неправильного типа искажения. Если я использую матрицу положительных искажений, я ожидаю искажения в виде ствола, согласно этот веб-сайт, на котором говорится:

На следующем рисунке показаны два распространенных типа радиальных искажений: бочкообразное искажение (обычно k_1> 0) и подушкообразное искажение (обычно k_1 ‹0).

Чтобы проверить это, я использовал следующую матрицу положительных искажений (как в приведенном выше коде), и она создавала подушкообразное искажение.

distortion = np.array([0.3, 0.001, 0.0, 0.0, 0.01])

Ожидаемое искажение ствола, но есть булавочная подушечка

На этом изображении я явно создал подушкообразное искажение, а не бочкообразное.

Точно так же, если я сделаю свой коэффициент искажения отрицательным, что должно привести к искажению подушечки, я получу следующее:

distortion = -np.array([0.3, 0.001, 0.0, 0.0, 0.01])

Ожидается подушкообразное искажение, есть бочкообразное искажение

Означает ли это, что матрица искажений применяется отрицательно, если вы используете функцию projectPoints?

Спасибо за помощь!


person Hein Wessels    schedule 17.08.2018    source источник
comment
Я предполагаю, что это просто вопрос модели крошечного отверстия, используемой opencv, и той, к которой вы привыкли. вы можете думать об этом как о physical точечном отверстии, куда проецируется перевернутое изображение. Нравится (en.wikipedia.org/wiki/File:Pinhole-camera.svg) Но часто мы используем модель, в которой проекция находится спереди, а не перевернута (openmvg.readthedocs.io/en/latest/_images/pinholeCamera.png). Эти 2 модели совершенно одинаковые, разница только в сигнале габаритов.   -  person Fred Guth    schedule 19.08.2018
comment
@Fred, спасибо за комментарий! Я осознаю разницу, о которой вы говорите, но это создаст перевернутую ось x и y, с чем я не борюсь. Вместо этого создается неправильный тип искажения. Я обновил свой вопрос, чтобы прояснить это.   -  person Hein Wessels    schedule 20.08.2018


Ответы (1)


Кажется, что distCoeffs в projectPoints того же типа, что и выходы calibrateCamera. Я провел более тщательное моделирование, в котором добавил искажение с помощью projectPoints, а затем снова оценил его с помощью calibrateCamera, и это дало мне ту же матрицу искажения.

Например, со следующим кодом

distortion_given = np.array([[0.2, 0.01,  0.0, 0.0, 0.01]])# Note the negative sign
... = projectPoints(... , distortion_given , ...)
... , distortion_estimated , ... = calibrateCamera (...)
print (distortion_given)
print (distortion_estimated)

который создал следующее проецируемое изображение с бочкообразным искажением

введите здесь описание изображения

Результат:

distortion_given = [[-0.2, -0.01,  0.0, 0.0, -0.01]]
distortion_estimated = [[-0.19999985 -0.01000031  0.          0.         -0.00999981]]

Это означает, что когда этот веб-сайт, о котором я упоминал в вопросе, должен сделайте больший акцент на слове обычно, поскольку я заметил обратное.

бочкообразное искажение (обычно k_1> 0) и подушкообразное искажение (обычно k_1 ‹0).

person Hein Wessels    schedule 20.08.2018