В этом году пришла идея: воплотить классическое клише из фильмов ужасов — скримера с зеркалом. Помните те сцены, где отражение внезапно показывает монстра, призрака или что-то подобное? Камера, Raspberry Pi, и библиотека OpenCV могут напугать кого угодно. Не верите?! Поскольку на телевидение не пускают (и правильно делают), создадим жуткую видеотрансляцию в старом черно-белом телевизоре. Система активируется при обнаружении лица или глаз.

Когда Raspberry Pi замечает лицо, он включает телевизор и выводит на него живое изображение с камеры. Как только человек отворачивается, на заднем плане появляется призрак (с помощью технологии вычитания фона). Несчастный снова смотрит на экран, видит фантома, радуется, хватается за сердце и оборачивается во второй раз — призрак исчезает. Через несколько секунд телевизор выключается, и цикл начинается заново.

Мы также реализуем распознавание глаз, чтобы система работала, даже если подопытный в маске. (Вдруг это грабитель?)

Краткий обзор

В первом шаге обсудим вдохновение, а затем предоставим список всего необходимого для самостоятельной сборки.

Далее увидим, как настроить Raspberry Pi для запуска нашей программы. После разберемся, как работают алгоритмы распознавания лиц и глаз, а также удаления фона. Затем последует пошаговое руководство по сборке, а в конце — раздел по устранению неполадок.

Погнали! Ну, телезритель, берегись!

Источник вдохновения

Видео с сайта автора оригинального текста gorkem.cc.

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

  1. Персонаж подходит к зеркальному шкафчику, и мы видим его отражение.

  2. Он открывает дверцу или отвлекается на что-то.

  3. Затем снова смотрит в зеркало и видит, что за его спиной кто-то стоит (обычно кто‑то жуткий, но даже если это будет улыбающаяся девочка с букетиком, то легче не станет).

  4. Наша жертва вскрикивает, стремительно оборачивается — а никого и нет!

Вот подборка подобных сцен из разных фильмов, для лучшего представления:

Видео с YouTube‑канала richfofo.

В обычном зеркале воссоздать этот эффект невозможно по очевидным причинам. Пришлось подобрать носитель, на который выводится изображение. Старый потрепанный телевизор подошел как нельзя лучше. Низкое разрешение и помехи дают неповторимый эффект: будто старый ящик — и есть окно в параллельную, но искаженную реальность. Так и родилась эта идея.

ML Impact — про ML и AI без хайпа

Все кругом говорят про ML, но многие ли понимают его настоящую пользу для бизнеса? Мы запустили ресурс, который поможет во всем разобраться.

Подробнее →

Инструменты и компоненты

Все необходимые файлы (для 3D-печати и код) — в репозитории проекта по этой ссылке.

Инструменты:

  • 3D-принтер (необязательно, если есть возможность вырезать детали из дерева, акрила или другого материала);

  • дрель;

  • паяльник.

Компоненты:

  • Raspberry Pi 3 или новее (чем выше производительность, тем меньше задержка);

  • камера для Raspberry Pi;

  • кинескопный (ЭЛТ) телевизор;

  • AV-RF конвертер (если у телевизора нет композитного входа);

  • модуль дистанционного управления YK04;

  • релейный модуль KY-019 на 5 В;

  • 4 резьбовые стойки М2.5;

  • 4 гайки и болты М2.5;

  • 2 резистора на 330 Ом;

  • композитный видеокабель для Raspberry Pi.

Детали для 3D-печати:

  • крепление для Raspberry Pi,

  • крепление для камеры.

Настройка Raspberry Pi

Этот шаг можно пропустить, если у вас уже установлена Raspberry Pi OS.

Установка Raspberry Pi OS

Для первоначальной настройки Raspberry Pi понадобятся клавиатура, мышь и монитор.

Прежде чем мы перейдем к программе, нужно подготовить наш одноплатный компьютер. Воспользуемся официальным руководством по установке операционной системы на Pi. Убедимся, что устанавливаем версию Raspberry Pi OS (32-bit) with desktop and recommended software. В этом дистрибутиве уже есть все программное обеспечение, необходимое для нашего кода.

После установки операционной системы и запуска Raspberry Pi вводим в терминале:

sudo raspi-config

Команда выше откроет меню конфигурации. Переходим в Interfacing Options, включаем камеру (Camera) и SSH. Активация SSH даст возможность подключаться к Raspberry Pi удаленно, чтобы каждый раз не использовать клавиатуру, мышь и монитор.

Теперь наш одноплатный компьютер готов к работе с кодом! На следующем шаге подключим к нему камеру и электронику, а затем протестируем все вместе.

Сборка электроники

На этом этапе паяльник можно пока не брать. Мы настоятельно рекомендуем воспользоваться макетными проводами (джамперами), чтобы можно было легко заменить любой компонент, если он не заработает как надо.

Распиновка GPIO на Raspberry Pi

Мы использовали физическую нумерацию контактов, которую взяли на странице Raspberry Pi OS.

Камера

Порт для камеры находится между выходом HDMI и аудиоразъемом. Вставляем шлейф камеры так, чтобы открытые контакты на нем были обращены к порту HDMI.

Подключение модулей

Подключаем приемник, RGB-светодиод и реле к Raspberry Pi с помощью джамперов, как показано ниже.

Приемник YK04

Контакт

Контакт Raspberry

YK04

Pi 3

GND

GND

POWER

3.3V

D0

12

D1

16

RGB-светодиод

Контакт LED

Контакт Raspberry Pi 3

GND

GND

RED

22

GREEN

24

BLUE

26

Реле

Контакт Relay

Контакт Raspberry Pi 3

GND

GND

POWER

5V

Data

32

Программный код

Для распознавания лиц и удаления фона будем использовать OpenCV (Open Source Computer Vision Library) — библиотеку компьютерного зрения с открытым исходным кодом. Установим ее на наш Pi.

Установка OpenCV

Python-модуль OpenCV можно загрузить из репозитория Raspbian. Для этого просто открываем терминал и вводим:

sudo apt update
sudo apt install python3-opencv

Эта команда скачает и настроит все пакеты, необходимые для работы OpenCV. После установки перезагружаем Pi:

sudo reboot

Код для «Телевизора с привидениями»

Сначала переходим в папку Documents:

cd Documents

Затем загружаем код проекта из репозитория на GitHub:

git clone https://github.com/gocivici/haunted-tv.git  

Команда выше скачает самую свежую версию кода. После — переходим в папку проекта:

cd haunted-tv

Наконец, запускаем программу:

python3 hauntedTV.py

Для тестирования и отладки кода можно использовать клавиатуру вместо пульта. Нажимаем h, чтобы сделать «фото с призраком», и a, чтобы запустить распознавание лиц.

Примечание

Если при запуске кода возникает ошибка, загляните в руководство по устранению неполадок в конце статьи.

Автозапуск

Нам нужно, чтобы наш скрипт запускался автоматически при загрузке Raspberry Pi. Для этого воспользуемся методом под названием Autostart. При таком подходе сначала инициализируется графический интерфейс, а затем запускается наш скрипт.

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

Открываем терминал и вводим:

mkdir /home/pi/.config/autostart
nano /home/pi/.config/autostart/hauntedTV.desktop

Теперь копируем приведенное ниже содержимое в только что созданный файл:

Type=Application
Name=HauntedTV
Exec=/usr/bin/python3 /home/pi/Documents/haunted-tv/hauntedTV.py

Сохраняем, выходим с помощью Ctrl + X и перезагружаемся:

sudo reboot

Кастомизация

Чтобы отредактировать код, находясь в каталоге проекта, вводим:

sudo nano hauntedTV.py

Для правильной работы скримера важны три таймера:

timeTV = 5
timeGhost = 25
timeNoGhost = 10

Важно понимать — эти значения заданы не в секундах. Они привязаны к счетчику faceFreqCounter, который запускается при обнаружении лица и продолжает считать, пока лицо остается в кадре. Если человек пропадает с экрана более чем на 4 секунды, счетчик сбрасывается на 0 (таким образом, отсеиваются ложные срабатывания).

  1. timeTV — когда faceFreqCounter достигает этого значения, телевизор включается.

  2. timeGhost — значение faceFreqCounter когда появляется призрак после того, как человек отведет взгляд — можно установить значение побольше, если нужно, чтобы гости подольше разглядывали телевизор перед появлением фантома.

  3. timeNoGhost — продолжительность отображения призрака после отвода взгляда.

Также стоит настроить чувствительность фона в коде.

backgroundSensitivity = 20

Эта переменная определяет чувствительность алгоритма вычитания фона. Значение следует увеличить, если «призрачное» изображение не видно на заднем плане.

Готово! Теперь пора протестировать всю систему с вашим телевизором.

Распознавание лиц/глаз и удаление фона (опционально)

Разберем же подробно, как использовать OpenCV для обнаружения лиц и удаления фона. Этот шаг можно и пропустить, если хочется просто скачать и запустить готовый код.

Распознавание лиц/глаз с помощью OpenCV

Существует много методов для обнаружения лица. Мы использовали «распознавание объектов с помощью каскадов Хаара» — алгоритм машинного обучения, который может находить объекты на изображении на основе набора признаков.

Такой метод можно использовать для обнаружения любых объектов, а не только лиц. Чтобы найти лицо, понадобятся каскадные файлы. Любая поисковая система поможет найти различные каскады для распознавания нужных объектов. Нам же потребуется каскад для лиц и каскад для глаз.

После загрузки каскадов в виде .xml файлов импортируем их в наш код:

import numpy as np
import cv2

# importing the cascades
detected = cv2.CascadeClassifier('haarcascade\_frontalface\_default.xml')
# detected = cv2.CascadeClassifier('haarcascade\_eye.xml')

Пока что мы импортируем только каскад для лиц. Как упоминалось в предыдущем шаге, код можно настроить на обнаружение лиц, глаз или и того и другого.

Далее запускаем камеру и инициализируем цикл while, чтобы код постоянно проверял присутствие лица:

cam = cv2.VideoCapture(0)
while True:
    ret, img = cam.read()
    gray = cv2.cvtColor(img, cv2.COLOR\_BGR2GRAY)
    faces = detected.detectMultiScale(gray, 1.3, 5)

Классификатор каскадов detectMultiScale просто находит лица. Теперь создаем цикл, чтобы нарисовать прямоугольник вокруг обнаруженных лиц.

for (x,y,w,h) in detected:
    cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
    #put code here to run when a face is detected

Наконец, выводим итоговое изображение в окне:

cv2.imshow('img',img)

Вот полный код для распознавания лиц:

import numpy as np
import cv2

# importing the cascades
detected = cv2.CascadeClassifier('haarcascade\_frontalface\_default.xml')
#detected = cv2.CascadeClassifier('haarcascade\_eye.xml')

cam = cv2.VideoCapture(0)
while True:
    ret, img = cam.read()
    gray = cv2.cvtColor(img, cv2.COLOR\_BGR2GRAY)
    faces = detected.detectMultiScale(gray, 1.3, 5)
    for (x,y,w,h) in detected:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
        #put code here to run when a face is detected
    cv2.imshow('img',img)
cam.release()
cv2.destroyAllWindows()

Сохраняем этот файл под именем, скажем, FaceDetection.py и запускаем. Испытываем на себе: вокруг лица должен появиться синий прямоугольник.

Удаление фона с помощью OpenCV

Нам нужен алгоритм для замены части фона на «призрачное» изображение. Так мы сможем поместить призрак позади человека. Это важная особенность, поскольку мы хотим создать эффект, будто за спиной действительно кто-то есть.

В поисках решения попался очень хороший туториал на YouTube. В этом руководстве показывается, как заменить фон на видео.

Видео с YouTube‑канала Misbah Mohammed.

Однако для наших целей код нужно слегка адаптировать. По триггеру требуется отображать статичное  изображение, а не видео.

Существуют и другие методы вычитания фона, которые можно использовать:

Первый прототип и тест

Видео с сайта автора оригинального текста gorkem.cc.

Для первого прототипа соберем регулируемую подставку для камеры и установим ее на телевизор вместе с Raspberry Pi. На этом этапе главная задача — протестировать сборку и телевизор, чтобы убедиться, что все работает правильно. Итак, шаги будут следующими:

  1. Подключаем Raspberry Pi к телевизору с помощью композитного кабеля (если у ТВ нет такого входа, используйте AV-RF конвертер).

  2. Подключаем Raspberry Pi к питанию и ждем, пока он загрузится.

  3. Проверяем, нет ли проблем с видеосигналом.

Дизайн и 3D-печать

Для этой сборки есть две детали, напечатанные на 3D-принтере. Первая — крепление для Raspberry Pi, которое будет приклеено внутри телевизора. Вторая деталь — крепление для камеры, которое поможет нам ее установить.

Примечание

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

Использовался принтер TEVO Tornado со следующими настройками:

  • сопло: 0,4 мм,

  • заполнение: 30%,

  • филамент: PLA.

Пайка

Припаять нужно две вещи: светодиод и антенну для приемника.

Разборка и чистка телевизора

Внутреннее устройство телевизора несет прямую угрозу для жизни!

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

Не подносите ничего даже близко к частям кинескопа, не вставляйте никакие предметы в зарешеченные части. Никогда не включайте телевизор со снятой задней стенкой!

Мы настоятельно рекомендуем прочитать инструкцию от MrJentis на эту тему: «How to Dismantle a CRT Monitor».

Сборка

Raspberry Pi

Камера

Есть элегантный способ разместить камеру — используем отверстие от старого разъема для наушников на телевизоре и монтируем камеру в него.

Финальная сборка и тест

Видео с YouTube‑канала Görkyver.

Теперь, когда Raspberry Pi установлен в телевизор, подаем питание на всю систему. Одноплатный компьютер загрузится и запустит Python-скрипт при старте. Через несколько секунд должен включиться телевизор, а вы — увидеть в нем себя.

Далее находим жуткий костюм, встаем перед экраном с пультом и делаем «фото с призраком», нажав кнопку B на пульте.

Теперь все готово! Нажимаем кнопку D на пульте — телевизор должен выключиться и начать распознавать лица.

Тестирование

Проверяем работу системы: встаем перед телевизором и через несколько секунд отворачиваемся. Должен запуститься скрипт, а на заднем плане возникнуть «призрачное» изображение. Если не получается — переходите к руководству по устранению неполадок.

Устранение неполадок

«Призрачное» изображение не видно

Освещение очень важно для удаления фона. Убедитесь, что перед телевизором светло. Также попробуйте разместить источник света так, чтобы он находился за телевизором и освещал вас, а не объектив камеры.

Я не уверен, работает ли распознавание лиц

Вернитесь к разделу про программный код и запустите скрипт распознавания лиц отдельно. Вы должны увидеть прямоугольник вокруг своего лица.

ЭЛТ-телевизор не отображает картинку.

Откройте файл config.txt на вашем Raspberry Pi и убедитесь, что регион ТВ (TV region) совпадает с регионом вашего телевизора.

На живой трансляции большая задержка/лаги.

Для проекта был взят Raspberry Pi 3. Любая другая модель с меньшей вычислительной мощностью может вызывать задержки и лаги. Но есть и оптимизации, которые можно предпринять.

Примечание переводчика

Автор оригинальной статьи когда‑то предлагал описывать проблемы в комментариях. Проект закрыт, и мы вряд ли можем рассчитывать на его помощь в таком формате. Если кто столкнется с трудностями при воплощении задумки — предлагаю два варианта.

1. Пробуйте обращаться к автору напрямую.

2. Пользуясь тем, что на Хабре сконцентрировалось сильнейшее IT‑сообщество, задавайте вопросы в комментариях здесь и под свежими профильными статьями.

Что дальше

В этом разделе перечислим еще несколько идей, на которые не хватило времени или ресурсов:

  • Bluetooth-колонка, чтобы издавать звук, когда сзади появляется призрак;

  • инфракрасная камера и светодиоды, чтобы все работало в темноте — атмосфера получится еще страшнее;

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

  • более мощный компьютер, например, Nvidia Jetson, который создан для задач компьютерного зрения — задержек точно не будет.

Комментарии (2)


  1. JBFW
    23.08.2025 13:12

    Бодрая музычка и приветствие типа "добро пожаловать в наш дом!". Живая видеосъёмка, как в шоу-руме систем видеонаблюдения, потом "кхе-кхе" где-то сбоку - и вот на экране вы видите за своей спиной ту девочку с букетиком...

    А в реальности не видите


    1. oneastok Автор
      23.08.2025 13:12

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