Отправка фото, если камера заметила движение (Python)

Статус
В этой теме нельзя размещать новые ответы.
Достаточно давно сделал такую штуку, которая может следить за тем, что происходит в ваше отсутствие. Вот допустим отставили вы сосиску на столе (с кем ни бывает) и сразу как только пушистое чудище захочет ее украсть, вы об этом узнаете.
мб кому-нибудь будет полезно.

Нам понадобятся библиотеки

"- nympy любой версии
- cv2 (в моем случае подошла версия 4.1.1.26

Ну чтож, приступим.
1. Импортируем необходимые библиотеки:


Python:
import time
import smtplib
import threading
import cv2
import numpy as np
from email.contentmanager import subtype
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

2. Далее объявляем переменные:

Python:
login = ""  # логин почты, с которой производится отправка
password = ""  # пароль почты, с которой производится отправка

stmp = "smtp.mail.ru"  # протокол по которому работает почта (в нашем случае mail.ru)
server = smtplib.SMTP_SSL(stmp, 465)

target = ""  # почта, на которую мы будем отправлять изображение

msg = MIMEMultipart()  # создаем объект будущего письма
msg['Subject'] = "message title"  # заголовок письма
msg['From'] = login
body = "message text"  # текст письма


3. Следующим шагом необходимо инициализировать камеру и сделать первое фото, с которым будут сравниваться все последующие:
P.S. инициализация камеры занимает некоторое время, в моем случае - 10 секунд, но все зависит от камеры


Python:
try:  # на всякий случай будем ловить ошибки
    cam = cv2.VideoCapture(0)  # инициализируем (0 - id камеры)
    time.sleep(10)  # ждем

    ret, start_photo = cam.read()  # получаем изображение
    cv2.imwrite("NormalState.png", start_photo)  # сохраняем изображение
    cv2.imshow("NormalState.png", start_photo)  # выводим изображение на экран (просто так)
    time.sleep(1)  # ждем (хз, без этого не работало)

    normal_state_img = cv2.imread("NormalState.png")  # сохраняем наше изображение в картинку
except Exception as error:
    print(error)


4. Дальше делаем функцию, которая будет бесконечно фотографировать и сравнивать начальное фото, с текущим:

Python:
def main_func():
    start = True  # переменная, благодаря которой часть кода выполниться лишь при первом проходе цикла
    acceptable_value_min, acceptable_value_max = 0, 0  # минимальное и максимальное значение погрешности
    while True:
        send_message = True
        temp, frame = camera.read()  # считываем изображение с камеры
        cv2.imwrite('UnNormalState.png', frame)  # сохранение текущего изображения
        current_img = cv2.imread('UnNormalState.png')  # сохраняем текущее изображение в переменную
        result = cv2.matchTemplate(normal_state_img, current_img, cv2.TM_CCOEFF_NORMED)  # сравнение начального изображения с текущим
        y, x = np.unravel_index(result.argmax(), result.shape)  # получаем кортеж массивов индексов
        if start:  # рассчет погрешности
            acceptable_value_min = result - 0.04  # мин. погрешность
            acceptable_value_max = result + 0.04  # макс. погрешность
            start = False
            print(acceptable_value_max, acceptable_value_min)  # выведем наши погрещности (просто так)
        print(result)  # выводим результат сравнения изображений
        if result < acceptable_value_min or result > acceptable_value_max:  # выход за пределы допустимых погрещностей
            if send_message:  # отправка сообщения
                unnormal_state_img = open('UnNormalState.png', 'rb')  # считываем изображение
                att = MIMEApplication(unnormal_state_img.read(), _subtype=subtype)  # добавляем вложение к письму
                unnormal_state_img.close()
                att.add_header('Content-Disposition', 'attachment', filename='UnNormalState.png')
                msg.attach(att)
                msg.attach(MIMEText(body, 'plain'))
                server.login(login, password)
                server.sendmail(login, target, msg.as_string())
                print("Message has been sent")
        if cv2.waitKey(1) & 0xFF == ord('q'):  # ловим ивент нажатия, для завершения работы
            break

5. На этом можно было бы закончить, но мы загоним все это дело в отдельный поток, чтобы винда не ругалась, что программа не отвечает:

Python:
def start_thread():
    thread = threading.Thread(target=main_func, daemon=False)
    thread.start()


6. Ну и завершение нашей работы нашей программы:


Python:
try:
    start_thread()  # вызываем функцию для создания отдельного потока
    normal_state_img.close()  # закрываем изображение
    camera.release()  # освобождаем камеру
    cv2.destroyAllWindows()  # закрытие всех окон
except Exception as error:
    print(error)


На этом у меня все

7. Полный код


Python:
import smtplib
import threading
import cv2
import numpy as np
from time import sleep
from email.contentmanager import subtype
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText


login = "*****"  # логин почты, с которой производится отправка
password = "*****"  # пароль почты, с которой производится отправка

stmp = "smtp.mail.ru"  # mail / yandex / gmail и т.д
server = smtplib.SMTP_SSL(stmp, 465)

target = "*****"  # целевая почта для отправки

msg = MIMEMultipart()
msg['Subject'] = "message title"
msg['From'] = login
body = "message text"


try:
    camera = cv2.VideoCapture(0)
    sleep(10)

    temp, start_photo = camera.read()
    cv2.imwrite("NormalState.png", start_photo)
    cv2.imshow("NormalState.png", start_photo)

    sleep(1)
    normal_state_img = cv2.imread("NormalState.png")
except Exception as error:
    print(error)


def main_func():
    start = True
    acceptable_value_min, acceptable_value_max = 0, 0
    while True:
        send_message = True
        temp, frame = camera.read()
        cv2.imwrite('UnNormalState.png', frame)  # сохранение текущего состояния
        current_img = cv2.imread('UnNormalState.png')  # текущее состояние
        result = cv2.matchTemplate(normal_state_img, current_img, cv2.TM_CCOEFF_NORMED)  # сравнение начального состояния с текущим
        y, x = np.unravel_index(result.argmax(), result.shape)
        if start:  # рассчет погрешности
            acceptable_value_min = result - 0.04  # мин. погрешность
            acceptable_value_max = result + 0.04  # макс. погрешность
            start = False
            print(acceptable_value_max, acceptable_value_min)
        print(result)
        if result < acceptable_value_min or result > acceptable_value_max:  # выход за пределы допустимых значений
            if send_message:  # отправка сообщения
                unnormal_state_img = open('UnNormalState.png', 'rb')
                att = MIMEApplication(unnormal_state_img.read(), _subtype=subtype)
                unnormal_state_img.close()
                att.add_header('Content-Disposition', 'attachment', filename='unnormal_state_img.png')
                msg.attach(att)
                msg.attach(MIMEText(body, 'plain'))
                server.login(login, password)
                server.sendmail(login, target, msg.as_string())
                print("take a photo")
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break


def start_thread():
    thread = threading.Thread(target=main_func, daemon=False)
    thread.start()


try:
    start_thread()
    normal_state_img.close()
    camera.release()
    cv2.destroyAllWindows()  # закрытие всех окон
except Exception as e:
    print(e)

P.S. Код написан не самым лучшим образом, ибо последний раз я притрагивался к нему более года назад, когда мои навыки были гораздо слабее
 
Последнее редактирование:
Статус
В этой теме нельзя размещать новые ответы.
Сверху