![](https://habrastorage.org/webt/q9/a8/ds/q9a8dslttmbpxjznmlvdj5kzlvg.jpeg)
Всю мою жизнь мне нравятся средства отображения информации — в виде электронно-лучевых трубок. В них есть определённый романтизм и шарм. Недаром их часто используют в иллюстрациях к фильмам антиутопиям.
В конце 2000-х набирали популярности социальные сети с фотографиями. И мне очень не хватало в те годы настоящего живого фильтра, который делает эффект телевизора. В один из прекрасных дней мне встретился проект, где из видоискателя от видеокамеры и фотоаппарата, сделали аппаратный фильтр для фотографий. Проект, когда я его встретил, уже не работал, а значит поле было не занято. Понял, вот это оно! И с тех пор идея поселилась в моей голове.
Как вы понимаете, этот проект — самый эпичный долгострой в моей жизни, раз я задумал его ещё в конце 2000-х. Где-то примерно в году 2015 он работал для друзей, и даже в 2016 году он ездил на Chaos Construction. Но это всё было не то, интерфейсы не те. И вот, наконец проект завершён, и может быть показан широкому зрителю.
А прежде, чем вы залезете под кат, можно сразу попробовать отфильтровать картинку — достаточно просто зайти в мой телеграмм бот.
Поехали, ниже много аппаратной жести.
Концепция
Идея достаточно проста, родилась она в то время, когда автоматическая обработка фотографий только набирала обороты, и всякие аппаратные решения могли бы быть достаточно забавными.
На чёрно-белый ЭЛТ-монитор выводится картинка, затем фотографируется камерой, а дальше уже сводятся цвета.
Вообще, те, кто давно следят за моим творчеством, могут сопоставить несколько статей по данной теме. Например, когда я искал монитор, то в качестве него хотел использовать видоискатель от старой видеокамеры. Так получилась статья «Мини ЭЛТ монитор». Но, к сожалению, экран от видеокамеры оказался слишком мал для таких целей. Поэтому, в дальнейшем, я приобрёл небольшой чёрно-белый охранный монитор, который был больше по размерам и оказался намного более удобным для моей задачи.
![](https://habrastorage.org/webt/4g/ru/pc/4grupcczeluk2sr1-8tbkitk1x0.jpeg)
В процессе экспериментов я подбирал различные камеры. Вообще, хотел использовать зеркальный фотоаппарат и даже пробовал его подключать. Это вы читали в статье «Старый фотик + bash = таймлапс». К сожалению, из-за малого ресурса, а также всяких аппаратных косяков — решил отказаться от этого варианта. Остановился на Raspberry Pi и малиновой камере.
От идеи до готового прототипа
![](https://habrastorage.org/webt/k-/pp/dn/k-ppdny0eu3nh8j_jtgubh9j3j0.jpeg)
Сразу стало понятно, что для реализации всей задумки, мне понадобится готовый стенд. Он должен удовлетворять следующим параметрам:
- Быть закрытым, чтобы не было бликов на мониторе.
- Быть носимым, чтобы можно было перемещать по квартире.
- В нём должна обеспечиваться достаточная вентиляция, чтобы монитор не перегревался.
- Необходимо иметь возможность в широких пределах менять месторасположение камеры и жёстко её фиксировать.
▍ Фанерный ящик
Первое, что было изготовлено — это фанерный ящик. Тут никаких хитростей нет, разве что съёмная боковая и верхняя крышка. Для уменьшения бликов изнутри был окрашен чёрной тушью. Это было сделано по неопытности, идеальная краска, с хорошим светопоглащением, доступная в любом магазине — это акриловая газовая сажа.
Ящик не так прост, как кажется на первый взгляд. Как я уже сказал, необходимо обеспечить охлаждение, поэтому ящик располагается на ножках, которые просто вырезаны из той же фанеры, с набойкой из войлока. Это нужно, чтобы снизу было пространство для движения воздуха. В месте установки монитора — сделаны отверстия воздухозабора (там же, где они у самого монитора) и отверстия под его ножки. Для удобства подключения — сзади установлена обычная розетка, куда подключается монитор и блок питания одноплатника.
![](https://habrastorage.org/webt/mm/nv/2i/mmnv2ik7u5-hd-rj15nxfofghae.jpeg)
![](https://habrastorage.org/webt/in/ku/nn/inkunnelc0si0w0lg6ym4dewva8.jpeg)
Для того чтобы камеру точно можно было позиционировать внутри, и она не сдвигалась в процессе эксплуатации, внутри решено было сделать деревянные рельсы. Изначально попробовал посмотреть, как это будет выглядеть из бросового материала — утеплителя.
![](https://habrastorage.org/webt/wf/3j/ex/wf3jexer16amncgycuhuqesult4.jpeg)
Рельсу изготовил из соснового щита. Не самый лучший материал для таких целей, слишком мягкий. Но для разовой установки подойдёт.
![](https://habrastorage.org/webt/qy/gw/zj/qygwzj76b2-l9a0eke3fei4stmi.jpeg)
Когда стало понятно, что это крепление наиболее оптимально, я выпилил все необходимые детали на лобзиковом станке для установки болтов. Они нужны для регулировки высоты и наклона камеры. Прорезь нужна, чтобы можно было смещать камеру поперёк оси. Не знаю, как корректно именовать этот элемент, назову суппортом.
![](https://habrastorage.org/webt/xh/lc/7t/xhlc7tobe-iam2crtcbtemwimvi.jpeg)
![](https://habrastorage.org/webt/un/j5/dr/unj5drsz05v2pn1wvd9hqf5ijny.jpeg)
В результате всех примерок и перестановок получился следующий готовый прототип.
![](https://habrastorage.org/webt/g0/ao/ra/g0aora0xvuquuxrsxnnobwidpiw.jpeg)
На фотографии не видно, но суппорт прижимается к рельсам с помощью барашка. Это оказалось не очень удобно, и дальше я решил сделать фанерный диск с запрессованной гайкой.
▍ Окончательная сборка
Поскольку проект растянулся на много лет, и описать все события с ним, в рамках одной статьи, невозможно, основной акцент я дам только на последних изменениях. Аппаратные решения минувшего прошлого я просто не помню, всё это было утрачено в веках.
Мозгами всего устройства выступает Raspberry Pi 4, для камеры взял устаревший модуль V2. Поскольку всё работает в закрытом корпусе, для лучшего охлаждения одноплатника приобрёл дополнительный корпус-радиатор с вентиляторами.
![](https://habrastorage.org/webt/e2/q2/tz/e2q2tz9dmxmdj4qawc5c0yhsvjk.jpeg)
После чего всё примеряю по месту и думаю об оптимальном расположении элементов.
![](https://habrastorage.org/webt/lk/b3/vi/lkb3vin2lykvwsprsm12das7w_y.jpeg)
Самое сложное было сделать крепление камеры. Необходимо было обеспечить жёсткость крепления так, чтобы камера не болталась и не дрожала. Перепробовал несколько вариантов, самым оптимальным оказалось крепление на винтах М2, между гаек.
![](https://habrastorage.org/webt/e5/ru/gf/e5rugfebmbjg1gxys4dllzbhnbe.jpeg)
После всех манипуляций мне показалось, что слишком уж больно весело и светло всё выглядит, и я решил дополнительно окрасить всё газовой сажей. На фотографии ниже — видна фанерная прижимная гайка.
![](https://habrastorage.org/webt/e0/ms/eb/e0msebq4yck6v9zzflid9nmq6dk.jpeg)
После всех манипуляций эмпирическим путём было установлено, что совсем без света в ящике нельзя. Потому что не будет видно стильную рамку самого монитора. А самое главное, камера будет постоянно настраивать отдельную яркость под каждую картинку и картинка будет получаться неодинаковой освещённости. Поэтому внутрь установил световое кольцо, и на заднюю стенку поставил лист обычной бумаги. Между кольцом и суппортом проложил лист бумаги, покрашенный чёрной краской, чтобы не было засветов снизу, и не сияли металлические болты в кадре.
![](https://habrastorage.org/webt/ho/ll/5l/holl5lqtzhhcrztm3cphnkxuqyc.jpeg)
Недостаток лампы в том, что на некоторых картинках можно видеть отсвет силуэта крепления камеры. Но пусть это будет не бага, а фича, которая показывает что установка реальная, аппаратная.
Всё укомплектовано, засветов лишних практически нет. Теперь всё готово к настройке и разработке софта.
![](https://habrastorage.org/webt/_s/fb/eb/_sfbebpx6cb-n0msi3kajzind2w.jpeg)
![](https://habrastorage.org/webt/vk/vz/qg/vkvzqgogrqdhpkft8lbuazqpn64.jpeg)
Настройка и разработка софта
Самая сложная часть — это не собрать ящик, хоть эта часть выглядит круто и понятна каждому. Самая сложная и скрытная часть — это настроить всё, и разработать ПО.
▍ Корректная установка камеры
Для меня это самая муторная задача, потому что надо в течение нескольких часов двигать суппорт и крутить винты. И да, я до сих пор недоволен идеальностью выставленной камеры.
В первый раз я выставлял камеру достаточно хитрым способом: скачал на DVD-диск специальные настроечные таблицы и выводил с помощью проигрывателя эти таблицы на монитор, а на телевизор выводил результат того, что снимает камера.
![](https://habrastorage.org/webt/p3/ef/bz/p3efbzhtjicufcd6rcsinxcrodq.jpeg)
Сейчас такими глупостями заниматься я не стал, потому что ни телевизора, ни плеера у меня уже нет. Поступил сильно проще, я открыл документацию на камеру для малины. И просто сделал трансляцию того, что она выводит в VLC. Главное поставить разрешение поменьше, а с помощью fbi (Linux framebuffer imageviewer) выводил на экран обычную настроечную таблицу для чёрно-белых телевизоров и старался, чтобы она хоть как-то совпадала с тем, что я должен увидеть.
![](https://habrastorage.org/webt/v1/qh/vl/v1qhvlyrpgzq5hjdetaazl0bnui.png)
Можно использовать и цветную. По ней сначала визуально настраиваю яркость-контраст монитора, а потом в течение нескольких часов двигаю суппорт туда-сюда, вдоль и поперёк рельсы, поднимаю-опускаю камеру, изменяю угол наклона так, чтобы квадраты были более-менее одинаковыми, и горизонт был не очень сильно завален.
В общем, после многочасовой изнуряющей настройки положения камеры, яркости монитора и всевозможных крутилок, можно убедиться, что результат получился нормальным. Далее предстоит кропотливый труд разработки ПО.
![](https://habrastorage.org/webt/dq/nt/hz/dqnthzlq5h-klg1jabkww1vq0uy.jpeg)
▍ Позвольте, а откуда цвет?
Внимательный читатель заметил, что в своём проекте я использую чёрно-белый монитор. Можно даже потрудиться, найти на него документацию и убедиться, что цвет он выводить не умеет. Но как же можно получить цветное изображение?
Всё просто, берётся цветная картинка, например:
![](https://habrastorage.org/webt/qb/3e/7h/qb3e7hyeijwdpkwdxv_otdgoefk.png)
И разделяется на три канала по цветам (делается это программно).
![](https://habrastorage.org/webt/85/y_/yl/85y_ylhp93bzuxwr4vhjm3kgk1m.png)
Далее, каждый цвет отдельно выводится на монитор и фотографируется:
![](https://habrastorage.org/webt/zc/o4/1x/zco41xw6ollsz6zyb4xzndq_jkc.png)
После чего, все три кадра снова сводятся единую фотографию и получается снова цветное изображение.
![](https://habrastorage.org/webt/i8/eq/9o/i8eq9ohjdq5alfwwnjori-ohdsc.png)
Виден засвет тёмной области, это именно та проблема, которая возникает в абсолютно тёмном ящике. Поэтому и нужен контр-свет.
▍ Разработка софта. Серверная часть
В первоначальном прототипе у меня был вебсайт, где всё работало через CGI. Но это было не самый удобный вариант и по многим параметрам он мне не нравится. Поэтому было принято волевое решение шагать в ногу со временем и сделать telegram-бота. Сам бот — это для меня запредельная магия (шучу), я потыкал в него палочкой и не смог реализовать. Поэтому слёзно просил помочь мне его сделать man_of_letters. О подобном боте у нас есть отличная статья «Проект — электрический помощник для редакции». С небольшими изменениями из него получился бот для получения и отдачи фотографий пользователю. Более подробно рассказать не смогу, потому что сильно код бота не ковырял.
API работы устроено достаточно просто:
- Бот принимает картинку от пользователя, шинкует её на три канала цвета RGB и сохраняет картинки в png с соответствующими именами.
- После успешной шинковки создаёт просто пустой файл, с именем трёх файлов. Создание этого файла и имя файла является ключём для того, чтобы начать обработку.
- После того как моё устройство заберёт эти файлы, перемелет их, а далее складывает обратно — все три обработанных файла в другую папку. Бот их сводит и отдаёт клиенту.
Итого, у меня три папки, которые и являются API для взаимодействия с ботом. Для работы с ними решили использовать протокол ssh, потому что это удобно, надёжно и просто. Как же я ошибался…
▍ Клиентская часть
Основная проблема работы по ssh — это держать постоянное подключение. И оказалось, что при длительном соединении постоянно «лопалась труба» (ошибка broken pipe).
![](https://habrastorage.org/webt/aa/eg/vl/aaegvlc_qo8v3gw5tmauwp2n5m0.jpeg)
Лопнувшие трубы ssh соединения сильно портили малину, и порой даже бились данные. Решила эти проблемы следующая статья. Но, изначальный сервер у нас был на Debian, любезно предоставленный компанией RuVDS, а там этот фокус вообще чуть не погасил весь ssh. Поэтому в срочном порядке пришлось переехать на сервер с Ubuntu 20.04. Для наших задач хватит самой простецкой конфигурации.
Далее там создаём файл:
sudo vim /etc/ssh/sshd_config.d/alive.conf
И добавляем туда следующие строки:
ClientAliveInterval 30
ClientAliveCountMax 30
TCPKeepAlive no
И не забываем перезапустить sshd-демон:
sudo systemctl restart ssh
Теперь возникает другой вопрос: как на стороне клиента aka Raspberry Pi мониторить создание файла на удалённом сервере?
Изначально для этих целей я использовал приложение inotifywait и отслеживал создание новых файлов, вот такой совершенно страшной конструкцией и далее в теле while уже делал все свои грязные дела:
ssh teleuser@$server inotifywait -e create /****/workaround --format "%f" -q -m| while read file; do
...
Но длительные тесты показали, что такой подход неэффективен: теряется часть файлов, и в случае потери соединения, мы уже не будем знать, что там произошло. Поэтому сделал на обычном ls, сортируя по дате добавления в обратном порядке, и по очереди пробегаясь по каждому файлу. И всё это запихал в большой цикл while. Не элегантно, но работает.
ssh teleuser@$server ls -1tr /*****/workaround | while read file; do
Вывод на экран делаю в консольном режиме, используя стандартную программу вывода во фреймбуффер:
sudo fbi -T 2 --nocomments --noverbose -a /***/hipcrt/${file%.*}$num.png
Самое сложное было разобраться с тем, как это фотографировать. Когда-то, давным-давно, я использовал приложение raspistill, но с тех пор много воды утекло и появилось другое приложение.
Необходимо было подобрать оптимальное разрешение, чтобы было всё чётко видно, и не занимало много места, и настроить выдержку с таким параметром, чтобы картинка успела отрисоваться вся, и при этом не было пересвета и баланс белого.
![](https://habrastorage.org/webt/jd/kp/zt/jdkpzt51zyciv-v3tzuqlwoabhk.jpeg)
Пример неудачно подобранной выдержки, когда идут разноцветные полосы из-за того, что кадр не успел отрисоваться весь.
В результате после небольшого НИР получилась следующая команда:
libcamera-still -n --width 800 --height 600 -o /****/hipcrt/result/${file%.*}$num.jpg -e jpg --shutter 125000 -t 500 --awb fluorescent
Итоговый скрипт получился простым и лаконичным. В этом скрипте происходит удаление всех временных файлов, то есть пользовательские файлы на сервере не хранятся, для экономии места, и мы их увидеть, увы, не можем.
#!/bin/bash
server=***.***.***.***
while true
do
sleep 0.1
ssh teleuser@$server ls -1tr /*****/workaround | while read file; do
scp teleuser@$server:/*****/pic_from_user_split/${file%.*}* /*****/hipcrt/
ssh teleuser@$server rm -f /*****/workaround/$file
ssh teleuser@$server rm -f /*****/pic_from_user/${file%.*}*
ssh teleuser@$server rm -f /*****/pic_from_user_split/${file%.*}*
for num in "_r" "_b" "_g"
do
sudo fbi -T 2 --nocomments --noverbose -a /*****/hipcrt/${file%.*}$num.png
sleep 0.5
sudo libcamera-still -n --width 800 --height 600 -o /*****/hipcrt/result/${file%.*}$num.jpg -e jpg --shutter 125000 -t 500 --awb fluorescent
done
sudo killall fbi
scp /*****/hipcrt/result/${file%.*}* teleuser@$server:/*****/pic_from_crt/
rm -f /*****/hipcrt/*.png /*****/hipcrt/result/*
done
done
exit 0
На самом деле, я как-то так легко и просто всё расписал, но в реальности — вся эта куча экспериментов и опытов вылилась в недели работы, потому что было неясно, где и что отваливается.
Так, и где же я могу всё это попробовать?
![](https://habrastorage.org/webt/gl/3x/as/gl3xas698srj5xx3ji-7whghn_k.jpeg)
Хочется уже попробовать, правда? Такая краткая инструкция для начинающих:
- Бот обитает по следующему адресу.
- Заходим в него и жмём «запустить».
- После этого у вас появится меню.
- Выбираем «Обработать новое изображение» и скармливаем любой графический файл со сжатием.
После этого ваше изображение добавляется в очередь. Обработка каждого изображения занимает 15 секунд, поэтому из-за хабраэффекта, пожалуйста, соблюдайте терпение, все получат свои картинки рано или поздно. С телефона всё выглядит вот так.
![](https://habrastorage.org/webt/yz/-f/z_/yz-fz_u_ea-2igenwffuajdb9ss.jpeg)
![](https://habrastorage.org/webt/jr/sc/ul/jrsculjdveqr1dv9cgnmm54myii.jpeg)
Чтобы канал не забил один крепкий кликер фоток — там стоит антиспам, ограничивающий количество фотографий от одного человека. Так что выбирайте фотографии лучше.
Заключение
![](https://habrastorage.org/webt/sm/oi/li/smoiliqgblovhusgvv7lcuuy4fi.jpeg)
В моей жизни — этот проект самый эпичный долгострой, который всё же был реализован и доведён до конца. Проект меня многому научил. Когда я делал сайт, то впервые вообще столкнулся с js, php и вообще web-программированием, CGI вообще был для меня пустым звуком, а ещё разработка своих скриптов… Всё это стало для меня замечательным опытом и дало весьма неплохой навык, который пригодился в моей дальнейшей работе.
Да, сам проект может быть глупым и абсурдным, но лично меня он научил очень многому, и я благодарен, что он состоялся.
Главное я благодарен всем моим друзьям, которые мне помогали с этим проектом. Не буду перечислять всех по именам, вы все молодцы. Громадное спасибо man_of_letters за помощь с сайтом в начале пути, и за помощь с ботом в завершении проекта. Компании RuVDS за помощь в подготовке этого проекта.
А главное, вам мои дорогие читатели, за то, что будете его использовать и понимать что это просто прикольно!
HIPCRT_BOT
И напоследок, вот видео, которое изготовлено на этом аппарате. Понадобился день, чтобы обработать все кадры этого короткого видеоролика.
З.Ы. Если всё будет хорошо, постараюсь чтобы аппаратная часть проработала не меньше месяца!
Telegram-канал с полезностями и уютный чат
![](https://habrastorage.org/webt/sz/7j/pf/sz7jpfj8i1pa6ocj-eia09dev4q.png)