Python opencv depth map

How to create a depth map from stereo images in OpenCV Python?

A depth map can be created using stereo images. To construct a depth map from the stereo images, we find the disparities between the two images. For this we create an object of the StereoBM class using cv2.StereoBM_create() and compute the disparity using stereo.comput(). Where stereo is the created StereoBM object.

Steps

To create a depth map from the stereo images, you could follow the steps given below −

  • Import the required libraries OpenCV, Matplotlib and NumPy. Make sure you have already installed them.
  • Read two input images using cv2.imread()method as grayscale images. Specify the full path of the image.
  • Create a StereoBM object stereo = cv2.StereoBM_create() passing the desired numDisparities and blockSize.
  • Compute the disparity map between the input images using stereo.compute().To get a better result you can adjust the values of numDisparities and blockSize.
  • Visualize the disparity map (depth map).

Let’s look at some examples to create a depth map from the stereo images.

Example

In this Python code, we create a depth map using stereo images.

# import required libraries import numpy as np import cv2 from matplotlib import pyplot as plt # read two input images as grayscale images imgL = cv2.imread('L.png',0) imgR = cv2.imread('R.png',0) # Initiate and StereoBM object stereo = cv2.StereoBM_create(numDisparities=16, blockSize=15) # compute the disparity map disparity = stereo.compute(imgL,imgR) plt.imshow(disparity,'gray') plt.show() disparity.shape

We will use the following images as the Input Files in the above program −

Читайте также:  Java lang securityexception access

Output

When you run the above Python program, it will produce the following output window −

Let’s look at another example.

Example

In this Python code, we create a depth map using two stereo images.

# import required libraries import numpy as np import cv2 from matplotlib import pyplot as plt # read two input images imgL = cv2.imread('aloeL.jpg',0) imgR = cv2.imread('aloeR.jpg',0) # Initiate and StereoBM object stereo = cv2.StereoBM_create(numDisparities=128, blockSize=15) # compute the disparity map disparity = stereo.compute(imgL,imgR) disparity1 = stereo.compute(imgR,imgL) plt.imshow(disparity,'gray') plt.show()

We will use the following images as the Input Files in the above program −

Output

When you run the above Python program, it will produce the following output window −

Источник

Depth Map from Stereo Images¶

In last session, we saw basic concepts like epipolar constraints and other related terms. We also saw that if we have two images of same scene, we can get depth information from that in an intuitive way. Below is an image and some simple mathematical formulas which proves that intuition. (Image Courtesy :

Calculating depth

The above diagram contains equivalent triangles. Writing their equivalent equations will yield us following result:

disparity = x - x

xand xare the distance between points in image plane corresponding to the scene point 3D and their camera center. Bis the distance between two cameras (which we know) and fis the focal length of camera (already known). So in short, above equation says that the depth of a point in a scene is inversely proportional to the difference in distance of corresponding image points and their camera centers. So with this information, we can derive the depth of all pixels in an image.

So it finds corresponding matches between two images. We have already seen how epiline constraint make this operation faster and accurate. Once it finds matches, it finds the disparity. Let’s see how we can do it with OpenCV.

Code¶

Below code snippet shows a simple procedure to create disparity map.

import numpy as np import cv2 from matplotlib import pyplot as plt imgL = cv2.imread('tsukuba_l.png',0) imgR = cv2.imread('tsukuba_r.png',0) stereo = cv2.createStereoBM(numDisparities=16, blockSize=15) disparity = stereo.compute(imgL,imgR) plt.imshow(disparity,'gray') plt.show() 

Below image contains the original image (left) and its disparity map (right). As you can see, result is contaminated with high degree of noise. By adjusting the values of numDisparities and blockSize, you can get better results.

Disparity Map

Источник

Изучаем OpenCV на StereoPi: карта глубин по видео

Сегодня мы хотим поделиться серией примеров на Питоне для изучающих OpenCV на Raspberry Pi, а именно для двухкамерной платы StereoPi. Готовый код (плюс образ Raspbian) поможет пройти все шаги, начиная c захвата картинки и заканчивая получением карты глубин из захватываемого видео.

Вводная

Сразу подчеркну, что эти примеры – для комфортного погружения в тему, а не для продакшн-решения. Если вы продвинутый юзер OpenCV и имели дело с малиной, то знаете, что для полноценной работы желательно кодить на сишечке, да еще и задействовать малиновый GPU. В конце статьи я чуть подробнее коснусь «бутылочных горлышек» питонового решения и производительности в целом.

С чем работаем

В качестве железа у нас вот такой вот сетап:

Плата StereoPi, на борту Raspberry Pi Compute Module 3+. Подключены две самые простые камеры для Raspberry Pi версии V1 (на сенсоре ov5647).

  • Raspbian Stretch (kernel 4.14.98-v7+)
  • Python 3.5.3
  • OpenCV 3.4.4 (pre-compiled, ‘pip’ from Python Wheels)
  • Picamera 1.13
  • StereoVision lib 1.0.3 (https://github.com/erget/StereoVision)

Шаг первый: захват картинки

Для этого используется скрипт 1_test.py

Открываем консольку, переходим из домашней папки в папку с примерами:

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

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

Вот как выглядит работа первого скрипта:

Шаг второй: собираем картинки для калибровки

Если говорить о сферическом коне в вакууме, то для получения карты глубин хорошего качества нам нужно иметь две абсолютно идентичные камеры, вертикальные и оптические оси которых расположены идеально параллельно, а горизонтальные оси совпадают. Но в реальном мире все камеры немножко отличаются, да и расположить их идеально не получается. Поэтому был придуман трюк с программной калибровкой. С помощью двух камер из реального мира делается большое количество снимков заранее известного объекта (у нас это картинка с шахматной доской), а затем специальный алгоритм высчитывает всю «неидеальность» и пытается поправить картинки так, чтобы они были близки к идеалу.

Данный скрипт делает первый этап работы, а именно помогает сделать серию фотографий для калибровки.

Перед каждой фотографией скрипт начинает 5-секундный обратный отсчет. Этого времени, как правило, хватает на то, чтобы переместить доску в новое положение, убедиться что на обеих камерах она не вылезает за края, и зафиксировать ее положение (чтобы не было смаза на фотографии). По умолчанию размер серии установлен в 30 фотографий.

В итоге мы имеем серию фотографий в папке /scenes.

Режем картинки на пары

Третий скрипт 3_pairs_cut.py нарезает сделанные фотографии на «левые» и «правые» картинки и сохраняет их в папке /pairs. На самом деле мы могли бы исключить этот скрипт и делать резку на лету, но он очень полезен при дальнейших экспериментах. Например, вы можете сохранять нарезку из разных серий, использовать свои скрипты для работы с этими парами, либо вообще подсовывать в качестве пар картинки, сделанные на других стереокамерах.

Плюс перед резкой каждой картинки скрипт выводит ее изображение, что часто позволяет еще до следующего этапа калибровки увидеть неудачные фото и просто их удалить.

В готовом образе есть набор фотографий и нарезанных пар, которые мы использовали для наших экспериментов.

Калибровка

Скрипт 4_calibration.py затягивает к себе все пары с шахматными досками и вычисляет необходимые поправки для исправления картинок. В скрипте сделан автоматический отброс фотографий, на которых не найдена шахматная доска, так что в случае неудачных фотографий работа не останавливается. После того, как все 30 пар картинок загружены, начинается обсчет. У нас он занимает примерно полторы минуты. После завершения скрипт берет одну из стереопар, и на основе посчитанных параметров калибровки «исправляет» их, выводя на экран ректифицированную картинку. В этот момент можно оценить качество калибровки.

Скрипт калибровки в работе:

Настройка карты глубин

Скрипт 5_dm_tune.py загружает картинку, сделанную первым скриптом, и результаты калибровки. Далее выводится интерфейс, позволяющий менять настройки карты глубин и смотреть, что меняется. Совет: перед настройкой параметров сделайте кадр, в котором у вас будут одновременно объекты на разных расстояниях: вблизи (сантиметров 30-40), на средней дистанции (метр-два) и вдалеке. Это позволит вам подобрать параметры, при которых близкие объекты будут красного цвета, а дальние – темно-синего.

В образе лежит файл с нашими настройками карты глубин. Вы можете загрузить наши настройки в скрипте просто нажав кнопку “Load settings”

Вот как выглядит процесс настройки:

Карта глубин в реальном времени

Последний скрипт 6_dm_video.py строит карту глубин по видео, используя результаты работы предыдущих скриптов (калибровку и настройку карты глубин).

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

На всякий случай добавлю, что во всех скриптах есть обработка нажатий клавиш, и прервать работу можно нажатием кнопки Q. Если останавливать «грубо», например Ctrl+C, то может поломаться процесс взаимодействия Питона с камерой, и потребуется перезагрузка малины.

Для продвинутых

  • Первый скрипт в процессе работы выводит среднее время между захватами кадров, а по завершению – средний FPS. Это простой и удобный инструмент для подбора таких параметров изображения, при которых питон еще «не захлебывается». С его помощью мы и подобрали 1280×480 при 20 FPS, при которых видео отдается без задержек.
  • Вы можете заметить, что мы захватываем стереопару в разрешении 1280×480, а затем скейлим ее до 640×240.

Резонный вопрос: зачем всё это, и почему не захватить сразу уменьшенную картинку и не загружать наш питон ее уменьшением?

На Compute Module 3+ Lite (новая серия, с железной «шапкой» на проце) показывает примерно такие результаты:

Как использовать GPU?

Как минимум его можно задействовать для андисторсии и ректификации картинок в реальном времени, ибо есть примеры (вот на WebGL ), Питоновый Pi3d, а также проект Processing (примеры для малины).

Источник

Оцените статью