OpenCV: измерение расстояния между двумя шарами в миллиметрах - как повысить точность

Я также разместил эту тему в форуме Q & A на opencv.org, но я не знаю, сколько экспертов здесь читают этот форум - так простите меня, что я тоже здесь пытаюсь.

В настоящее время я изучаю OpenCV, и моя текущая задача - измерить расстояние между двумя шарами, которые лежат на тарелке. Мой следующий шаг - сравнить несколько камер и разрешений, чтобы понять, насколько важны разрешение, шум, искажения и т.д. И насколько тяжелые эти параметры влияют на точность. Если сообщество заинтересовано в результатах, я рад поделиться результатами, когда они будут готовы! Камера расположена над пластиной с помощью широкоугольного объектива. Известны ширина и высота пластины (1500 x 700 мм) и радиус шариков (40 мм).

Мои действия:

  • калибровка камеры
  • Неисправность изображения (искажение высокое из-за широкоугольного объектива)
  • findHomography: я использую угловые точки пластины в качестве входных данных (4 точки в пикселях в неискаженном изображении) и угловые точки в миллиметрах (начиная с 0,0 в левом нижнем углу, до 1500 700 в верхний правый угол)
  • используя HoughCircles, чтобы найти шары в неискаженном изображении
  • Применение перспективыТрансформация по точкам окружности = > Центрирующие точки окружности теперь существуют в миллиметрах
  • вычисление расстояния между двумя центральными точками: d = sqrt ((x1-x2) ^ 2 + (y1-y2) ^ 2)

Результаты: ошибка около 4 мм на расстоянии 300 мм, погрешность около 25 мм на расстоянии 1000 мм. Но если я измеряю прямоугольник, который печатается на пластине, ошибка меньше 0,2 мм, поэтому я думаю, что калибровка и искажение работают хорошо.

Я подумал об этом и выяснил три возможные причины:

  • findHomography применялась к точкам, лежащим прямо на пластине, тогда как центральные точки шаров должны быть измерены на экваториальной высоте = > как я могу изменить результат findHomography, чтобы изменить это, то есть "переместить" самолет? Радиус в мм известен.
  • ошибка увеличивается с увеличением расстояния шара до оптического центра, потому что камера не увидит мяч сверху, поэтому центральная точка в 2D-проекции изображения не такая, как в 3D-мире - я проедем дальше к границам изображения. = > Есть ли какие-либо геометрические операции, которые я могу применить в найденном центре, чтобы исправить значение?
  • во время неисторификации, возможно, потеря информации, потому что я создаю новое неискаженное изображение и возвращаюсь к точности пикселей, хотя у меня много значений с плавающей запятой в матрице искажений. Должен ли я искать шары в искаженном изображении и преобразовывать только центральные точки с матрицей искажений? Но я не знаю, какой код для этой задачи.

Я надеюсь, что кто-то может помочь мне улучшить это, и я надеюсь, что эта тема интересна другим запускам OpenCV.

Спасибо и с наилучшими пожеланиями!

Ответ 1

Вот несколько мыслей, которые помогут вам... Ни в коем случае не "ответ".

Сначала простой. Если вы откалибровали свое изображение в мм на определенной плоскости, которая находится на расстоянии D, то точки с r ближе будут отображаться больше, чем они есть. Чтобы получить от измеренных координат фактические координаты, вы используете

Actual = measured * (D-r)/D

Так как центры сфер имеют радиус r над плоскостью, приведенная выше формула должна ответить на часть 1 вашего вопроса.

Относительно второго вопроса: если вы думаете об этом, то центр сферы, который вы видите, должен находиться в нужном месте "в плоскости центра сферы", хотя вы смотрите на него под углом. Нарисуйте себе картину, чтобы убедить себя в этом.

Третий вопрос: если вы найдете координаты сфер в искаженном изображении, вы сможете преобразовать их в исправленное изображение, используя perspectiveTransform. Это может немного улучшить точность, но я удивлен размером ошибок, которые вы видите. Насколько велико один пиксель на самом большом расстоянии (1000 мм)?

ИЗМЕНИТЬ

Вы спросили об эллиптических проекциях и т.д. В принципе, если вы думаете о оптическом центре камеры как источнике света и смотрите на тень шара на плоскость в качестве своего "2D-изображения", вы можете нарисовать картинку лучей, которые только что попали по сторонам шара, и определяют разные углы:

enter image description here

Легко видеть, что P (средняя точка A и B) не совпадает с C (проекция центра сферы). Немного больше триггера покажет вам, что ошибка C - (A+B)/2 увеличивается с x и уменьшается с помощью D. Если вы знаете A и B, вы можете рассчитать правильную позицию C (учитывая D):

C = D * tan( (atan(B/D) + atan(A/D)) / 2 )

Ошибка становится больше, поскольку D меньше и/или x больше. Примечание D - это перпендикуляр (кратчайшее) расстояние от объектива до плоскости объекта.

Это работает только в том случае, если камера действует как "истинный объектив" - другими словами, нет искажений подкладки, а прямоугольник в плоскости изображения отображается в прямоугольник на датчике. Вышесказанное в сочетании с вашей собственной идеей, чтобы вписаться в нескорректированное ( "пиксельное" ) пространство, затем преобразовать центры, найденные с помощью perspectiveTransform, должно быть вам до конца.

Посмотрите, что вы можете с этим сделать!