#opencv #camera #distance #stereo-3d #stereoscopy
#opencv #камера #расстояние #стерео-3d #стереоскопия
Вопрос:
Есть ли способ рассчитать расстояние до конкретного объекта с помощью стереокамеры? Есть ли уравнение или что-то еще, чтобы получить расстояние, используя неравенство или угол?
Комментарии:
1. Я надеюсь, вы не возражаете, что я немного изменил ваше второе предложение.
2. Попробуйте отметить принятые ответы, если они действительно отвечают на вашу проблему.
Ответ №1:
ПРИМЕЧАНИЕ: Все описанное здесь можно найти в книге Learning OpenCV в главах о калибровке камеры и стереовидении. Вам следует прочитать эти главы, чтобы лучше понять приведенные ниже шаги.
Один из подходов, который не требует от вас самостоятельного измерения всех внутренних и внешних характеристик камеры, заключается в использовании функций калибровки OpenCVs. Внутренние характеристики камеры (искажение / перекос объектива и т.д.) Могут быть рассчитаны с помощью cv::calibrateCamera, В то время как внешние характеристики (соотношение между левой и правой камерами) могут быть рассчитаны с помощью cv::stereoCalibrate. Эти функции берут некоторое количество точек в пиксельных координатах и пытаются сопоставить их с координатами объектов реального мира. В CV есть удобный способ получить такие точки, распечатать черно-белую шахматную доску и использовать функции cv::findChessboardCorners / cv::cornerSubPix для их извлечения. Должно получиться около 10-15 пар изображений для шахматных досок.
Матрицы, рассчитанные с помощью функций калибровки, могут быть сохранены на диске, поэтому вам не нужно повторять этот процесс каждый раз при запуске вашего приложения. Здесь вы получаете несколько аккуратных матриц, которые позволяют вам создать карту исправления (cv:: stereoRectify / cv::initUndistortRectifyMap), которую позже можно применить к вашим изображениям с помощью cv::remap. Вы также получаете аккуратную матрицу под названием Q, которая представляет собой матрицу несоответствия глубине.
Причина исправления ваших изображений заключается в том, что после завершения процесса для пары изображений (при условии правильной калибровки) каждый пиксель / объект на одном изображении можно найти в той же строке на другом изображении.
Отсюда вы можете пойти несколькими путями, в зависимости от того, какие особенности вы ищете на изображении. Одним из способов является использование функций стереоотчета CVs, таких как сопоставление стереоблоков или полуглобальное сопоставление блоков. Это даст вам карту несоответствий для всего изображения, которое может быть преобразовано в 3D точки с использованием матрицы Q (cv::reprojectImageTo3D).
Недостатком этого является то, что, если на изображении не содержится большого количества текстурной информации, CV не очень хорош в построении плотной карты несоответствий (в ней будут пробелы там, где он не смог найти правильное несоответствие для данного пикселя), поэтому другой подход заключается в поиске точек, которые вы хотите сопоставить самостоятельно. Допустим, вы нашли объект при x = 40, y = 110 на левом изображении и x = 22 на правом изображении (поскольку изображения исправлены, они должны иметь одинаковое значение y). Несоответствие вычисляется как d = 40 — 22 = 18.
Постройте cv::Point3f(x, y, d), в нашем случае (40,110,18). Найдите другие интересные точки таким же образом, затем отправьте все точки в cv:: perspectiveTransform (с матрицей Q в качестве матрицы преобразования, по сути, эта функция cv :: reprojectImageTo3D, но для разреженных карт несоответствий), и на выходе будут точки в системе координат XYZ с левой камерой в центре.
Комментарии:
1. отличное резюме процесса, не многие люди на самом деле делают резюме, а просто цитируют «иди посмотри главу 12!». Спасибо, что нашли время объяснить 🙂
2. @Orka отличное резюме и большое вам спасибо, но не могли бы вы, пожалуйста, помочь мне, как определить несоответствие для каждой точки с помощью OpenCV?
Ответ №2:
Я все еще работаю над этим, поэтому пока не буду публиковать весь исходный код. Но я дам вам концептуальное решение.
В качестве входных данных вам понадобятся следующие данные (для обеих камер):
- положение камеры
- точка интереса камеры (точка, на которую смотрит камера)
- разрешение камеры (по горизонтали и вертикали)
- углы обзора камеры (горизонтальный и вертикальный)
Последнее расстояние вы можете измерить самостоятельно, поместив камеру на лист бумаги, проведя две линии и измерив угол между этими линиями.
Камеры не обязательно каким-либо образом выравнивать, вам нужно только иметь возможность видеть ваш объект в обеих камерах.
Теперь вычислите вектор от каждой камеры до вашего объекта. У вас есть пиксельные координаты объекта (X, Y) с каждой камеры, и вам нужно вычислить вектор (X, Y, Z). Обратите внимание, что в простом случае, когда объект виден прямо в центре камеры, решением было бы просто (camera.Интересующая точка — camera.Position).
Как только оба вектора будут направлены на вашу цель, линии, определенные этими векторами, должны пересекаться в одной точке в идеальном мире. В реальном мире этого не произошло бы из-за небольших ошибок измерения и ограниченного разрешения камер. Поэтому используйте ссылку ниже, чтобы вычислить вектор расстояния между двумя линиями.
Расстояние между двумя линиями
По этой ссылке: P0 — это ваше первое положение камеры, Q0 — ваше второе положение камеры, а u и v — векторы, начинающиеся с положения камеры и указывающие на вашу цель.
Вас не интересует фактическое расстояние, они хотят рассчитать. Вам нужен вектор Wc — мы можем предположить, что объект находится в середине Wc. Как только у вас есть положение вашего объекта в 3D-пространстве, вы также получаете любое расстояние, которое вам нравится.
Скоро я выложу весь исходный код.
Комментарии:
1. вы когда-нибудь делали доступным «полный» исходный код? Мне было бы интересно увидеть (еще один) пример получения глубины из двух изображений
2. @Eiver. Не могли бы вы, пожалуйста, привести несколько ссылок на примеры, как вы реализовали? Заранее спасибо..
3. @Eiver. не могли бы вы, пожалуйста, поделиться с нами своим кодом? заранее спасибо
4. @MohamedAM-Hassan Привет! Извините, но я был полностью перенаправлен на другие вещи и так и не смог закончить это.
Ответ №3:
У меня есть исходный код для определения человеческого лица, который возвращает не только глубину, но и координаты реального мира с левой камерой (или правой камерой, я не мог вспомнить), являющейся источником. Он адаптирован из исходного кода из «Learning OpenCV» и ссылается на некоторые веб-сайты, чтобы заставить его работать. Результат, как правило, довольно точный.
Комментарии:
1. Привет, Тони, можешь ли ты дать мне более подробную информацию об этом исходном коде?
2. Он сказал, возьмите книгу «Изучение OpenCV», это действительно стоит инвестиций. Также вы можете найти исходный код для book в Google, но опять же, без book вы не получите хорошего объяснения того, что происходит внутри него.