(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; m[i].l=1*new Date(); for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }} k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym"); ym(93790508, "init", { defer: true, clickmap:true, trackLinks:true, accurateTrackBounce:true }); ym(93790508, 'hit', window.location.href);

Сделай сам: умная камера для наблюдения за питомцами

Обучаем нейросеть на котиках.

В серии DIY-статей «Пространство для изобретений» мы пробуем в домашних условиях разработать необычные гаджеты и оставляем все необходимые инструкции, чтобы любой желающий мог повторить наш опыт. Серию статей поддерживает Selectel — провайдер ИТ-инфраструктуры, которая помогает в решении рабочих задач и разработке личных проектов. Посмотреть, что интересного есть у провайдера, и выбрать для себя подходящие решения можно на сайте.

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

Зачем нужна камера

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

Рассказываю, что из этого вышло.

Что потребуется для сборки

Большую часть времени коты проводят на участке — там у меня уже установлена система видеонаблюдения из четырёх аналоговых камер с простым регистратором Falcon Eye, поэтому ничего нового я не покупал. Для моей задумки было важно, чтобы регистратор мог отдавать в сеть RTSP-поток для покадровой обработки видео в режиме реального времени.

Устанавливаем софт

До начала сборки камеры у меня было довольно смутное представление о работе нейросетей и особенностях компьютерного зрения: в лаборатории робототехники для детей, которой я руковожу, мы занимаемся программированием на Arduino и до этого не касались подобных проектов. Изучать область я начал с библиотеки PixelLib — она помогает определять и сегментировать объекты на изображениях, при этом разбираться в нейросетях не нужно.

Установил утилиту Virtualenv — она позволяет создавать изолированные виртуальные окружения для Python: создаёт внутри вашего проекта каталог, в который устанавливает нужную версию Python и все необходимые пакеты для приложения, фреймворка или скрипта. В результате вы получаете рабочее, полностью изолированное и переносимое окружение — это значит, что пакеты мы сможем устанавливать именно в это окружение, а не глобально.

Устанавливаю в терминале

sudo pip3 install virtualenv

Если pip не установлен

sudo apt install python3-pip pip3 install –upgrade pip

Создаю виртуальную среду в папку Venv1 с python3.6

virtualenv -p python3.6 project/Venv1

И запускаю

source project/Venv1/bin/activate

Для выхода из среды Venv1

deactivate

Теперь устанавливаю библиотеку PixelLib, проект буду создавать в Virtualenv.

source project/Venv1/bin/activate

PixelLib требует Python версии 3.5–3.7 и версию pip больше 19.0.

pip3 install pip

Устанавливаю последнюю версию Tensorflow (Tensorflow 2.0+)

pip3 install tensorflow

А теперь imgaug:

pip3 install imgaug

И последний шаг — установка PixelLib:

pip3 install pixellib --upgrade

Захватываем RTSP-поток с камер

Регистратор отдаёт rtsp-поток по адресу

rtsp://<login>:<password>@<ip-адрес регистратора>:554/mode=real&idc=<n камеры>&ids=1

Сначала я настроил камеры в самом щадящем режиме — один кадр в секунду. А ещё отключил на них режим «тревоги», при котором поток увеличивается до 15 кадров в секунду.

Пробую захватить поток с одной камеры и получить картинку в виде фрейма для последующей обработки. Полученную картинку прогоняю через детектор объекта (модель mask_rcnn_coco.h5, ссылка для скачивания) и сохраняю в папке, если объект (кот) обнаружен.

Библиотека PixelLib хорошо документирована, в ней очень много примеров. Для этого скрипта, например, я использую Instance segmentation of images with PixelLib.

Подключение библиотек

import os os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" import time #import _thread from pixellib.instance import instance_segmentation import cv2 from datetime import datetime

Загрузка модели (указываю путь к скачанной модели mask_rcnn_coco.h5):

segment_frame.load_model("mask_rcnn_coco.h5")

Выбор объектов для определения (для тестирования person и cat):

target_class = segment_frame.select_target_classes(person=True,cat=True)

Создание объекта камеры:

vcap = cv2.VideoCapture(urlRtsp+"&idc="+idc+"&ids="+ids)

Получение кадра:

ret, frame = vcap.read()

Масштабирование картинки:

output=cv2.resize(frame,(int(frame.shape[1]/2),int(frame.shape[0]/2)))

И прогон через детектор:

result,img = segment_frame.segmentFrame ( output, #show_bboxes=True, segment_target_classes=target_class, #extract_segmented_objects=True, #save_extracted_objects=True, #output_image_name="output.jpg" )

При ненулевом результате сохранение картинки в папку:

f=cv2.imwrite(pathSaveImg+"/cam"+idc+"/"+ftime.strftime("%d-%m-%Y")+"/_"+ftime.strftime("%H:%M:%S.%f")+".jpg", output)

Скрипт целиком:

import os os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3" import time #import _thread from pixellib.instance import instance_segmentation import cv2 from datetime import datetime # "rtsp://admin:[email protected]:554/mode=real&idc=3&ids=1" urlRtsp="rtsp://admin:[email protected]:554/mode=real" pathSaveImg="/home/petin/python3_prgs_1" idc="3" ind=1; ids="1" timePrevFrame=0 countAll=0 countDetect=0 segment_frame = instance_segmentation(infer_speed = "fast") segment_frame.load_model("mask_rcnn_coco.h5") target_class = segment_frame.select_target_classes(person=True,cat=True) vcap = cv2.VideoCapture(urlRtsp+"&idc="+idc+"&ids="+ids) print("start**********************************************") while(1): ret, frame = vcap.read() if ret: dt = datetime.now() countAll=countAll+1 print("countAll=",countAll) print(" pixellib ") output=cv2.resize(frame,(int(frame.shape[1]/2),int(frame.shape[0]/2))) timePrevFrame=dt.timestamp() result,img = segment_frame.segmentFrame ( output, #show_bboxes=True, segment_target_classes=target_class, #extract_segmented_objects=True, #save_extracted_objects=True, #output_image_name="output.jpg" ) dt = datetime.now() timeTekFrame=dt.timestamp() print(timePrevFrame," ",timeTekFrame," ",timeTekFrame-timePrevFrame) objects_count = len(result["scores"]) print(f"Найдено объектов: {objects_count}") if objects_count>0: #_thread.start_new_thread(detect,(frame,)) ftime=datetime.now() if(os.path.exists(pathSaveImg+"/cam"+idc+"/"+ftime.strftime("%d-%m-%Y"))==False): os.mkdir(pathSaveImg+"/cam"+idc+"/"+ftime.strftime("%d-%m-%Y")) f=cv2.imwrite(pathSaveImg+"/cam"+idc+"/"+ ftime.strftime("%d-%m-%Y")+"/_"+ftime.strftime("%H:%M:%S.%f")+".jpg", output) print("write file = ",f) cv2.imshow('VIDEO1', output) elif ret: vcap.release() vcap = cv2.VideoCapture(urlRtsp+"&idc="+idc+"&ids="+ids) print("restart vcap") else: print("no ret",countAll) cv2.waitKey(1)

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

Есть пара альтернатив: можно установить OpenVINO и подключить Neural Compute Stick 2 или попробовать Nvidia Jetson Nano. У меня был Neural Compute Stick 2, поэтому пробую этот вариант.

Устанавливаю OpenVINO toolkit — открытый бесплатный набор инструментов, который помогает детектировать лицо, распознавать объекты, текст и речи. По описаниям Intel производительность OpenVINO при вычислении сетей на платформах Intel в разы выше по сравнению с популярными фреймворками, а требования памяти — значительно ниже.

Во время установки выбираю последний дистрибутив 2021.3.394 и устанавливаю Intel® Neural Compute Stick 2. OpenVINO включает в себя несколько модулей и скриптов. Сразу попробовал, как работает определение объектов. Я использовал модель mobilenet-ssd — её нужно преобразовать во внутренний формат OpenVino с помощью Model Optimizer.

Загрузка модели

путь к downloader.py

/opt/intel/openvino_2021/deployment_tools/open_model_zoo/tools/downloader

команда загрузки модели

python3 /opt/intel/openvino_2021/deployment_tools/open_model_zoo/tools/downloader/downloader.py --name mobilenet-ssd

Перед запуском примера с обученной моделью убедитесь, что она преобразована в формат механизма вывода (* .xml + * .bin) с помощью инструмента Model Optimizer.

Конвертирование модели

путь к converter.py

/opt/intel/openvino_2021/deployment_tools/open_model_zoo/tools/downloader

После конвертирования получаю модель в формате OpenVino.

Проверяю работу на старых фотографиях.

python3 /opt/intel/openvino_2021/inference_engine/samples/python/object_detection_sample_ssd.py -i cat01.jpg -m home/petin/public/mobilenet-ssd/FP32/mobilenet-ssd.xml -nt 5 -d CPU

Опознание в модели mobilenet-ssd приемлемое, буду использовать ее. Дополнительно устанавливаю пакет imutils.

pip3 install imutils

Скачиваю файлы модели mobilenet-ssd.caffemodel и mobilenet-ssd.prototxt с помощью «Загрузчика моделей» (Model Downloader) OpenVino

python3 /opt/intel/openvino_2021/deployment_tools/open_model_zoo/tools/downloader/downloader.py ----name mobilenet-ssd

Пишу скрипт захвата видео с четырёх камер, прогон картинки через детектор и сохранение картинки в каталог cam<n>/<d-n-Y> при детектировании кота.

# подключение библиотек from imutils.video import VideoStream from imutils.video import FPS import numpy as np import sys import argparse import imutils import time import cv2 from urllib.request import urlopen from datetime import datetime import os tekcamera=1 pathSaveImg="/home/petin/python3_prgs_1/OpenVino01" cameras=[[0,0,0,0,0], [0,0,0,0,0], [False,True,False,True,False], ["","Camera1","Camera2","Camera3","Camera4"]] for i in range(1,5): cameras[1][i] = 'rtsp://admin:[email protected]:554/mode=real&idc='+str(i)+'&ids=1' fps = FPS().start() # получение аргументов командной строки # --prototxt путь к файлу mobilenet-ssd.prototxt # --model путь к файлу модели mobilenet-ssd.caffemodel # --show вывод изображений с камер в окна # -c минимальная точность определения объекта ap = argparse.ArgumentParser() ap.add_argument("--prototxt", required=True, help="path to Caffe 'deploy' prototxt file") ap.add_argument("--model", required=True, help="path to Caffe pre-trained model") ap.add_argument("--show", required=True, help="Show cv2.imshow)") ap.add_argument("-c", "--confidence", type=float, default=0.2, help="minimum probability to filter weak detections") args = vars(ap.parse_args()) # загрузка модели CLASSES = ["background", "aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"] COLORS = np.random.uniform(0, 255, size=(len(CLASSES), 3)) print("[INFO] loading model...") net = cv2.dnn.readNetFromCaffe(args["prototxt"], args["model"]) # обработка в Neural Compute Stick net.setPreferableTarget(cv2.dnn.DNN_TARGET_MYRIAD) # инициализация получения потока с камер print("[INFO] starting video stream...") for i in range(1,5): cameras[0][i] = cv2.VideoCapture(cameras[1][i]) print("OK") time.sleep(5.0) detected_objects = [] # цикл while(1): tekcamera = tekcamera+1 if tekcamera+==5: tekcamera=1 logfile=open("last.txt","w+") ftime=datetime.now() str1=.strftime("%d-%m-%Y % %H:%M:%S\n ") logfile.write(str1) logfile.close() if cameras[2][tekcamera] == False: continue # получение кадров из потока ret, frame = cameras[0][tekcamera].read() frame = imutils.resize(frame, width=800) # grab the frame dimensions and convert it to a blob (h, w) = frame.shape[:2] blob = cv2.dnn.blobFromImage(cv2.resize(frame, (300, 300)), 0.007843, (300, 300), 127.5) # pass the blob through the network and obtain the detections and # predictions net.setInput(blob) detections = net.forward() # обработка результатов детектирования print("******************") for i in np.arange(0, detections.shape[2]): confidence = detections[0, 0, i, 2] idx = int(detections[0, 0, i, 1]) #if confidence > args["confidence"] and idx==15 : if confidence > args["confidence"] and (idx==8 or idx==12) : # save files ftime=datetime.now() if(os.path.exists(pathSaveImg+"/cam"+str(tekcamera)+"/"+ftime.strftime("%d-%m-%Y"))==False): os.mkdir(pathSaveImg+"/cam"+str(tekcamera)+"/"+ftime.strftime("%d-%m-%Y")) f=cv2.imwrite(pathSaveImg+"/cam"+str(tekcamera)+"/"+ftime.strftime("%d-%m-%Y")+"/_"+ftime.strftime("%H:%M:%S.%f")+".jpg", frame) print("write file = ",f) # extract the index of the class label from the # `detections`, then compute the (x, y)-coordinates of # the bounding box for the object #idx = int(detections[0, 0, i, 1]) box = detections[0, 0, i, 3:7] * np.array([w, h, w, h]) (startX, startY, endX, endY) = box.astype("int") # draw the prediction on the frame label = "{}: {:.2f}%".format(CLASSES[idx], confidence * 100) print(confidence," ",idx," - ",CLASSES[idx]) detected_objects.append(label) cv2.rectangle(frame, (startX, startY), (endX, endY), COLORS[idx], 2) y = startY - 15 if startY - 15 > 15 else startY + 15 cv2.putText(frame, label, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, COLORS[idx], 2) # show the output frame if args["show"] == "True": cv2.imshow(cameras[3][tekcamera], frame) key = cv2.waitKey(1) & 0xFF # выход по клавише 'q' if key == ord("q"): break fps.update() fps.stop() print("[INFO] elasped time: {:.2f}".format(fps.elapsed())) print("[INFO] approx. FPS: {:.2f}".format(fps.fps())) # do a bit of cleanup cv2.destroyAllWindows()

Запуск скрипта на выполнение

source Venv1/bin/activate cd /home/petin/python3_prgs_1/OpenVino01 python3 pets04.py --prototxt mobilenet-ssd.prototxt --model mobilenet-ssd.caffemodel --show True -c 0.3

Изображения сохраняются в папках cam/. Скорость хорошая — для двух камер при частоте 5 кадров в секунду задержек нет. Но получается слишком много фото, поэтому поток я уменьшил до 1 кадра в секунду.

Обязательно делаю автозагрузку скрипта. Создаю файл autoupload.sh следующего содержания:

#!/bin/bash source Venv1/bin/activate cd /home/petin/python3_prgs_1/OpenVino01 python3 pets04.py --prototxt mobilenet-ssd.prototxt --model mobilenet-ssd.caffemodel --show True -c 0.3

И помещаю в автозагрузку autoupload.sh.

Обзор → Автоматически запускаемые приложения → Добавить

И указываю путь к python-скрипту.

Собираем видео и отправляем в Telegram

Фотографии котов я хочу получать в виде ролика. Для этого устанавливаю пакет ffmpeg.

sudo apt install ffmpeg

И запускаю следующие команды:

Для камеры 1:

ffmpeg -f image2 -pattern_type glob -i /home/petin/python3_prgs_1/OpenVino01/cam1/$(date +%d-%m-%Y)/'*.jpg' -y /home/petin/python3_prgs_1/OpenVino01/cam1-$(date +%d-%m-%Y).mp4 –r 10

Для камеры 2:

ffmpeg -f image2 -pattern_type glob -i /home/petin/python3_prgs_1/OpenVino01/cam2/$(date +%d-%m-%Y)/'*.jpg' -y /home/petin/python3_prgs_1/OpenVino01/cam2-$(date +%d-%m-%Y).mp4 –r 10

Для остальных камер — по аналогии. Показалось, что фото будет много, поэтому выбрал скорость 10 кадров в секунду. Команды помещаю в cron (запуск в конце дня — в 18:00) для формирования файлов cam-.mp4.

Создаю файл cron.sh:

#!/bin/bash ffmpeg -f image2 -pattern_type glob -r 10 -i /home/petin/python3_prgs_1/OpenVino01/cam1/$(date +%d-%m-%Y)/'*.jpg' -y /home/petin/python3_prgs_1/OpenVino01/cam2-$(date +%d-%m-%Y).mp4 ffmpeg -f image2 -pattern_type glob -r 10 -i /home/petin/python3_prgs_1/OpenVino01/cam2/$(date +%d-%m-%Y)/'*.jpg' -y /home/petin/python3_prgs_1/OpenVino01/cam2-$(date +%d-%m-%Y).mp4 ffmpeg -f image2 -pattern_type glob -r 10 -i /home/petin/python3_prgs_1/OpenVino01/cam3/$(date +%d-%m-%Y)/'*.jpg' -y /home/petin/python3_prgs_1/OpenVino01/cam3-$(date +%d-%m-%Y).mp4 ffmpeg -f image2 -pattern_type glob -r 10 -i /home/petin/python3_prgs_1/OpenVino01/cam4/$(date +%d-%m-%Y)/'*.jpg' -y /home/petin/python3_prgs_1/OpenVino01/cam4-$(date +%d-%m-%Y).mp4

Добавляю задание cron. Записываю в файл /var/spool/cron/crontabs/petin строку

* 18 * * * /home/petin/python3_prgs_1/OpenVino01/cron.sh

Теперь настраиваю отправку файлов в Telegram. Создаю телеграм-бота: пишу пользователю @BotFather и придумываю имя. В ответ приходит сообщение с токеном для http api — его нужно сохранить.

Создаю группу, добавляю в неё бота, устанавливаю библиотеку:

pip3 install pytelegrambotapi

И пишу программу:

import telebot from telebot import types from datetime import datetime, timedelta from pathlib import Path keyboard1 = [["","Камера 1","Камера 2","Камера 3","Камера 4","Не надо"],["","cam1","cam2","cam3","cam4","no"]] bot = telebot.TeleBot('your-token'); @bot.message_handler(content_types=['text', 'document', 'audio']) def get_text_messages(message): chatId=message.chat.id print(chatId) key_1=[0,0,0,0,0,0] ftime=datetime.now() print(ftime.day," ",ftime.hour) day=ftime.strftime("%d-%m-%Y") if message.text == "/help": bot.send_message(message.from_user.id, "Привет, здесь ты можешь посмотреть, что делали мои котики за день 9:00–18:00. Набери /video") elif message.text == "/video": msg="здесь ты можешь посмотреть, что делали мои котики за день 9:00–18:00"+day bot.send_message(message.from_user.id, msg) keyboard = types.InlineKeyboardMarkup(); # клавиатура for i in range(1,6): #кнопка key_1[i] = types.InlineKeyboardButton(text=keyboard1[0][i], callback_data=keyboard1[1][i]); #добавляем кнопку в клавиатуру keyboard.add(key_1[i]); bot.send_message(message.from_user.id, "Выбери камеру", reply_markup=keyboard) else: bot.send_message(message.from_user.id, "Я тебя не понимаю. Напиши /help.") @bot.callback_query_handler(func=lambda call: True) def callback_worker(call): ftime=datetime.now() day=ftime.strftime("%d-%m-%Y") if call.data.find("cam") < 0: bot.send_message(call.message.chat.id, 'No'); else: if ftime.hour >= 18: bot.send_message(call.message.chat.id, 'Видео с камеры '+call.data.replace("cam","")+'. Wait ....'); videofile = Path(call.data+'-'+day+'.mp4') if videofile.is_file(): video = open(call.data+'-'+day+'.mp4', 'rb') bot.send_video(call.message.chat.id, video) bot.send_message(call.message.chat.id, "Загружено") else: bot.send_message(call.message.chat.id, 'Видео отсутствует !!!'); else: bot.send_message(call.message.chat.id, 'Просмотр видео текущего дня только после 18:00, Просмотр за предыдущий день'); ftime=datetime.now()- timedelta(days=1) dayold=ftime.strftime("%d-%m-%Y") videofile = Path(call.data+'-'+dayold+'.mp4') if videofile.is_file(): video = open(call.data+'-'+dayold+'.mp4', 'rb') bot.send_video(call.message.chat.id, video) bot.send_message(call.message.chat.id, "Загружено") else: bot.send_message(call.message.chat.id, 'Видео отсутствует !!!'); bot.polling(none_stop=True, interval=0)

Запуск бота (чтобы он мог отвечать на сообщения, скрипт должен быть постоянно запущен):

cd /home/petin/python3_prgs_1/OpenVino01 python3 pets_send_telegram.py

Скрипт бота также добавляю в автозагрузку.

Создаю файл autoupload_telegram.sh

#!/bin/bash cd /home/petin/python3_prgs_1/OpenVino01 python3 pets_send_telegram.py

И помещаю в автозагрузку autoupload.sh.

Обзор → Автоматически запускаемые приложения → Добавить

И указываю путь к python-скрипту.

Бот знает две команды: /help и /video. Когда просишь видео — открывает меню с выбором камеры. Бот присылает видео от сегодняшнего дня (если просим после шести вечера) или от вчерашнего.

Выбираем место для установки камер

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

Подсоединяю камеры к регистратору.

В сети — роутер, регистратор, NUC по Wi-Fi. При загрузке запускаются python-скрипт получения данных с камер и детектирования, плюс скрипт бота.

Захожу в Telegram, выбираю камеру и… начинаю смотреть за котиками.

Подводим итоги и приступаем к новой версии

Все файлы проекта доступны на github.

Я доволен результатом — теперь могу медитировать, наблюдая за своими питомцами.

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

Первым делом решил собрать фотографии питомцев: для тренировки сети нужно минимум по 300 фото каждого кота и по 100 — для тестирования. При этом коты не хотели фотографироваться в разных позах, так что после нескольких дней съёмок я собрал всего 314 снимков.

Выделил объекты на фото и пометил их (использую программу labelme):

sudo pip3 install labelme

Для каждой фотографии создаётся файл json.

Разделяю фото в папки train и test и запускаю скрипт для обучения модели.

import pixellib from pixellib.custom_train import instance_custom_training train_maskrcnn = instance_custom_training() train_maskrcnn.modelConfig(network_backbone = "resnet101", num_classes= 2, batch_size = 4) train_maskrcnn.load_pretrained_model("mask_rcnn_coco.h5") train_maskrcnn.load_dataset("Nature") train_maskrcnn.train_model(num_epochs = 300, augmentation=True, path_trained_models = "mask_rcnn_models")

За 7 дней прошло 25 шагов тренировки из 300 — не очень-то быстро. Ускориться помогут либо мощное железо, либо облачные сервисы с графическими процессорами. Например, серверы с GPU от Selectel: провайдер предлагает мощную ресурсную базу, с которой время тренировки удастся сократить с нескольких недель — до дней или даже часов.

Вот такую конфигурацию служба поддержки Selectel подобрала для меня:

На сервере уже была установлена заказанная мной ОС Ubuntu 20.04. Устанавливаю CUDA по этой инструкции и библиотеку pixellib.

Install the latest version of tensorflow(Tensorflow 2.0+) with: pip3 install tensorflow-gpu pip3 install imgaug pip3 install pixellib --upgrade

Сделал много дополнительных фотографий, разделил их на две папки и разметил, как предыдущие в программе labelme. Загрузил набор данных на сервер.

Для обучения нашей модели будем применять методику трансферного обучения, используя базовую модель mask_rcnn_coco.h5, обученную на 80 категориях объектов.

Загрузка mask_rcnn_coco.h5

wget "https://github.com/ayoolaolafenwa/PixelLib/releases/download/1.2/mask_rcnn_coco.h5"

Скрипт для обучения customtrain01.py

import pixellib from pixellib.custom_train import instance_custom_training train_maskrcnn = instance_custom_training() train_maskrcnn.modelConfig(network_backbone = "resnet50", num_classes= 5, batch_size = 4) train_maskrcnn.load_pretrained_model("mask_rcnn_coco.h5") train_maskrcnn.load_dataset("pets03") train_maskrcnn.train_model(num_epochs = 200, augmentation=True, path_trained_models = "mask_rcnn_models")

Запуск скрипта

python3 customtrain01.py

Процесс обучения отображается в терминале

Using resnet50 as network backbone For Mask R-CNN model Applying Default Augmentation on Dataset Train 608 images Validate 89 images Checkpoint Path: /home/petin/petscats/mask_rcnn_models Selecting layers to train Epoch 1/100 100/100 [==============================] - 394s 3s/step - batch: 49.5000 - size: 4.0000 - loss: 1.9734 - rpn_class_loss: 0.1194 - rpn_bbox_loss: 0.7562 - mrcnn_class_loss: 0.1773 - mrcnn_bbox_loss: 0.7554 - mrcnn_mask_loss: 0.1652 - val_loss: 1.8159 - val_rpn_class_loss: 0.0354 - val_rpn_bbox_loss: 0.7352 - val_mrcnn_class_loss: 0.2133 - val_mrcnn_bbox_loss: 0.7738 - val_mrcnn_mask_loss: 0.0583 - lr: 0.0010 Epoch 2/100 100/100 [==============================] - 287s 3s/step - batch: 49.5000 - size: 4.0000 - loss: 1.5770 - rpn_class_loss: 0.0347 - rpn_bbox_loss: 0.6571 - mrcnn_class_loss: 0.1848 - mrcnn_bbox_loss: 0.6495 - mrcnn_mask_loss: 0.0510 - val_loss: 1.5399 - val_rpn_class_loss: 0.0318 - val_rpn_bbox_loss: 0.5624 - val_mrcnn_class_loss: 0.1974 - val_mrcnn_bbox_loss: 0.6905 - val_mrcnn_mask_loss: 0.0578 - lr: 0.0010 Epoch 3/100 13/100 [==>...........................] - ETA: 3:29 - batch: 6.0000 - size: 4.0000 - loss: 1.6279 - rpn_class_loss: 0.0347 - rpn_bbox_loss: 0.6848 - mrcnn_class_loss: 0.1869 - mrcnn_bbox_loss: 0.6644 - mrcnn_mask_loss: 0.0571

Модели сохраняются в папку mask_rcnn_models на основе уменьшения потерь при проверке

Запуск

python3 testtrain01.py

Вывод

mask_rcnn_models\ mask_rcnn_model.001-1.851553.h5 evaluation using iou_threshold 0.5 is 0.723500

Проверяем модель на фотографиях

import pixellib from pixellib.instance import custom_segmentation segment_image = custom_segmentation() segment_image.inferConfig(num_classes= 5, class_names= ["BG", "mimicat", "tigercat","smokeycat","redcat","wildcat"]) segment_image.load_model("mask_rcnn_models/mask_rcnn_model.xxx-1.yyyyyy.h5") segment_image.segmentImage("myimg.jpg", show_bboxes=True, output_image_name="sample_out.jpg")

Модель готова, теперь её можно использовать в проекте.

За месяц аренды сервера для своей задачи я бы потратил 25 600 рублей. Целого сервера для одного пет-проекта «слишком много»: арендовать его можно совместно с друзьями, чтобы по очереди учить модели для разных задач.

0
7 комментариев
Написать комментарий...
Dmitry Kiselev

Хозяин: делает систему видеонаблюдения за котами, медитирует на них.
Коты: делятся на группы А и Б, и пока группа А отвлекает внимание хозяина, валяясь, потягиваясь и вылизываясь под камерами, группа Б проникает на кухню и взламывает холодильник.

Ответить
Развернуть ветку
Аккаунт удален

Комментарий недоступен

Ответить
Развернуть ветку
Надежда Токарева

Такие можно ставить в гостиницах для кошек, чтобы в отъезде можно было наблюдать за ушастыми и не беспокоиться ^_^

Ответить
Развернуть ветку
Сергей Георгиевский

У нас в гостинице просто стоят камеры в каждом номере. Нужны ли там такие усложнения? У автора задачи посложнее.

Ответить
Развернуть ветку
Denis Novikov

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

Ответить
Развернуть ветку
Санти Воид

камера наблюдения за питомцами.

Ответить
Развернуть ветку
Han

Узко товарищи смотрите применение данного проекта не ограничено питомцами! Автору спасибо за статью познавательно показательно!

Ответить
Развернуть ветку
4 комментария
Раскрывать всегда