Основы программировния морских роботов

Работа с видеокамерой

logo
smtu logo

План занятия

  • Работа с камерами в Linux

  • OpenCV: получение изображений и их изменения

  • Нода камеры

  • Файл конфигурации ноды

  • Калибровка камеры

Зачем нам работать с камерами?

  • Пройти задание соревнований по точкам не выйдет

  • Мы уже обсудили необходимость обратной связи

  • Но по изображению с камеры, в режиме телеуправления, каждый из вас пройдёт задание

  • Значит нам нужно замкнуть обратную связь по изображениям с камеры

  • Сегодня - техническая часть, подготовка к обработке изображений

Подготовка окружения

Установим пакеты

$ sudo apt install v4l-utils           # Утилита для работ с камерами
$ sudo apt install qv4l2               # Графическая утилита для работы с камерой
$ sudo apt install python3-opencv      # Библиотека для работы с CV
$ sudo apt install \*jazzy-compressed* # ROS, для работы с сжатыми изображениями
$ sudo apt install ros-jazzy-usb-cam   # Нода для работы с usb-камерами
$ sudo apt install ros-jazzy-camera-calibration # Нода для калибровки камеры

Склонируем репозиторий

$ git clone http://sdb.smtu.ru/gitlab/marinerobotics/lesson_06.git

Video4Linux (V4L)

  • V4L - API для работы с аудио и видео, а также связанный набор утилит

  • V4L2 - актуальная версия системы

  • Основные утилиты:

    • v4l2-ctl - позволяет в командной строке получать и устанавливать параметры V4L2 (яркость, контраст, форматы, буферы и т.д.)

    • qv4l2 - то же самое, но с графическим интерфейсом

  • Камера с точки зрения Linux - это файл /dev/video*

v4l2-ctl: список устройств

$ v4l2-ctl --list-devices
Integrated IR Camera: Integrate (usb-0000:00:14.0-5):
	/dev/video0
	/dev/video1
	/dev/media0

Integrated Camera: Integrated C (usb-0000:00:14.0-8):
	/dev/video2
	/dev/video3
	/dev/media1

v4l2-ctl: об устройстве

$ v4l2-ctl -d /dev/video2 --all
Driver Info:
	Driver name      : uvcvideo
	Card type        : Integrated Camera: Integrated C
	Bus info         : usb-0000:00:14.0-8
	Driver version   : 6.14.11
	Capabilities     : 0x84a00001
		Video Capture
		Metadata Capture
		Streaming
		Extended Pix Format
		Device Capabilities
	Device Caps      : 0x04200001
		Video Capture
		Streaming
		Extended Pix Format
Media Driver Info:
	Driver name      : uvcvideo
	Model            : Integrated Camera: Integrated C
	Serial           : 0001
	Bus info         : usb-0000:00:14.0-8
	Media version    : 6.14.11
	Hardware revision: 0x00000027 (39)
	Driver version   : 6.14.11
Interface Info:
	ID               : 0x03000002
	Type             : V4L Video
Entity Info:
	ID               : 0x00000001 (1)
	Name             : Integrated Camera: Integrated C
	Function         : V4L2 I/O
	Flags            : default
	Pad 0x01000007   : 0: Sink
	  Link 0x02000013: from remote pad 0x100000a of entity 'Extension 6' (Video Pixel Formatter): Data, Enabled, Immutable
Priority: 2
Video input : 0 (Camera 1: ok)
Format Video Capture:
	Width/Height      : 1280/720
	Pixel Format      : 'MJPG' (Motion-JPEG)
	Field             : None
	Bytes per Line    : 0
	Size Image        : 1843200
	Colorspace        : sRGB
	Transfer Function : Rec. 709
	YCbCr/HSV Encoding: ITU-R 601
	Quantization      : Default (maps to Full Range)
	Flags             :
Crop Capability Video Capture:
	Bounds      : Left 0, Top 0, Width 1280, Height 720
	Default     : Left 0, Top 0, Width 1280, Height 720
	Pixel Aspect: 1/1
Selection Video Capture: crop_default, Left 0, Top 0, Width 1280, Height 720, Flags:
Selection Video Capture: crop_bounds, Left 0, Top 0, Width 1280, Height 720, Flags:
Streaming Parameters Video Capture:
	Capabilities     : timeperframe
	Frames per second: 30.000 (30/1)
	Read buffers     : 0

User Controls

                     brightness 0x00980900 (int)    : min=0 max=255 step=1 default=128 value=30
                       contrast 0x00980901 (int)    : min=0 max=255 step=1 default=32 value=0
                     saturation 0x00980902 (int)    : min=0 max=100 step=1 default=64 value=0
                            hue 0x00980903 (int)    : min=-180 max=180 step=1 default=0 value=-180
        white_balance_automatic 0x0098090c (bool)   : default=1 value=1
                          gamma 0x00980910 (int)    : min=90 max=150 step=1 default=120 value=120
           power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=1 value=1 (50 Hz)
				0: Disabled
				1: 50 Hz
				2: 60 Hz
      white_balance_temperature 0x0098091a (int)    : min=2800 max=6500 step=10 default=4600 value=4600 flags=inactive
                      sharpness 0x0098091b (int)    : min=0 max=7 step=1 default=0 value=0
         backlight_compensation 0x0098091c (int)    : min=0 max=2 step=1 default=1 value=0

Camera Controls

                  auto_exposure 0x009a0901 (menu)   : min=0 max=3 default=3 value=1 (Manual Mode)
				1: Manual Mode
				3: Aperture Priority Mode
         exposure_time_absolute 0x009a0902 (int)    : min=2 max=1250 step=1 default=156 value=2
     exposure_dynamic_framerate 0x009a0903 (bool)   : default=0 value=1

v4l2-ctl: форматы и разрешения

$ v4l2-ctl -d /dev/video2 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
	Type: Video Capture

	[0]: 'MJPG' (Motion-JPEG, compressed)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x180
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 424x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 848x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 960x540
			Interval: Discrete 0.033s (30.000 fps)
	[1]: 'YUYV' (YUYV 4:2:2)
		Size: Discrete 1280x720
			Interval: Discrete 0.100s (10.000 fps)
		Size: Discrete 320x180
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 424x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x360
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 848x480
			Interval: Discrete 0.050s (20.000 fps)
		Size: Discrete 960x540
			Interval: Discrete 0.067s (15.000 fps)

v4l2-ctl - управление параметрами

$ v4l2-ctl -d /dev/video2 --get-ctrl=brightness
brightness: 0
$ v4l2-ctl -d /dev/video2 --set-ctrl=brightness=30
$ v4l2-ctl -d /dev/video2 --get-ctrl=brightness
brightness: 30

qv4l2

  • менять параметры камеры удобнее через графический интерфейс

  • так что попробуйте (если есть доступ к GUI) qv4l2

OpenCV

  • OpenCV - библиотека алгоритмов компьютерного зрения, обработки изображений и т.д.

  • Принадежит intel, существенную роль в разработке оказала компания itseez (Россия)

  • На сегодняшний день - де-факто стандарт в "классическом" CV

  • Но нейросети существенно потеснили классическое CV

opencv logo

Получение изображения

lesson_06/nonros_example/cv2_video_capture.py

import cv2

# Открытие камеры (0 обычно означает встроенную веб-камеру)
cap = cv2.VideoCapture(0)

# Проверка успешного открытия камеры
if not cap.isOpened():
    print("Error: Could not open camera")
    exit()

while True:
    # Чтение кадра
    ret, frame = cap.read()

    # Если кадр считан корректно, ret имеет значение True
    if not ret:
        print("Error: Can't receive frame")
        break

    # Отображение кадра
    cv2.imshow('Webcam', frame)

    # Нажмите 'q' для выхода
    if cv2.waitKey(1) == ord('q'):
        break

# Освобождение камеры и закрытие окон
cap.release()
cv2.destroyAllWindows()

Изменение изображений: рамки

lesson_06/nonros_example/cv2_video_labeling.py

# Нарисовать ограничивающую рамку (прямоугольник) в центре
# cv2.rectangle(изображение, начальная_точка, конечная_точка, цвет, толщина)
box_x1, box_y1 = 220, 50
box_x2, box_y2 = 440, 470

# Нарисовать синий прямоугольник (цвет BGR: Синий=255, Зеленый=0, Красный=0)
cv2.rectangle(frame, (box_x1, box_y1), (box_x2, box_y2), (255, 255, 0), 2)

Изменение изображений: добавление текста

lesson_06/nonros_example/cv2_video_labeling.py

# Добавить текст над рамкой
# Формат: cv2.putText(изображение, текст, положение, шрифт, масштаб, цвет, толщина)
text = "teacher"
text_position = (box_x1, box_y1 - 10)
cv2.putText(frame, text, text_position,
                cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 1)
cv2.putText(frame, "2026-01-01 00:00:00", (10, 480 - 10),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)

ROS

  • Техническая часть: работа с usb-камерами

  • Калибровка камер

  • Шаблоны для интеграции ROS с OpenCV

usb-cam-node

  • простой запуск публикации изображения с камеры

    ros2 run usb_cam usb_cam_node_exe --ros-args \
        -p video_device:=/dev/video0
  • В RQT: PluginsVisualizationImage View

    • в появившемся окне надо выбрать топик с изображением

ros2 rqt image view

Параметры ноды

  • в папке config можно создавать *.yaml файлы ноды и в нём указывать параметры

    /**:
      ros__parameters:
        video_device: /dev/video0
        image_width: 640
        image_height: 480
        framerate: 15.0
        pixel_format: mjpeg2rgb

Использование параметров

  • вызов в консоли:

    ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>
  • использование в launch-файле:

    Node(
        package='turtlesim',
        executable='turtlesim_node',
        namespace='turtlesim2',
        name='sim',
        parameters=[PathJoinSubstitution([
            FindPackageShare('launch_tutorial'),
            'config', 'turtlesim.yaml'])
        ],
    )

Работа с изображениями в ROS2

Приём и передача данных

  • библиотека

    from sensor_msgs.msg import CompressedImage
  • subscriber

    self.create_subscription(
        CompressedImage,
        'image_raw/compressed',
        self.image_callback,
        1
    )
  • publisher

    self.image_publisher = self.create_publisher(
        CompressedImage,
        'image_raw/changed/compressed', 10)

Взаимодействие с OpenCV

  • библиотека

    import cv2
    from cv_bridge import CvBridge
  • использование

    self.bridge = CvBridge()
    #...
    cv_image = self.bridge.compressed_imgmsg_to_cv2(msg)
    #...
    result =  self.bridge.cv2_to_compressed_imgmsg(cv_image)
    self.image_publisher.publish(result)

Калибровка камеры в ROS

Калибровка камеры в ROS

Любая камера вносит искажения (дисторсию) в изображение. Из-за дисторсии прямые линии в реальном мире могут выглядеть изогнутыми. Для точных измерений по изображению (расстояния, углы, размеры) необходима калибровка. Калибровка позволяет получить матрицу внутренних параметров камеры и коэффициенты искажений.

Как проходит калибровка в ROS2?

Используется пакет camera_calibration

Применяется классический метод с шахматной доской (checkerboard)

Шахматную доску надо клеить на плоскую поверхность

checkboard

Как проходит калибровка в ROS2?

Необходимо снять 40-50 кадров шахматной доски под разными углами и положениями.

Программа автоматически определит углы доски и вычислит параметры.

Подводную камеру необходимо калибровать с учётом условий воды, так как там будут свои дополнительные искажения.

Как проходит калибровка в ROS2? Практика

Для начала давайте установим пакет ROS2

sudo apt install ros-jazzy-camera-calibration

Запуск запуск видеопотока ROS

ros2 run usb_cam usb_cam_node_exe --ros-args -p video_device:="/dev/video2" -p framerate:=30.0 -p pixel_format:="mjpeg2rgb" -r __ns:=/camera

В параметр video_device необходимо вписать ваш путь до камеры

Узнать путь всех доступных камер

ls /dev/video*

либо

v4l2-ctl --list-devices

Запуск калибровки

ros2 run camera_calibration cameracalibrator --size 8x6 --square 0.025 --no-service-check --ros-args --remap image:=/camera/image_raw
  • --size 8x6 - размерность шахматной доски

  • --square 0.025 - размер одного квадрата

  • --no-service-check - не проверяет наличие сервисов (в нашем случае обязательный параметр)

  • image:=/camera/image_raw - подписывается топик с изображением

Калибровка

Для полной калибровки необходимо запонить все пункты (x,y, size, skew) до появления активной кнопки calibrate

start calibration

Калибровка x и y

Для калибровки первых двух парамеров нужно перемешать данную шахматную доску по данным осям.

  • x - горизонтальное перемещение

  • y - вертикальное

calibrate x y

Калибровка size

Для калибровки парамера size нужно изменять размер данной шахматной доски относительно камеры (приближать и отдалять).

calibrate size

Калибровка skew

Для калибровки парамера skew нужно откалиборвать искажения шахматной доски относительно камеры.

calibrate skew 1
calibrate skew 2

Почти готово

Как только мы и программа готова откалибровать камеру

final calibration
  1. calibrate

  2. save

  3. Файлы с калибровкой сохраняется в папку /tmp/

Готово

Далее неоходимо переместить в домашнюю директорию, разархивировать архив с калибровкой

и при помощи команды mv переместим в папку с camera info

mv /home/orangepi/<folder_calibrate>/out.yaml /home/orangepi/.ros/camera_info/default_cam.yaml

Сегодня я многое понял

  • Как работать с камерами в Linux

  • Как работать с библиотекой OpenCV

  • Как обрабатывать изображения в ROS

KyleBroflovski

Дополнительные материалы

Calibration Checkerboard https://markhedleyjones.com/media/calibration-checkerboard-collection/Checkerboard-A4-25mm-8x6.pdf

https://markhedleyjones.com/media/calibration-checkerboard-collection/Checkerboard-A4-25mm-8x6.pdf

Документация camera calibration https://docs.ros.org/en/jazzy/p/image_pipeline/

https://docs.ros.org/en/jazzy/p/image_pipeline/

Документация OpenCV camera calibration https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html

https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html

Домашнее задание

  • Нанесите изображение на видеокамеру - прямоугольник по центру

  • Выведите любой текст под прямоугольником

    • Задание со звёздочкой - выведите текущее время в качестве текста