Введение

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

То, что мы собираемся сделать, - это всего лишь одна альтернатива, которую мы можем классифицировать как систему обнаружения падений на основе зрения. Цель состоит в том, чтобы построить модель, которая способна обнаруживать падения с помощью простого простого видео. Большая часть этого проекта основана на этой статье, Обнаружение падения на основе зрения в реальном времени с изображениями истории движения и сверточными нейронными сетями, 2018, T. HARALDSSON. [1]

Все коды здесь.

Отслеживание движения

Чтобы запечатлеть движение, которое считается временным, мы можем использовать один метод компьютерного зрения, который называется Изображение истории движения (MHI). Идея состоит в том, чтобы включить предыдущую информацию о движении в текущее изображение, уменьшив предыдущее положение человека в течение определенного периода или количества кадров.

Изображение истории движения (MHI)

Алгоритм MHI, который мы собираемся использовать для предварительной обработки, показан ниже. Для большей интуиции больше объяснений в этом вдо. Надеюсь, это станет яснее, когда вы глубже изучите сценарий, когда мы его реализуем.

Выполнение

Источник данных

Набор данных обнаружения падений (FDD) [3] состоит из видео с одной камеры в разных местах - Дом, Кофейня, Офис и Аудитория. Частота кадров составляет 25 кадров / с, а разрешение - 320x240 пикселей.

Для этого эксперимента были выбраны Домашняя (Home_01.zip и Home_02.zip) и Кофейная (Coffee_room_01.zip и Coffee_room_02.zip), поскольку они были дополнены аннотациями.

data
├── Coffee_room
│   ├── Annotation_files
│   │   ├── video (1).txt
│   │   ├── ...
│   └── Videos
│       ├── video (1).avi
│       ├── ...
└── Home
    ├── Annotation_files
    │   ├── video (1).txt
    │   ├── ...
    └── Videos
        ├── video (1).avi
        ├── ...

Для каждого видео аннотация дается video (i).txt в Annotation_files.. Каждый файл аннотации содержит: каждый файл содержит:

  • номер кадра начала осени
  • номер кадра конца осени
  • высота, ширина и координаты центра ограничивающей рамки для каждого кадра
48
80
1,1,0,0,0,0
2,1,0,0,0,0
3,1,0,0,0,0
4,1,0,0,0,0
5,1,292,152,311,240
6,1,292,152,311,240
...

Предварительная обработка

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

Coffee_room/Annotation_files/
'video (26).txt'
197
227
'video (50).txt'
1816
1852
'video (52).txt'
87
113

Подготовка наборов данных для обучения, проверки и тестирования

Наборы данных для каждого местоположения были распределены для наборов данных для обучения, проверки и тестирования с соотношением 0,7, 0,2 и 0,1 соответственно. Каждый клип относится только к одному из наборов данных.

Процессор MHI

Алгоритм MHI обрабатывается MHIProcessor Class для генерации MHI для обучения. Параметр dim=128 - это размер ввода для модели MobileNetV2. Каждый кадр записи MHI каждые два кадра, interval=2, для 40 кадров, duration=40 со скоростью затухания 1/duration.

class MHIProcessor:
def __init__(self, dim=128, threshold=0.1, interval=2, duration=40):
# initialize MHI params
self.index = 0
self.dim = dim
self.threshold = threshold
self.interval = interval
self.duration = duration
self.decay = 1 / self.duration
def process(self, frame, save_batch=True):
    ...
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    ...
        frame = cv2.resize(frame,(self.dim, self.dim),
                           interpolation=cv2.INTER_AREA)
        diff = cv2.absdiff(self.prev_frame, frame)
        binary = (diff >= (self.threshold * 255)).astype(np.uint8)
        mhi = binary + (binary == 0) * np.maximum(self.mhi_zeros,
                                       (self.prev_mhi - self.decay))
    ...

Образец ОМС, созданный MHIProcessor

Всю предварительную обработку можно выполнить, запустив preprocess.py.

python preprocess.py --source data --dest dataset

Наборы данных для обучения, проверки и тестирования будут созданы.

dataset
├── train
│   ├── fall
│   │   ├── Coffee_roomHome_01.zip80.png
│   │   ├── ...
│   └── not_fall
│       ├── Coffee_roomHome_01.zip82.png
│       ├── ...
├── val
│   ├── fall
│   │   ├── Coffee_roomHome_02.zip192.png
│   │   ├── ...
│   └── not_fall
│       ├── Coffee_roomHome_02.zip80.png
│       ├── ...
└── test
    ├── fall
    │   ├── Coffee_room1/duration376.png
    │   ├── ...
    └── not_fall
        ├── Coffee_room1/duration80.png
        ├── ...

Модель

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

class FDNet(nn.Module):
    def __init__(self, out_features=2):
        super(FDNet, self).__init__()
        mnet = models.mobilenet_v2(pretrained=True)
        for name, param in mnet.named_parameters():
            if("bn" not in name):
                param.requires_grad_(False)
            
        in_features = mnet.classifier[1].in_features
        mnet.classifier = nn.Sequential(
                                nn.Dropout(p=0.2, inplace=False),
                                nn.Linear(in_features,500),
                                nn.ReLU(),
                                nn.Dropout(),
                                nn.Linear(500, out_features))
        self.mnet = mnet
        
    def forward(self, images):
        features = self.mnet(images)
        
        return features

Обучение

Перед запуском training.ipynb в Google CoLab не забудьте загрузить dataset в то же место.

Оценка
Оценка тестового набора данных имела точность 95% с матрицей неточностей, приведенной ниже:

from sklearn.metrics import confusion_matrix
cf = confusion_matrix(targets_np, outputs_np)
array([[  61,   59],        
       [  21, 1317]])
tn, fp, fn, tp = (61, 59, 21, 1317)

Визуализируйте результат

Посмотрим на результат на примере набора тестов.

Вывод

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

В следующей статье я покажу вам, как развернуть нашу модель PyTorch в Amazon Sagemaker. Надеюсь, это тоже будет полезно. А пока, если вам понравилась эта статья или вы считаете ее полезной, пожалуйста, хлопните в ладоши. Любые комментарии или вопросы приветствуются.

PS. К сожалению, я обнаружил, что ссылка на набор данных по обнаружению падений не работает. Я не уверен, когда это будет доступно. Однако с некоторой адаптацией вы можете рассмотреть возможность использования другого набора данных, такого как Набор данных обнаружения падения UR для обучения, использования созданных наборов данных MHI для обучения или использования уже обученной модели PyTorch для вывода.

Использованная литература: