Скільки потрібно нейронів, щоб розпізнати зведення мосту?

Історія почалася, коли я переїхав жити на острів Декабристів в Санкт-Петербурзі. Вночі, коли розвели мости, цей острів разом з Васильевским повністю ізольований від великої землі. Мости при цьому нерідко зводять достроково, іноді на годину раніше опублікованого розкладу, але оперативної інформації про це ніде немає.
Після другого "запізнення" на мости, я задумався про джерела інформації про дострокову зведенні мостів. Одним з тих, що прийшли в голову варіантів була інформація з публічних веб-камер. Озброївшись цими даними і залишковими знаннями з спеціалізації за ML від МФТІ Яндекса, я вирішив спробувати вирішити завдання "в лоб".
0, Палацовий
 
По-перше — камери
З веб-камерами в Петербурзі зараз не густо, живих спрямованих на мости камер в мене вийшло знайти тільки дві: vpiter.com і РГГМУ. Кілька років тому були камери від Skylink, але зараз вони не доступні. З іншого боку, навіть інформація по одному тільки Палацовому мосту з vpiter.com може бути корисна. І вона виявилася корисніше, ніж я очікував — товариш-парамедик розповів, що його екіпаж "швидкої" у тому числі завдяки оперативній інформації про мостах врятував "плюс" двох петербуржців і одного шведа за тиждень. :-)
Ще камери мають властивість відвалюватися, віддавати відеопотік потік в мерзенному форматі flv, але все це дуже нескладно обходиться готовими кубиками. Буквально в два рядки shell-скрипта з відеопотоку виходить набір кадрів, що надходять на класифікацію раз в 5 секунд:
while true; do
curl --connect-timeout $t --speed-limit $x --speed-time $y http://url/to | \
ffmpeg -loglevel warning -r 10 -i /dev/stdin -vsync 1 -r 0.2 -f image2 $(date +%s).%06d.jpeg
done

Правда, поки ніякої класифікації немає. Спочатку в "сосисочную машинку" потрібно покласти розмічені дані, тому залишимо скрипт працювати ночами на тиждень, і опціонально підемо мантрі #ВПитереПить, перевіривши, що картинки вантажаться.
x = io.imread(fname)

1, frame
По-друге — обробка зображень
Так чи інакше, розкидавши руками і методом ділення навпіл фотографії по папках UP, MOVING, DOWN я отримав розмічену вибірку. Ендрю Ин у своєму курсі пропонував хорошу евристику "якщо ви на картинці можете відрізнити об'єкт A від об'єкта Б, то і у нейронної мережі є шанс". Назвемо це емпіричне правило наївним тестом Ина.
Першим ділом здається розумним обрізати картинку, щоб на ній була тільки секція розвідного моста. Телевежа — це красиво, але не виглядає практично. Напишемо перший рядок коду, що має хоч якесь відношення до обробці зображень:
lambda x: x[40:360, 110:630]

2, bridge
Я краєм вуха чув, що справжні фахівці беруть OpenCV, витягують фічі і отримують пристойну якість. Але, почавши читати документацію до OpenCV, мені стало сумно — досить швидко я зрозумів, що в встановлений ліміт "зробити прототип за пару вечорів" я з OpenCV не вкладуся. Але в використовуваної для читання jpeg-ів бібліотеці skimage по слову
feature
також дещо знаходилося. Чим відрізняється розведений міст від зведеного? Контуром на тлі неба. Ну так і візьмемо
skimage.feature.canny
, записавши собі в блокнот завдання почитати після прототипу про те, як влаштований оператор Кенні.
lambdax x: feature.canny(color.rgb2gray(x[40:360, 110:630]))

3, canny
Їде над заштрихованої водою тролейбус виглядає досить красиво. Бути може, нудьгуючи і цією красою, mkot шкодує, що переїхав з Петербурга :-) Але ця картинка погано проходить наївний тест Ина — вона візуально виглядає гучною. Доведеться прочитати документацию далі першого аргументу функції. Видається логічним, що якщо кордонів занадто багато, то можна розмазати картинку пропонованим фільтром Гаусса. Значення за замовчуванням —
1
, спробуємо його збільшити.
lambdax x: feature.canny(color.rgb2gray(x[40:360, 110:630]), sigma=2)

4, sigma
Це вже більше схоже на дані, ніж на штрихи простим олівцем. Але є інша проблема, у цієї картинки 166400 пікселів, а кадрів за ніч збирається пару-трійку тисяч, т. к. місце на диску ноутбука не нескінченне. Напевно, якщо взяти ці бінарні пікселі як є, класифікатор просто переобучится. Застосуємо ще раз метод "в лоб" — стискаємо її в 20 разів.
lambda x: transform.downscale_local_mean(feature.canny(color.rgb2gray(x[40:360, 110:630]), sigma=2), (20, 20))

5, features
Це все ще схоже на мости, але і зображення тепер все 16x26, 416 пікселів. Маючи кілька тисяч кадрів на такому безлічі недо-фіч вже не дуже страшно вчитися і займатися крос-валідацією. Тепер непогано б вибрати топологію нейронної мережі. Колись Сергій Михайлович Добровольський, який читав нам лекції з мат. аналізу, жартував, що для передбачення результату виборів президента США досить одного нейрона. Здається, міст — не набагато більше складна конструкція. Я спробував навчити модель логістичної регресії. Як і очікувалося, міст влаштований не набагато складніше виборів, і модель дає цілком пристойна якість з двома-трьома дев'ятками на всяких різних метриках. Хоча такий результат і виглядає підозріло (напевно в даних все погано з мультиколлинеарностью). Приємним побічним ефектом є те, що модель передбачає вірогідність класу, а не сам клас. Це дозволяє намалювати кумедний графік, як процес розведення Палацового мосту виглядає для "нейрона" робота в реальному часі.
6, розводка
Залишається прикрутити до цієї конструкцію push-повідомлення і який-небудь інтерфейс, що дозволяє подивитися на міст очима, якщо класифікатор дав збій. Перше виявилося зробити простіше всього за допомогою Telegram-бота, який відправляє повідомлення в канал @SpbBridge. Друге — з костыликов, bootstrap і jquery зробити веб-мордочку з прямим ефіром.
Навіщо я це все написав?
Хотів нагадати, що у кожної проблеми є просте, всім зрозуміле неправильне рішення, яке тим не менш може бути практичним.
І ще, поки я писав цей текст, дощ, здається, сенс в Неву камеру, яка дивилася на Палацовий міст разом з сервером vpiter.tv, про що робот оперативно і повідомив.
7, nomorecam
Я буду радий, якщо ви в ім'я відмовостійкості захочете поділитися своєю веб-камерою, що дивиться на який-небудь розвідний міст. Раптом, наприклад, ви працюєте в СПб ЦКУ «ГМЦ» :-)
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.