4.17. Настройки датчика

Помимо pixformat() и framesize(), класс CSI предоставляет несколько настроек, специфичных для датчика, к которым рано или поздно обращается почти любое приложение, – ориентацию монтажа, экспозицию, усиление, баланс белого и несколько вспомогательных средств отладки. Каждая из них напрямую соответствует концепции датчика, рассмотренной ранее; API лишь предоставляет дескриптор Python для записи в регистр, которую драйвер выполняет под капотом.

Все приведённые ниже методы воздействуют на сам датчик. Они выполняют записи в регистры по управляющей шине I2C датчика, поэтому затраты составляют микросекунды, а новая настройка вступает в силу при следующей экспозиции – обычно при следующем snapshot().

4.17.1. Ориентация

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

csi0.hmirror(True)
csi0.vflip(True)

hmirror() отражает изображение слева направо, а vflip() – сверху вниз. Вместе они охватывают случаи, встречающиеся на практике: плату, смонтированную вверх ногами (оба флага True), плату за зеркалом с лицевым отражающим покрытием (только hmirror) или плату, смотрящую на отражённую сцену снизу (только vflip).

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

4.17.2. Экспозиция

Экспозиция – это время интегрирования, то есть продолжительность накопления заряда фотодиодом каждого пикселя перед считыванием строки, в микросекундах. Драйвер запускается с работающим циклом автоэкспозиции датчика, поэтому камера старается удерживать среднее значение пикселей вблизи целевого. Отключение этого цикла фиксирует экспозицию на значении, которое выбирает приложение:

csi0.auto_exposure(False, exposure_us=8000)

Фиксированная экспозиция – правильный выбор, когда яркость сцены стабильна и приложению нужны предсказуемое размытие движения или одинаковая интенсивность от кадра к кадру для порогового анализа. Считывание текущей экспозиции – независимо от того, задал ли её цикл или приложение – выполняется отдельным вызовом:

us = csi0.exposure_us()

Вызов auto_exposure() со значением True и без значения экспозиции возвращает управление обратно циклу.

4.17.3. Усиление

Усиление – это коэффициент усилителя, применяемый к напряжению пикселя перед тем, как оно достигнет ADC, в децибелах. Как и в случае с экспозицией, драйвер запускается с включённым циклом автоусиления. Часто встречаются два сценария. Ограничение верхней границы позволяет циклу адаптироваться к освещению, но не даёт ему бесконечно усиливать шум в тёмных сценах:

csi0.auto_gain(True, gain_db_ceiling=16)

Фиксация усиления – правильный шаг, когда приложение также фиксирует экспозицию: стабильность усиления важна для приложений, которые сравнивают значения пикселей от кадра к кадру, например для отслеживания цвета:

csi0.auto_gain(False, gain_db=0)

Текущее усиление считывается через gain_db(). Всякий раз, когда приложение отключает автоусиление, оно должно также отключить автоматический баланс белого и автоэкспозицию – иначе остающиеся в работе управляющие циклы будут изменять изображение способами, нивелирующими фиксированное усиление.

4.17.4. Баланс белого

Баланс белого – это поканальное усиление, которое ISP применяет к красному, зелёному и синему каналам, выходящим со ступени дебайеринга, чтобы белый объект выглядел белым при свете любого цвета. Цикл автоматического баланса белого вычисляет эти три коэффициента усиления на основе статистики по областям, которую ISP собирает для каждого кадра, и применяет их к следующему кадру.

Большинство приложений оставляют этот цикл работающим. Отслеживание цвета – частое исключение: коэффициенты усиления – это как раз то, что цикл будет изменять в погоне за цветным объектом, поэтому, если приложение пытается найти красный блоб, цикл незаметно приглушит красный канал, и блоб перестанет соответствовать. Блокировка цикла решает эту проблему:

csi0.auto_whitebal(False)

Передайте явный кортеж (r, g, b) в децибелах для воспроизводимой цветовой калибровки – одинаковых коэффициентов усиления на разных платах и в разных сеансах:

csi0.auto_whitebal(False, rgb_gain_db=(0.0, 0.0, 0.0))

Текущие коэффициенты усиления считываются в виде кортежа через rgb_gain_db().

4.17.5. Ограничение частоты кадров

По умолчанию датчики работают на своей собственной частоте кадров – от 30 до 60 кадров в секунду на большинстве моделей и существенно выше на высокоскоростных датчиках, когда размер кадра достаточно мал. Ограничение частоты позволяет приложению снизить скорость камеры до уровня, с которым успевает справляться последующая обработка:

csi0.framerate(15)

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

4.17.6. Тестовый шаблон

Тестовый шаблон цветных полос встроен в большинство датчиков и полезен для отделения проблемы формирования изображения от проблемы вывода. Его включение обходит массив фотодиодов и отправляет фиксированный шаблон по тому же тракту пиксельных данных:

csi0.colorbar(True)

Если тестовый шаблон выглядит правильно, а живое изображение – нет, неисправность кроется в оптике или аналоговом входном тракте датчика; если же повреждён даже тестовый шаблон, проблема находится где-то на шине пиксельных данных или в конфигурации pixformat() / framesize(). Передайте False, чтобы вернуться к живому изображению.

См. csi.CSI для полного описания API, включая специфичные для датчиков команды ioctl(), которые открывают доступ к настройкам, уникальным для отдельных семейств датчиков.