Skip to content

Latest commit

 

History

History
552 lines (410 loc) · 28.7 KB

README.md

File metadata and controls

552 lines (410 loc) · 28.7 KB

[EN] Antiterror security project

Overview

Greetings! Here I would like to share with you the results of my coursework at Robotics Department of Sirius University.

Introduction

The goal was to create and realize a method to detect adandoned items in the elevator's cabin. This's a very important task, because abandoned items can pose a threat to the safety of people.

Let's take a look at the images. We start with an image of an empty elevator car.

drawing

The light from the light bulb is actually non-permanent, so the illumination can change.

drawing

Also the cabin moves, then the camera, so the image can be shifted from its original position. And it makes the task harder.

You still can't see it here, but these lines, they actually have different lenght and even orientation.

drawing

Sometimes there are lost items it the elevator cab, we need to detect them.

drawing

Often people put ads on the walls of the elevator. Such things hardly pose a real threat, so we want to ignore their appearnce.

drawing

So what solution have I proposed?

Proposed solution

Floor detecion

Firstly, we need to find a working surface - the cabin's floor. To solve this problem, I've used a Canny edge detector with little post-processing. Below you can see the resulted mask.

drawing

It's definitely not ideal, but it's good enough. Later I want to improve this result, may be another edge detector will show better performance.

You can find the entire source code for solving this problem in the working_surface module.

Search for forgotten items

Optical flow can't help as to determine the cabin's shift, so I've formulated the following hypothesis: the cabin is stable, but every time we make a shot, random noise appearce so the pixels are corrupted now.

drawing

Noise between two empty images which we saw above, when they are in grayscale format. As you can see, it's definitely not normal, it's more like Beta distribution with both $\alpha$ and $\beta$ = 0.5

If there is a noise, so we can try to get it from the corrupted images, estimate it then try to remove. In my hypotesis, using noise estimation and may be a post-processing, we can detect real forgotten items.

Here you can see the table with lower and upper border we have computed according to different parameters of the algorithm. These borders we can you to threshold image, for example, using thresholdImage from noise_borders module.

Color images Gray images
Strategy With histogram equalization Without histogram equalization With histogram equalization Without histogram equalization
Max -701, 650 -533, 515 -235, 225 -175, 179
Mean -523.875, 425.5 -390.875, 308.125 -174.5, 147.5 -127.875, 106.375
Median -491.5, 329 -381.5, 212 -162.5, 112 -126, 73

On this stage, we have a denoised and thresholded image, then we need to finally detect the lost objects.

You can find the entire source code for solving this problem in the noise_borders module.

Object detection

We want to find the left objects, that is, circle them in a frame, so the guard can pat attention to them. Pixels, which locates next to each other, are the pixels of the same object, so we can recursively find this object's borders and circle it.

As a result, we get something like this:

drawing

You can find the entire source code for solving this problem in the detection module.

Results

Using this pipeline with different parameters, like, use histogram equalization or not, use grayscale or BGR format and etc, you cant achieve the following result:

Validation Test
Straregy, parameters and postprocessing Precision Recall F2 Precision Recall
Mean, Color, without eq.; M3x4, D7x3 0.741 0.855 0.830 1.000 1.000
Mean, Color, with eq.; M3x5, D7x3 0.856 0.710 0.735 1.000 0.727
Median, Color, without eq.; M3x4, D7x3 0.369 0.949 0.722 1.000 1.000

As you can see, we've achieved the following results: second algo can detect around 70% of all lost items, but it'll generate on 1 extra frame for every 6 correct ones. Third variant will detect around 95% of all lost items, which is very good, but it'll also generate 2 extra frames for every one correct. First implementation just have the best ratio between precision and recall.

(Here Mx is a shortcut for MaxNeighbour filter, Dx is a shortcut for Dilate filter)

Details

In the case you want to know more about the details or you want to read about this problem in more scientific way, you can read my report in Russian.

Install and Run

To run install and run this peoject, you can follow these steps:

  1. Make sure that you already have installed cmake>=3.10, cause this project is cmake-based, and git to clone this repository. Also you need an opencv c++ library installed. Google tests will be needed for testing, if for some reasons you dont have this library, you will need to edit the file called ./CMakeLists.txt

  2. Clone this project using the following command:

     git clone [email protected]:windowsartes/AntiterrorSecurityProject.git
     cd AntiterrorSecurityProject/

    So you are in the project root directory now.

  3. To build the project, there are 2 options:

    1. If you have a make installed into your system (or its equivalent):
        mkdir build
        cd build
        cmake ..
        make
    2. In the case you don't have a make (or its equivalent):
      mkdir build
      cd build
      cmake ..
      cmkae --build .
  4. The project have built so you can use the cli now:

  5. (You are still in the ./build directory)

    ./antiterror_security <path_to_your_image> [-s] [path_to_dir]

    Be sure to pass as the first argument the path to the file (absolute or relative to the ./build directory) where you want to find leftover items. The result can be saved in a directory of your choice, to do this, pass the "-s" flag as the second argument, followed by the path to this directory.

    Note that it works fine for my dataset, in your case may be you will be needed to compute a new bounds for noise using "noise_dorders" module and new mask for working surface with "working_surface" module

How to Use the Project

In the case you want to use this project for your data out of box, there will be some trouble cause:

1. Working surface mask will be incorrect, so you need to re-compute it;
2. Boundaries for noise will be incorrect too, so re-compute them;

Because of this to point, I'll describe source code modules so you can use them proper.

  • detection - contains the code for object visual detection; use it with already thresholded image;
  • filters - contains some useful filters, they are commonly used inside other functions;
  • noise_borders - contains some functions for computing the noise lower and upper borders; all the preprocessing takes place inside its core function, so you can use it out of box;
  • preprocessing - use it to prepare you data; commonly used inside other functions;
  • utils - contains some useful functions;
  • working_surface - use it for working surface searching; its core function, findSurface, can be used out of box, In other words, without any preprocessing;

For more details, read module's readme and function's dockstrings.

Testing

You must be in the ./build directory, because the paths to the test data are written relative to this directory. To run all tests, you can use this command.

./tests/tests

If you want to run tests for specific function, you can ues this command

./tests/tests --gtest_filter="functionName.*"

For example, if you want to test quickSelectMedian function, use

./tests/tests --gtest_filter=quickSelectMedian.*

Future ideas

In the future, I would also like to implement the following ideas for this project:

  • Mark up the data, so I can compute metrics automatically. Now I have to do it by my hands T_T;
  • Compare my algorithm with others. For example, with Hoare's algorithm for object detection;
  • Tune Github actions;
  • Improve the working sufrace detection algo;

Credits

Thanks to my academic advisor, Andrei V. Shipatov, for the opportunity to try my hand at such an interesting project.

License

I use the MIT License here, so feel free to copy and modify this code.

[RU] Система антитеррористической безопасности

Обзор

Приветствую! Здесь я хотел бы поделиться с вами результатами моей курсовой работы, которую я выполнял как студент образовательной программы «Математическая робототехника и искусственный интеллект» университета «Сириус».

Введение

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

Давайте взглянем на снимки кабины, чтобы понять, с чем придётся иметь дело. Мы начинаем со снимка пустой кабины лифта.

drawing

Освещённость кабины может меняться в процессе её движения.

drawing

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

Здесь это едва ли заметно, но у этих линий различная длина. Более того, у них чуть-чуть отличается и ориентация.

drawing

Иногда в кабине остаются какие-то вещи, их-то нам и нужно уметь находить.

drawing

Часто люди клеят на стенки лифта объявления, стикеры и т.д. Едва ли эти вещи несут в себе какую-то угрозу, поэтому их мы хотим игнорировать.

drawing

Так какое же решение я предложил?

Предложенное решение

Обнаружение пола

В первую очередь необходимо найти рабочую поверхность кабины - ей пол. Для решения этой задачи я использовал детектор границ Кэнни и лёгкую постобработку. Ниже вы можете наблюдать результат работы этого алгоритма:

drawing

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

Весь исходный код для решения этой задачи вы можете найти в модуле working_surface.

Поиск оставленных вещей.

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

drawing

Шум мужду двумя пустуми изображениями, которые мы видели выше, когда они представлены в чёрно-белом варианте. Как можно заметить, шум распределён совсем не нормально, скорее, это Бета-распределение с параметрами $\alpha$ and $\beta$ = 0.5

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

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

Цветное изображение Чёрно-белое изображение
Стратегия оценивания шума С выравниванием гистограммы Без выравнивания гистограммы С выравниванием гистограммы Без выравнивания гистограммы
Max -701, 650 -533, 515 -235, 225 -175, 179
Mean -523.875, 425.5 -390.875, 308.125 -174.5, 147.5 -127.875, 106.375
Median -491.5, 329 -381.5, 212 -162.5, 112 -126, 73

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

Весь исходный код для решения этой задачи вы можете найти в модуле noise_borders.

Детектирование объектов

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

В результате, получаем что-то такое:

drawing

Весь исходный код для решения этой задачи вы можете найти в модуле detection.

Результаты

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

Validation Test
Стратегия оценки шума, параметры алгоритма и постобработка Precision Recall F2 Precision Recall
Mean, Цветное, без выр.; M3x4, D7x3 0.741 0.855 0.830 1.000 1.000
Mean, Цветное, с выр.; M3x5, D7x3 0.856 0.710 0.735 1.000 0.727
Median, Цветное, без выр.; M3x4, D7x3 0.369 0.949 0.722 1.000 1.000

Как вы можете видеть, мы достигли следующих результатов: второй алгоритм может обнаружить около 70% от всех оставленных в лифте вещей, зато на каждые 6 верно сгенерированных рамок будет всего 1 лишняя. Третий вариант алгоритма будет верно находить уже 95% от всех вещей, но из 3 сгенерированных рамок 2 будут некорректные. Первый вариант алгоритма просто обладает наилучшим соотношением precision и recall.

(Mx - это сокращение для MaxNeighbour фильтра, Dx - сокращение для фильтра Dilate)

Детали

Если же вы хотите в деталях знать, что и как я делал, или хотите почитать текст в более научном стиле, обратите внимание на мой отчёт о проделанной работе.

Собрать и запустить проект

Чтобы собрать и запустить этот проект, вы можете следовать этим шагам:

  1. Убедитесь, что вы установили cmake>=3.10, потому что этот проект cmake-based, и git, чтобы склонировать этот репозиторий. Также понадобится плюсовая библиотека opencv. Гугл-тесты будут необходимы для тестирования кода, если же у вас нет этой библиотеки, вам нужно будет отредактировать файл под названием ./CMakeLists.txt

  2. Склонируйте этот репозиторий с помощью следующей команды:

     git clone [email protected]:windowsartes/AntiterrorSecurityProject.git
     cd AntiterrorSecurityProject/

    Теперь вы находитесь в корневой директории проекта.

  3. Есть 2 варианта, чтобы собрать этот проект:

    1. Если в вашей системе установлен make (или его аналог):
        mkdir build
        cd build
        cmake ..
        make
    2. В случае, если make (или его аналога) у вас нет:
      mkdir build
      cd build
      cmake ..
      cmkae --build .
  4. Проект собран, теперь можно использовать cli:

    (Вы всё ещё в директории ./build)

    ./antiterror_security <path_to_your_image> [-s] [path_to_dir]

    Обязательно нужно первым аргументом передать путь до файла (абсолютный или записаный относительно директории ./build), на котором вы хотите найти оставленные предметы. Результат можно сохранить в вами выбранной директории, для этого передайте флаг "-s" вторым аргументом и за ним путь до этой директории.

    Заметьте, что моё решение хорошо работает с моими данными, в вашем случае может понадобиться пересчитать оценки на шум и заново найти маску для веделения рабочей зоны.

Как использовать этот проект

В случае, если вы хотите использовать этот проект для своих данных из коробки, возникнут некоторые проблемы:

  1. Маска рабочей поверхности будет некорректной, поэтому ее необходимо вычислить заново;
  2. Границы для шума тоже будут неверными, так что пересчитайте их;

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

  • detection - содержит код для визуального обнаружения объектов; используйте его с изображениями, чьи пиксели уже разделены на пиксели поверхности и пиксели объектов;
  • filters - содержит несколько полезных фильтров, которые используются во время постобработки;
  • noise_borders - содержит некоторые функции для вычисления нижней и верхней границ шума; вся предварительная обработка происходит внутри его основной функции, так что вы можете использовать её из коробки;
  • preprocessing - используйте его для подготовки ваших данных; обычно его функционал используется внутри других функций или cli;
  • utils - содержит несколько полезных функций;
  • working_surface - используйте его, чтобы найти рабочую поверхность; его основная функция, findSurface, может использоваться из коробки. Другими словами, без какой-либо предварительной обработки;

Чтобы получить более детальное описание, читайте личное README каждого из модулей и докстринги функций.

Тестирование

Вы должны находится в директории ./build, потому что пути до тестовых данных прописаны относительно этой директории. Чтобы запустить все тесты, используйте следующую команду:

./tests/tests

Если вы хотети протестировать только какую-то отдельную функцию, используйте следующую команду:

./tests/tests --gtest_filter="имяФункции.*"

Например, чтобы протестировать функцию quickSelectMedian, используйте

./tests/tests --gtest_filter=quickSelectMedian.*

Идеи на будущее

В будущем, работая над этим проектом, я хотел бы реализовать следующие идеи:

  • Разметить данные, чтобы я смог считать метрики автоматически. Сейчас я вынужден делать это руками T_T;
  • Сравнить мой алгоритм с известными аналогами. Например, с кфскадным алгоритмом Хоара;
  • Настроить Github actions;
  • Улучшить алгоритм нахождение рабочей поверхности;

Благодарности

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

Лицензия

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