{"id":14279,"url":"\/distributions\/14279\/click?bit=1&hash=4408d97a995353c62a7353088166cda4ded361bf29df096e086ea0bbb9c1b2fc","title":"\u0427\u0442\u043e \u0432\u044b\u0431\u0435\u0440\u0435\u0442\u0435: \u0432\u044b\u0435\u0445\u0430\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u0438\u043b\u0438 \u0437\u0430\u0435\u0445\u0430\u0442\u044c \u0440\u0430\u043d\u044c\u0448\u0435?","buttonText":"","imageUuid":""}

Mask R-CNN: как разделить разные объекты на записях с видеокамер?

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

Так как сжатые строки и ограниченные ресурсы коррелируют между собой, то нужно разобраться с ними в первую очередь. Эти проблемы подтолкнули нас к решению отказаться от обработки потокового видео, решили обрабатывать не все кадры, а только 1 кадр с дельтой по времени в 4 секунды (цифра выбрана исходя из опыта проб и ошибок). Для получения скриншотов наша задача оказалась очень подходящей, т.к. можно их скачивать через url адрес с помощью библиотеки python request.

Отсутствие обучающей выборки заставило нас обратить внимание на размеченные датасеты MS COCO. На просторах интернета нашли open source решения PythonAPI (pycocotools) – библиотека для использования СOCO API на языке python с предобученными весами на Mask R-CNN. Найденная информация подтолкнула нас к использованию именно этой реализации нейросети на Python 3, Keras и TensorFlow, генерирующую ограничительные рамки и маски сегментации для каждого из экземпляров объектов в изображении. Он основан на функциональной пирамидальной сети (FPN) и магистрали ResNet101.

С установкой пакета pycocotools возник ряд трудностей, повлекших за собой временные потери. Хотим рассказать, как вам избежать ошибок и не тратить время на поиски ответов на различных форумах.

Для установки пакета запустите из командной строки pip install. То же самое нужно проделать с Mask R-CNN (github). Пакеты необходимо именно клонировать из этого git репозитория, чтобы избежать ошибок. Еще одним важным условием успешного инсталлирования библиотеки является наличие установленного и прописанного в системные пути компонента Visual C ++ 2015 Build Tools (файл visualcppbuildtools_full.exe).

При запуске pip install pycocotools у нас возникла проблема:

Исправить ошибку получилось после внесения изменений в файл setup.py – библиотеки — там нужно было заменить строку

extra_compile_args=['-Wno-cpp', '-Wno-unused-function', '-std=c99'] на extra_compile_args={'gcc': ['/Qstd=c99']}

После данных манипуляций ошибок больше не возникало, и библиотека pycocotools установилась успешно.

Чтобы воспользоваться предобученными весами на датасете COCO вам нужно будет скачать файл mask_rcnn_coco.h5 и положить его в клонированную директорию Mask R-CNN. В папке samples есть файл demo, именно его мы и использовали как baseline для своего решения. При импорте библиотек, у вас может возникнуть ошибка.

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

Далее используем модель, обученную на наборе данных MS-COCO и загружаем уже существующие веса.

maskrcnn_model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_FILE, config=config) maskrcnn_model.load_weights(COCO_MODEL, by_name=True)

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

У нас уже собрано некоторое количество скриншотов, теперь осталось пробежаться по папке, прочитать каждое изображение, выбрать зону для распознавания и распознать объекты.

from PIL import Image arr = os.listdir('images/1-10') count_all=0 count_sotr = 0 z=0 res = pd.DataFrame(columns=['path','frame','people_all','sotr','clients', 'max_sotr']) for v in arr: image_list = os.listdir('images/'+v) for i in image_list: try image = Image.open('images/'+v+'/'+i) area = (1185,297,1435,635) # область анализа cropped_img = image.crop(area) results = maskrcnn_model.detect([np.array(cropped_img)], verbose=False) r = results[0] count_all =0 count_sotr=0 for k in (range(len(r['rois']))): if r['class_ids'][k] == 1: if r['rois'][k][0] > 233 : count_sotr = count_sotr + 1 count_all =count_all +1 except: print ('cannot open') cl = count_all-count_sotr print (v,i,count_all,count_sotr) new_row = [v,i,count_all,count_sotr,cl,0] res.loc[z] = new_row z = z +1 res['max_sotr'] = res.groupby(['path'])['sotr'].transform('max') writer = pd.ExcelWriter('images/result.xlsx') res.to_excel(writer, 'Sheet1',index=False) writer.save()

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

my_image = skimage.io.imread("foto.jpg") result = maskrcnn_model.detect([my_image], verbose=1) detect_results = result[0] visualize.display_instances(my_image, detect_results['rois'], detect_results['masks'], detect_results['class_ids'], class_names, detect_results['scores'])

В результате распознавания получим вот такую картинку:

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

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

0
Комментарии
-3 комментариев
Раскрывать всегда