Este projeto tem como objeto obter dados/informações sobre uma região monitorada por uma CCTV como por exemplo:
- Detecção das pessoas no vídeo
- Geração de mapa de calor com base nas regiões com maior fluxo de pessoas
- Número de pessoas em cada uma das áreas segmentadas no momento atual
- Número total de pessoas detectadas em cada área segmentada
- Ids/pessoas em cada uma das áreas
- Ids/pessoas que estiveram na área
- Histórico das áreas acessadas por cada pessoa
- Tempo de permanência em cada uma das áreas
-
Instalar as dependências: Inicialmente certifique-se de que as dependências necessárias foram instaladas, isso pode ser feito executando o seguinte comando:
pip install -r requirements.txt
-
Navegue até a pasta do projeto: A partir da pasta do projeto execute o comando:
python main.py
-
Saída:
- O vídeo contendo a inferência e o mapa de calor será exibido em uma janela
- Os arquivos contendo as estatísticas serão gerados na pasta stats
Nesta seção será apresentada a ideia geral do funcionamento do código bem como o papel de cada um de seus componentes. Inicialmente trataremos das classes auxiliares como person,area,heatMap e stats então iremos tratar da classe principal, videoAnalyzer para conectar todos os componentes, além de realizar a geração das estatísticas e a inferência no vídeo. Por fim mostraremos o fluxo do arquivo principal main.py.
1. person: A classe person é utilizada para armazenar os dados referentes à pessoas identificadas no vídeo, esta tem como atributos:
id➡️ Número de identificação da pessoa detectadapositionHistory➡️ É um deque(Double ended queue) utilizada para aramazenar as últimas n posições da pessoa, onde n é escolhido pelo usuáriovisitedAreas➡️ É uma lista que contém a sequência de áreas visitada pelo usuário, a lista é atualizada apenas caso o úsuario mude da área atual para outra- currentArea ➡️ Determina o nome da área atual do usuário
BBox➡️ Coordenadas da bounding box da pessoa no frame atualBBoxColor➡️ Cor da bounding box, está é utilizada para melhorar a visualização da área em que a pessoa se encontraframesSpentInArea➡️ Dicionário que tem como chave os nomes das áreas e o valor obtido ao acessar as chaves é o tempo(número de frames) que a pessoa permaneceu na árealastFrameDetected➡️ Último frame em que a pessoa foi detectada
já os métodos dessa classe são os seguintes:
_initFramesSpentInArea(self,areasDict)➡️ Utilizado para construir o dicionárioframesSpentInAreaa partir de um dicionário contendo as áreasdist2centroid(self,centroid)➡️ Calcula a distância entre a última posição que a pessoa foi detectada e um centroide detectado no frame atualupdatePosition(self,bbox,centroid)➡️ Atualiza o BBox da pessoa e posição atual
2. area: A classe area armazenda dados de cada uma das areas segmentadas. Os atributos dessa classe são:
name➡️ Armazena o nome da áreacolor➡️ Armazena a cor relacionada a áreavertices➡️ Armazena os vértices que delimitam a áreaIdsRecordInArea➡️ Armazena os Ids das pessoas que acessaram a áreacurrentIdsInArea➡️ Armazena os Ids das pessoas que se encontram na área atualmentecurrentNumberOfPeople➡️ Armazena o número de pessoas na área atualmentetotalNumberOfPeople➡️ Armazena o número total de pessoas que acessou a área
Essa classe possui apenas um método sendo ele o isInside, o qual verifica se o centroide de uma pessoa está dentro da área.
3. heatMap: A classe heatMap tem como objetivo gerar o mapa de calor do vídeo. Essa classe tem os seguintes atributos:
height➡️ Altura do vídeowidth➡️ Largura do vídeodecay➡️ Taxa de decaimento do mapa de calor, utilizado para suavizar o mapa ao longo do tempodetectionMatrix➡️ Matrix que armazena as regiões onde ocorreram as detecções
Abaixo estão listado os métodos dessa classe e suas funcionalidades:
applyDecay(self)➡️ Aplica o decaímento na matrizupdateDetectionMatrix(self, bbox)➡️ Adiciona o valor 1 na matrizdetectionMatrixnas regiões relativas aos pixels onde foram inferidas as bounding boxes no frame atualgetNormalizedDetectionMatrix(self)➡️ retorna a matrizdetectionMatrixnormalizadagetColoredHeatMap(self)➡️ Aplica um mapa de cores na matriz normalizada de modo a produzir o mapa de caloroverlayHeatMap(self, frame)➡️ Sobrepõe o heatmap ao frame
3. stats: A classe stats é responsável por gerar as estatíscas e escreve-las em arquivos de saída, tendo como atributos:
peopleDict➡️ Dicionário da classepersonareasDict➡️ Dicionário da classeareafilename➡️ nome da pasta onde serão armazenados os arquivos gerados
Os métodos da classe são updateAreasStats(self) e updatePeopleStats(self) utilizados para imprimir as informções das áreas e das pessoas.
Como mencionado anteriormente a classe videoAnalyzer tem como papel unificar todas as classes implementadas anteriormente. Os atributos dessa classe são:
id➡️ Inicializado como zero e é imcrementado em um a cada pessoa nova que é identificadaareasDict➡️ Dicionário contendo as áreaspeople➡️ Dicionário contendo as pessoas identificadasheatmap➡️ Mapa de calorstatistics➡️ Instância da classestats
Os métodos dessa classe são os seguintes:
_buildAreasDict(self,areasList)➡️ Constroí o dicionário de áreas a partir de uma lista contendo as áreasgetData(self,results)➡️ retorna uma lista contendo tuplas de centroides e bounding boxes extráidos de results, que dados retornados pela YOLOv8 ao realizar inferência em um frame do vídeo.removeLostPeople(self,frameNumber)➡️ Remove pessoa do dicionáriopeoplecaso essa não seja detectada por mais de 10 framesupdatePeopleDict(self,results,frameNumber,threshold = 20)➡️ Verifica se algum dos centroides do frame atual está próximo do último centroide de uma pessoa do dicionáriopeoplese isso ocorre, atualiza as informações da pessoa, caso não ocorra uma nova pessoa é adicionada ao diconárioupdatePersonArea(self)➡️ Atualiza a área em que cada uma das pessoas se encontramupdateAreas(self)➡️ Atualiza os atributos das áreas emareasDictdrawAreas(self, frame)➡️ Desenha as áreas no frame do vídeodrawBoundingBoxes(self,frame)➡️ Desenha as Bounding boxes das pessoas identificadas no frame do vídeobuildHeatMap(self,frame)➡️ Atualiza o mapa de calorprocessVideo(self,results,frameNumber,frame)➡️ Une os métodos da classe de modo a produzir os resultados durante o processamento do vídeo
No arquivo main.py foi importado o modelo YOLOv8 da biblioteca ultralytics, nele é feito a segmentação das áreas de interesse do vídeo, bem como a criação de uma lista dessas áreas. É então feito processamento dos frames do vídeos onde a YOLOv8 é utilizada para obter os dados desejados, os quais são armazendos em results, em seguida é feito o processamento desses dados utilizadno o método videoProcess() da classe videoAnalyzer.
O vídeo contendo os resultados pode ser visto no link abaixo: link do vídeo
