Четверг, 01 ноября 2018 11:12

Одержимая картина.

Оцените материал
(3 голосов)

Используя Raspberry Pi 3 B, Python и AtmosFX видео мы созданим одержимую картину которая будет пугать прохожих.

 

Что мы использовали

  1. Raspberry Pi 3 Model B
  2. Инфракрасный сенсор
  3. Камера Raspberry
  4. Использованный LCD монитор
  5. Деревянная рама

 

Введение

В этом году, я хотел придумать проект Хэллоуина с использованием Raspberry. Я видел несколько вариантов реализации Картин Призраков, но не одна из них меня особо не напугала, так как на них вообще не было никакого интерактива.

Я решил расширить эту идею и начал искать какие-то хорошие видеоролики, которые я мог бы использовать. Это привело меня к AtmosFx, у них есть несколько действительно интересных видеороликов Unliving Portrait, которые стоят всего 7,99 долларов США каждый. Они были идеальны для того, что я задумал.

Вот видео готового проекта.

Я не хотел писать код PIR с нуля, поэтому я искал в Интернете примеры кода для PIR на Python. Я нашел старую статью от Arc Software, в которой разбирался аналогичный проект.

Код, который я представляю, в основном из их примера, но я сделал несколько модификаций в соответствии с моими потребностями.

 

Шаг 1. Сборка рамы для LCD

После разборки ЖК-монитора и снятия ЖК-панели и электроники я измерил точный размер дисплея 17 X 11 в портретной ориентации.

Я использовал этот онлайн-инструмент, чтобы выяснить размеры моих рамок, чтобы они соответствовали моей ЖК-панели.

Я изготовил деревянную раму используя дерево размером 1 "x 2", с внутренним размером 17 "x 11", который удерживает ЖК-дисплей. Рамка прикрепляется к корпусу ЖК-дисплея и оставляет всю электронику доступной сзади.

backframe qbyx821iY5

Затем я установил Raspberry Pi с помощью небольшого крепления от Thingiverse.com (Pi Side Mount), которое я напечатал с помощью своего 3D-принтера.

pimount qlH0zcz4MN

Я использовал держатели для зеркала, чтобы закрепить ЖК-дисплей, чтобы он не сдвигался и поддерживал его заподлицо с передней частью рамки.

Последний этап сборки состоял в том, чтобы просверлить отверстие для датчика PIR и прикрепить его к GPIO Pi. PIR довольно прост, у него есть плюс, земля и контакт сигнала.

image FR3a0TQT6Y

 

Шаг 2. Изображения, видео и код

В моем проекте я использовал три видеоролика Unliving Portrait от AtmosFX.

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

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

Чтобы отобразить первый кадр, я использовал Linux FBI (framebuffer imageviewer).

Используемый проигрыватель - это OMXPlayer, и, хотя он поддерживает возможность поставить видео на паузу, нет такой команды в командной строке, которую я мог бы вызвать в Python для приостановки и воспроизведения без реализации чего-то вроде DBuscontrol, который слишком усложнял бы проект.

 

Структура папок

Структура папок, показанная ниже на фото, соответствует путям сценария для доступа к изображениям и видео. Путь может быть изменен в любой момент, но нужно будет так же менять пути в скриптах для соответствия.

image ZL09oHTTvQ

 

Изображение

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

Три видео которые я использовал про «Человека, женщину и ребенка», поэтому я взял скриншоты первых кадров каждого и назвал их MaleStart.png, FemaleStart.png и ChildStart.png. Я создал папку в моем проекте Halloween под названием ScareMedia и загрузил туда 3 снимка.

 

Видео

Затем я назвал каждое видео MaleScare.mp4, FemaleScare.mp4 и ChildScare.mp4 и загрузил их в папку ScareMedia.

 

Код

Существует 2 сценария, которые необходимо автоматизировать видео при обнаружении движения

pirDetect.py

Это обрабатывает все обнаружение движения и подключает событие Montion, которое активируется в скрипте scare.

#!/usr/bin/python
import RPi.GPIO as GPIO
import time
import os

class detector(object):
        def __init__(self, sensor):
                self.callBacks = []
                self.sensor = sensor
                self.currState = False
                self.prevState = False

                GPIO.setmode(GPIO.BOARD)
                GPIO.setup(self.sensor, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

        def read(self):
                self.prevState = self.currState
                self.currState = GPIO.input(self.sensor)

        def printState(self):
                print( "GPIO pin {0} is {1}".format(self.sensor, "HIGH" if self.currState else "LOW"))

        def subscribe(self, callBack):
                self.callBacks.append(callBack)

        def callBack(self, state):
                for fn in self.callBacks:
                        fn(state)

        def start(self):
                try:
                        self.read()
                        self.printState()
                        while True:
                                 self.read()
                                 if self.currState != self.prevState:
                                         self.printState()
                                         self.callBack(self.currState)
                                 time.sleep(.1)

                except (KeyboardInterrupt, SystemExit):
	#Since fbi doesn't restore the console correctly when the application is exited we do a little clean up.
						os.system('stty sane')

 

scare.py

Это скрипт, который запускает видео при обнаружении движения

#!/usr/bin/python
import subprocess as sp
import time
import os
from pirDetect import *
import sys

video = ["omxplayer", "filename", "-o", "both", "--win", "0 0 1280 720", "--aspect-mode", "fill", "--no-osd", "--orientation" ,"180","--vol", "-600"]
scareFile = "/home/pi/Projects/Halloween/ScareMedia/{0}ScareV.mp4".format(sys.argv[1])
print(scareFile)

def onMotion(currState):
    if currState:
        video[1] = scareFile
        subVideo = sp.Popen(video)
        while subVideo.poll() is None:
            time.sleep(.1)


def showImage():
    os.system("sudo fbi -T 1 -d /dev/fb0 -noverbose -once /home/pi/Projects/Halloween/ScareMedia/{0}Start.png".format(
        sys.argv[1]))


showImage()
objDetect = detector(7)
objDetect.subscribe(onMotion)
objDetect.start()
os.system("sudo killall -9 fbi")

 

Все вместе

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

Существует также модификация, чтобы добавить Pi-камеру и сделать 5-секундное видео человека, активирующего движение, и сохранить его в Pi при каждом обнаружении движения.

Используя SSH и войдите в Pi и выполните скрипт scare, используя ./scare.py, передав Male, Female, Child аргумент.

Обновление: запись жертвы с помощью камеры Pi

Я добавляю scare2.py, у которого теперь есть необходимый код для записи видео вашей жертвы с помощью Pi-камеры, а затем он воспроизводит их обратно, чтобы они могли видеть свою собственную реакцию. Он записывает 5-секундное видео, которое можно настроить в сценарии.

Я просверлил отверстие в центре верхней части рамы и установил камеру Pi на спину, используя два застежки-молнии на молнии I, напечатанные 3D и застежки-молнии.

Также необходимо создать новую папку в папке Хэллоуина под названием «Записи» или изменить код, чтобы указать, где вы хотите сохранить файлы. Вы можете установить сетевой ресурс и записать его в него.

Как повезло, проект Video сделал его на шоу Daily Planet на канале Discovery (VIDEO LINK) с отметкой в 44 минуты.

 

scare2.py

Это обновленная версия скрипта scare.py, которая включает возможность запись видео вашей жертвы с помощью камеры Pi.

#!/usr/bin/python
import subprocess as sp
import time
import os
import datetime
from pirDetect import *
import sys

video = ["omxplayer", "filename", "-o", "both", "--win", "0 0 1280 720", "--aspect-mode", "fill", "--no-osd", "--orientation" ,"180","--vol", "-600"]
record = ["raspivid", "-o", "filename", "-n", "-t", "5000", "-rot","180"]
scareFile = "/home/pi/Projects/Halloween/ScareMedia/{0}ScareV.mp4".format(sys.argv[1])

def getFileName():
    return "/home/pi/Projects/Halloween/Recordings/" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S.h264")

def subProcWait(params):
        sub = sp.Popen(params)
        while sub.poll() is None:
            time.sleep(.1)

def onMotion(currState):
    if currState:
        autoFileName = getFileName()  # Get a time stamped file name
        record[2] = autoFileName
        subRecord = sp.Popen(record)  # Start recording to capture their fright
        video[1] = scareFile
        subProcWait(video)  # Play the video to scare them
        video[1] = autoFileName
        subProcWait(video)  # Play back the video we just recorded

def showImage():
    os.system("sudo fbi -T 1 -d /dev/fb0 -noverbose -once /home/pi/Projects/Halloween/ScareMedia/{0}Start.png".format(
        sys.argv[1]))


showImage()
objDetect = detector(7)
objDetect.subscribe(onMotion)
objDetect.start()
os.system("sudo killall -9 fbi")

scareRandom.py

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


#!/usr/bin/python import subprocess as sp import time import os import datetime from pirDetect import * import sys import random """ This script will play any of the videos listed in a random order. Usage: python ./scareRandom.py [VideoName] [Minutes] [VideoName] is any of video prefixes in the video_prefix list. [Minutes] is the time value in minutes of how often you want to rotate to a different video. Example usage would be : python ./scareRandom.py Male 5. After each trigger of the on_motion event the script will check and determine if the time elapsed is greater than the value you provided in argument 2 and if the elapsed time is longer than your time setting it will randomly pick a new video prefix and will recursively attempt to choose one that is NOT the current video prefix so it doesn't play the same video more than one time in sequence. To add more or different videos just add to or modify the video_prefix list below. If adding more videos or changing the defaults you will have to create a start image for each additional video. The naming structure for the start images and videos are as follows. [Prefix]ScareV.m4v (MaleScareV.m4v) or [Prefix]ScareV.mp4 (MaleScareV.mp4) [Prefix]Start.png (MaleStart.png) """ # initialize variables video_prefix = ["Male", "Female", "Child"] # This is the list of videos prefixes, you can add additional video # prefixes here. video = ["omxplayer", "filename", "-o", "both", "--win", "0 0 1280 720", "--aspect-mode", "fill", "--no-osd", "--orientation", "180", "--vol", "-600"] record = ["raspivid", "-o", "filename", "-n", "-t", "5000", "-rot", "180"] scare_file = "" current_prefix = "" new_prefix = "" image_name = "" start_time = time.time() def change_video(): global start_time global scare_file global current_prefix global new_prefix elapsed_time = time.time() - start_time print(str("\nTime since last rotation: {0}".format(datetime.timedelta(seconds=elapsed_time)))) if elapsed_time > (int(sys.argv[2]) * 60): while new_prefix == current_prefix: # make sure we don't choose the same video new_prefix = video_prefix[random.randrange(len(video_prefix))] current_prefix = new_prefix scare_file = "/home/pi/Projects/Halloween/ScareMedia/{0}ScareV.m4v".format(current_prefix) start_time = time.time() show_image(current_prefix) print("\nUpdating Video to: {0}\n".format(current_prefix)) def getfilename(): return "/home/pi/Projects/Halloween/Recordings/" + datetime.datetime.now().strftime("%Y-%m-%d_%H.%M.%S.h264") def sub_proc_wait(params): sub = sp.Popen(params) while sub.poll() is None: time.sleep(.1) def on_motion(curr_state): if curr_state: auto_file_name = getfilename() # Get a time stamped file name record[2] = auto_file_name sub_record = sp.Popen(record) # Start recording to capture their fright video[1] = scare_file sub_proc_wait(video) # Play the video to scare them video[1] = auto_file_name sub_proc_wait(video) # Play back the video we just recorded change_video() def show_image(_image_name): os.system("sudo fbi -T 1 -d /dev/fb0 -noverbose -once /home/pi/Projects/Halloween/ScareMedia/{0}Start.png".format( _image_name)) def start_up(): global scare_file global image_name image_name = arg1 scare_file = "/home/pi/Projects/Halloween/ScareMedia/{0}ScareV.m4v".format(image_name) show_image(image_name) obj_detect = detector(7) obj_detect.subscribe(on_motion) obj_detect.start() os.system("sudo killall -9 fbi") if __name__ == "__main__": try: arg1 = sys.argv[1] if arg1 not in video_prefix: raise ValueError('first argument must be Male,Female or Child') if sys.argv[2].isdigit(): arg2 = int(sys.argv[2]) else: raise ValueError('Second argument must be a number') except IndexError: print("Usage: python ./scareRandom.py [VideoName] [Minutes]") sys.exit(1) except ValueError as x: print(x.message + "\nUsage: python ./scareRandom.py [VideoName] [Minutes]") sys.exit(1) start_up()



 Источник

Author

Bender

Я поделюсь с тобой всеми знаниями, которые доступны мне.

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

There are no comments posted here yet

Оставьте свой комментарий

  1. Posting comment as a guest. Sign up or login to your account.
Вложения (0 / 3)
Share Your Location

О нас

Основой деятельностью портала является показ и объяснение что представляет собой выражени "Робот", "Робототехника", "Законы робототехники", "Мехатроника", "Искусственный интеллект(ИИ)". 

 Если у Вас есть интересная информация по тематике сайта и Вы готовы ей поделиться, - обращайтесь на емайл через форму обратной связи. И мы опубликуем Вашу статью

Мы используем файлы cookie для улучшения нашего веб-сайта. Продолжая использовать этот веб-сайт, вы даете согласие на использование файлов cookie. More details…