Видеокаротаж своими руками: накладываем глубину на видео

от автора

При видеокаротаже мы опускаем в скважину камеру и видим на экране обсадную трубу, фильтры, отложения и повреждения, застрявшие насосы и тд. Но есть проблема: на видео нет глубины. Ты видишь картинку, но не знаешь, на какой глубине находится камера. Можно конечно сделать метки на кабеле, условно, каждые 1 -2 метра, но это жутко не удобно и их нужно стоять и считать, вообще тот еще костыль. Раньше использовали вторую видео камеру, которая снимала механический счетчик с отображением метров, но тоже костыль. Нужно потом накладывать друг на друга картинку, что не самый удобный вариант.

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

Вот как я это сделал. Начнем с железа :

Микроконтроллер: Arduino Nano
Почему? Простота и размер. Он маленький, дешёвый, легко программируется. Вставляется в разъём на плате OSD-модуля. В сети куча примеров по данной теме, решил использовать то, что уже было сделано другими.

Чип OSD: MAX7456
Этот чип умеет в реальном времени накладывать символы на аналоговый видеосигнал. Выпускается в готовых модулях — например, MinimOSD. Такие модули изначально делали для квадрокоптеров (F3/F4 flight controllers), но они отлично подходят для каротажа.

Почему не готовый видеорегистратор со встроенным OSD?

  • Дорого.

  • Нельзя программировать под свои задачи.

  • Обычно нет возможности принимать данные по Serial извне.

Библиотека: стандартный SPI + самописные функции. Готовые библиотеки из интернета не

всегда корректно работали с PAL, поэтому часть кода писал сам.

Я использовал готовый модуль MinimOSD, который уже включает MAX7456 и всю схему обвязки. Подключение — по UART (TX → RX, RX → TX, земля). Arduino отправляет на модуль символы для отображения. Самому паять SPI-подключение не нужно. Можно конечно купить чип сделать плату ( также есть схема в сети, кстати достаточно подробная ) но я человек-лень.

Видеосигнал от камеры идёт на видеовход модуля, с выхода — на монитор или видеорегистратор. Модуль смешивает исходное видео с наложенными символами.

В итоге берем модуль, очищаем его память, подаем питание:

После подачи питания нужно сбросить MAX7456 и настроить видеорежим:

digitalWrite(MAX7456SELECT, LOW); spi_transfer(VM0_reg); spi_transfer(MAX7456_reset); // сброс digitalWrite(MAX7456SELECT, HIGH); delay(500);

// Настройка яркости строк (белый уровень 90%) for (x = 0; x < MAX_screen_rows; x++) { spi_transfer(x + 0x10); spi_transfer(WHITE_level_90); }

// Включаем OSD, синхронизация по VSYNC, режим PAL (у нас Россия) spi_transfer(VM0_reg); spi_transfer(VERTICAL_SYNC_NEXT_VSYNC | OSD_ENABLE | VIDEO_MODE_PAL);

Основной регистратор на STM32 Black Pill отправляет данные по Serial на Arduino. Формат очень простой: текстовая строка, заканчивающаяся \n.

  • Если строка начинается с C — это глубина в метрах (например, "C123.45\n").

  • Если с G — это локация муфт (например, "G87.2\n").

Arduino читает в буфер:

while (Serial.available() > 0) { Serial.readBytesUntil(0x0a, mass, 64); } потом отображает :

if (mass[0] == 0x43) { // ‘C’ // извлекаем число и выводим printDisplayCircle(result); } if (mass[0] == 0x47) { // ‘G’ printDisplayLocate(result); }

Функция OSD_write_to_screen — самая важная. Она помещает строку в заданные координаты (x,y). Координаты подбирались экспериментально, чтобы цифры не наезжали на важные элементы изображения.

cpp

void OSD_write_to_screen(const char s[], byte x, byte y, byte blink, byte invert) {  // x - горизонталь (символы, до 30)  // y - вертикаль (строки, до 16)  // blink - мигание (0 - нет, 1 - да)  // invert - инверсия фона (0 - нормально, 1/3 - инверсия)  ...}

Последний параметр invert особенно полезен: инвертированные символы отлично видны на светлом фоне (например, на яркой воде или белой трубе).

Вот как выглядит обмен в реальном времени:

  1. Оператор на регистраторе (STM32 Black Pill, дисплей DWIN) включает режим видео.

  2. Энкодер глубины выдаёт импульсы. STM32 пересчитывает их в метры.

  3. По Serial (UART) на Arduino уходит строка: "C125.30\n" (125 метров 30 см).

  4. Arduino принимает её, разбирает и вызывает printDisplayCircle("125.30").

  5. На экране монитора, рядом с глубиной, отображается цифра.

Для локации муфт — аналогично: "G45.1\n" и вывод в левом верхнем углу надпись "Loc: 45.1".

Скорость обмена: 9600 бод. Этого достаточно, потому что глубина меняется не быстрее 1-2 раз в секунду (скорость спуска 5-10 м/мин).

Когда сделал плату, поставил камеру, пришла пора сделать корпус.

Самое сложное- выточить стекло, нужно точить строго в размер, попадет вода-помрет все. Для связи с кабелем сделал наконечник прибора, да не просто, а герметичный:

Уплотнения- резина, зазоры все по заводу), максимальное давление выдержало около 50 атм, это 500 метров под водой.

ссылка на оригинал статьи https://habr.com/ru/articles/1043162/