Приветствую, Codeby.
В этой статье мы создадим свою сигнализационную систему для дома, с помощью лишь ноутбука с веб-камерой и Python
Введение:
Сигнализации в доме стали повседневностью в нашей жизни, их предлагают компании, государство, одиночные специалисты.
Во всех случаях установка и дальнейшая эксплуатация обходятся в копеечку, при этом мы сами часто не знаем как устроена система в нашем доме.
Чаще всего сигнализация представляет собой датчик движения подключенный к двери для отключения и включения, если датчик засекает какое-либо движение, то отправляется определенный сигнал.
Планируется сделать цикл из 2 статей, так как в этой мы лишь создадим датчик движения для обнаружения сторонних объектов.
Основное:
Для определения движения используются следующие библиотеки:
cv2 - получение, вывод, работа с изображениями
numpy - для более удобного проведения некоторых операций
imutils - grab_contours
time - время
collections - deque
Код уже существует и состоит из функций get_movement, get_background, detect, main
Функция get_movement будет передавать нам фреймы с изменениями:
Функция get_background позволяет получить статичный фон
Функция detect будет определять сам факт движения в зависимости от заданных параметров, таких как насколько сильно изменение и какой минимальный размер объекта
Ну и главная функция main которая позволяет отслеживать движения:
Данная программа ограничена обрисовкой движущихся объектов и при появлении движения выводит предупреждение.
Так все выглядит:
Теперь мы можем вместо отрисовки и вывода текста отправлять сообщения от нашего бота Telegram, сделаем это с помощью pyTelegramBotAPI.
Чтобы не отправлять по каждому движению 100 сообщений, мы будем отправлять сообщение при первом движении в минуте, сохранять время отправки, сохранять время 2 движения в этой минуте если оно произошло не менее чем через 20 секунд после предыдущего.
То есть:
15:00 - Движение, отправка сообщения
15:00:10 - Движение, сообщение не отправляется и не сохраняется, так как не прошло 60 или 20 секунд с момента прошлого сообщения.
15:00:20 - Движение, время сохраняется для отправки в ближайшую минуту
15:01 - Нет движений, отправка данных о движении в 15:00:20
Сделано это для того, чтобы оптимизировать нашего бота, так мы вряд-ли что-то упустим, но и не будем получать сотни сообщений в секунду
Теперь в функции main уберем отрисовку объектов и будем вызывать motion_alert в отдельном потоке:
Теперь, если в период с 15:01 по 15:02 было совершено движение и оно было первым в этой минуте, то будет прислан HTTP запрос.
Если движение уже не первое и запрос уже посылался, то alert_in_queue ставится на True и с наступлением следующей минуты система снова отправит нам запрос.
В результате на нашего бота приходят сообщения при движениях!
На этом мы не остановимся и сделаем функцию для отключения сигнализации:
В функцию main добавим отключение при становлении stop_alert True:
Итоговый результат:
В конечном итоге мы имеем систему для ловли движений и отправку данных прямо нам в телефон, вместе с возможностью включения и выключения!
Осталось только реализовать подключение к турели.
Вывод:
Как мы убедились в этой статье - сделать свою сигнализацию очень легко.
В виде контроллера мы используем телеграм бота и язык Python для самого слежения за окружением, такая система может пригодиться параноикам нежелающим ставить сторонние сигнализационные решения.
В этой статье мы создадим свою сигнализационную систему для дома, с помощью лишь ноутбука с веб-камерой и Python
Введение:
Сигнализации в доме стали повседневностью в нашей жизни, их предлагают компании, государство, одиночные специалисты.
Во всех случаях установка и дальнейшая эксплуатация обходятся в копеечку, при этом мы сами часто не знаем как устроена система в нашем доме.
Чаще всего сигнализация представляет собой датчик движения подключенный к двери для отключения и включения, если датчик засекает какое-либо движение, то отправляется определенный сигнал.
Планируется сделать цикл из 2 статей, так как в этой мы лишь создадим датчик движения для обнаружения сторонних объектов.
Основное:
Для определения движения используются следующие библиотеки:
cv2 - получение, вывод, работа с изображениями
numpy - для более удобного проведения некоторых операций
imutils - grab_contours
time - время
collections - deque
Код уже существует и состоит из функций get_movement, get_background, detect, main
Функция get_movement будет передавать нам фреймы с изменениями:
Python:
def get_movement(frames, shape):
movement_frame = np.zeros(shape, dtype='float32')
i = 0
for f in frames:
i += 1
movement_frame += f * i
movement_frame = movement_frame / ((1 + i) / 2 * i)
movement_frame[movement_frame > 254] = 255
return movement_frame
Python:
def get_background(frames, shape):
bg = np.zeros(shape, dtype='float32')
for frame in frames:
bg += frame
bg /= len(frames)
bg[bg > 254] = 255
return bg
Python:
def detect(frame, bg_frames, fg_frames, threshold=25, min_box=50):
fg_frames.append(frame)
bg_frames.append(frame)
fg_frame = get_movement(list(fg_frames), frame.shape)
bg_frame = get_background(list(bg_frames), frame.shape)
movement = cv2.absdiff(fg_frame, bg_frame)
movement[movement < threshold] = 0
movement[movement > 0] = 254
movement = movement.astype('uint8')
movement = cv2.cvtColor(movement, cv2.COLOR_BGR2GRAY)
movement[movement > 0] = 254
cv2.imshow('Movement', movement)
contours = cv2.findContours(movement, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
boxes = []
for contour in contours:
if cv2.contourArea(contour) < min_box:
continue
box = cv2.boundingRect(contour)
boxes.append(box)
return boxes
Python:
def main(width=640, height=480, scale_factor=3):
bg_frames = deque(maxlen=30)
fg_frames = deque(maxlen=10)
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
last_time = time.time()
while True:
_, frame = cap.read()
frame = cv2.resize(frame, (width, height))
work_frame = cv2.resize(frame, (width // scale_factor, height // scale_factor))
work_frame = cv2.GaussianBlur(work_frame, (5, 5), 0)
work_frame_f32 = work_frame.astype('float32')
boxes = detect(work_frame_f32, bg_frames, fg_frames)
if boxes != []:
text = "FPS:" + str(int(1 / (time.time() - last_time)))
last_time = time.time()
cv2.putText(frame, text, (10, 20), cv2.FONT_HERSHEY_PLAIN, 2, (0, 255, 0), 2)
cv2.imshow('Webcam', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
Данная программа ограничена обрисовкой движущихся объектов и при появлении движения выводит предупреждение.
Так все выглядит:
Теперь мы можем вместо отрисовки и вывода текста отправлять сообщения от нашего бота Telegram, сделаем это с помощью pyTelegramBotAPI.
Чтобы не отправлять по каждому движению 100 сообщений, мы будем отправлять сообщение при первом движении в минуте, сохранять время отправки, сохранять время 2 движения в этой минуте если оно произошло не менее чем через 20 секунд после предыдущего.
То есть:
15:00 - Движение, отправка сообщения
15:00:10 - Движение, сообщение не отправляется и не сохраняется, так как не прошло 60 или 20 секунд с момента прошлого сообщения.
15:00:20 - Движение, время сохраняется для отправки в ближайшую минуту
15:01 - Нет движений, отправка данных о движении в 15:00:20
Сделано это для того, чтобы оптимизировать нашего бота, так мы вряд-ли что-то упустим, но и не будем получать сотни сообщений в секунду
Python:
last_alert = 0
alert_in_queue = False
def motion_alert():
global last_alert
global alert_in_queue
if time.time() - last_alert > 60:
if alert_in_queue != None:
alert_time = alert_in_queue
bot.send_message(1823377615, "Сигнализация сработала в " + alert_time)
alert_in_queue = None
else:
alert_time = datetime.now().strftime("%H:%M:%S")
bot.send_message(1823377615, "Сигнализация сработала в " + alert_time)
last_alert = time.time()
elif alert_in_queue == None and time.time() - last_alert >20:
alert_in_queue = datetime.now().strftime("%H:%M:%S")
Python:
boxes = detect(work_frame_f32, bg_frames, fg_frames)
if boxes != [] or alert_in_queue != None:
threading.Thread(target=motion_alert()).start()
Теперь, если в период с 15:01 по 15:02 было совершено движение и оно было первым в этой минуте, то будет прислан HTTP запрос.
Если движение уже не первое и запрос уже посылался, то alert_in_queue ставится на True и с наступлением следующей минуты система снова отправит нам запрос.
В результате на нашего бота приходят сообщения при движениях!
На этом мы не остановимся и сделаем функцию для отключения сигнализации:
Python:
@bot.message_handler(commands=['start_alert'])
def start_alert(message):
bot.reply_to(message, "Сигнализация активирована. До скорого возращения!")
signalisation = threading.Thread(target=main())
signalisation.start()
@bot.message_handler(commands=['stop_alert'])
def start_alert(message):
global stop_alert
stop_alert = True
bot.reply_to(message, "Сигнализация деактивирована. Добро пожаловать домой!")
bot.infinity_polling()
Python:
if stop_alert == True:
break
Итоговый результат:
В конечном итоге мы имеем систему для ловли движений и отправку данных прямо нам в телефон, вместе с возможностью включения и выключения!
Осталось только реализовать подключение к турели.
Вывод:
Как мы убедились в этой статье - сделать свою сигнализацию очень легко.
В виде контроллера мы используем телеграм бота и язык Python для самого слежения за окружением, такая система может пригодиться параноикам нежелающим ставить сторонние сигнализационные решения.
Последнее редактирование модератором: