Estudo exploratório da interação homem máquina em linguagem natural no contexto visual

Pequeno relatório do estudo exploratório da interacção homem máquina em linguagem natural no contexto visual que efectuei com base num conjunto de processos ilustrados com as respectivas relações no diagrama mais abaixo.

Este abordagem à interacção homem máquina em linguagem natural tendo em conta o contexto visual da máquina, foi efectuada com o propósito de integrar o conhecimento adquirido num projecto de controlo vocal de um braço robótico Niryo One.

A solução que montei para explorar esta área está próxima do end user. Foi efectuada com o base no ROS e nos serviços do google cloud, e deste modo os principais serviços são caixas negras. Esta abordagem serve as minhas necessidades de aplicação prática já que não procuro saber como funcionam os processos mais complexos.

No entanto, alguns dos serviços remotos podem ser substituídos por soluções locais, dos quais destaco o reconhecimento de objectos e faces construídas com base no opencv e tensorflow. Uma segmentação dos custos de utilização dos serviços do google que exibo mais abaixo, sugere que serão os processos com o maior beneficio económico na execução local.

ROS nodes

Os nodes ROS usados no projecto estão contidos no opencv_apps e no meta-pacote gc_bridge, que foi adoptado de um dos vários projectos que usei para compor esta exploração.

O pacote opencv_apps contêm os nodes locais que usei para explorar esta área. A exploração dos serviços de detecção facial do google tem de ser complementada por um node que republique a informação do rectângulo no node de reconhecimento facial no opencv. (TODO. colocar no repositório)

O gc_bridge contêm vários pacotes que contribuem em conjunto com outros que surgem como dependências do projecto.

  • gc_msgs
  • gc_dialogflow_bridge
  • gc_speech_bridge
  • gc_vision_bridge

Diagrama de relações entre os vários sistemas e mensagens envolvidas

gc_bridge

Meta pacote copiado do gc_bridge (https://github.com/jihoonl/gc_bridge), e ao qual foi adicionado posteriormente os outros pacotes. De origem o gc_bridge contribuiu com o gc_msgs e o gc_vision_bridge.

gc_msgs

Este pacote contém a definição das mensagens trocadas com o serviço que processa a interacção com os serviços de análise de imagem do google.

As mensagens definidas neste pacote são usadas pelos nodes  e serviços do gc_vision_bridge.

gc_dialogflow_brigde

Foi adaptado do pacote  dialogflow_ros (https://github.com/piraka9011/dialogflow_ros). Contém o interface com o Google dialogflow services alimentado em tempo real pelo microfone, via transcrição de voz para texto, e o seu resultado alimenta o sistema de transcrição de texto para voz. O resultado dos serviços do dialogflow é construído tendo em conta a informação existente num servidor de contexto remoto, alimentado pelo os nodes do gc_vision_bridge.

gc_vision_bridge

Este pacote contem o software que processa as imagens recolhidas pelo node usb_cam, e as redirige para os nodes especializados de análise, armazenando num servidor remoto as respostas de cada um deles.

gc_speech_bridge

Este pacote foi adaptado do pacote speech_database (http://wiki.ros.org/speech_database)

Este pacote passou a incluir o node speech2text_mic.py que foi obtido no pacote (dialogflow_ros)

 

 

 

Nesta fase exploratória o leque de entendimento que se expressa no conjunto de comandos implementados visa apenas aspectos descritivos e de focalização de atenção.

Comandos implementados

  • Enunciar os objectos que detecta nas imagem da camera  de video
  • Confirmar que está a ver um objecto
  • Indicar quantos objectos é que está a ver de um tipo especifico
  • Solicitação para ignorar determinados objectos
  • Solicitação para parar de ignorar objectos previamente ignorados
  • Saudar o utilizador

 

 

 

ROS roscore service

Instruções para correr o ROS roscore como serviço

Para o efeito é necessário criar dois ficheiros novos:

  • /etc/systemd/system/roscore.service
  • /etc/roscore_env.sh

Seguidamente usar o comando systemctl para testar o serviço e  a sua activação posterior.

Criar o ficheiro para a unit roscore.service

sudo nano /etc/systemd/system/roscore.service

Substituir “kinetic” por “melodic” ou outra distribuição do ROS, na linha que começa por “ExecStart=”

Substituir “ubuntu”  pelo user adequado na linha User=ubuntu

[Unit]
After=NetworkManager.service time-sync.target
[Service]
Type=forking
User=ubuntu
# Start roscore as a fork and then wait for the tcp port to be opened
# ----------------------------------------------------------------
# Source all the environment variables, start roscore in a fork
# Since the service type is forking, systemd doesn't mark it as
# 'started' until the original process exits, so we have the
# non-forked shell wait until it can connect to the tcp opened by
# roscore, and then exit, preventing conflicts with dependant services
ExecStart=/bin/sh -c ". /opt/ros/kinetic/setup.sh; . /etc/roscore_env.sh; roscore & while ! echo exit | nc localhost  11311 > /dev/null; do sleep 1; done"
[Install]
WantedBy=multi-user.target

Criar o ficheiro com as variáveis de ambiente para o roscore

sudo nano /etc/roscore_env.sh

Colocar o seguinte texto.

#!/bin/sh
export ROS_HOSTNAME=$(hostname).local
export ROS_MASTER_URI=http://$ROS_HOSTNAME:11311

Após criar estes ficheiros passamos a fase de teste.

Teste e conclusão da configuração do serviço roscore

Para testar iniciamos o serviço e seguidamente consultamos o seu estado com os seguintes comandos:

systemctl start roscore
systemctl status roscore

Se existir algum erro verificar se o texto foi bem copiado e as substituições bem feitas. Repetir a verificação até funcionar bem.

Após o serviço iniciar correctamente activar a sua inicialização automática com o seguinte comando:

systemctl enable roscore

O processo ficou concluido e o serviço roscore irá iniciar automaticamente.

Gestão do serviço roscore

Para iniciar o serviço

systemctl start roscore

Para saber o estado do serviço

systemctl status roscore

Para parar o serviço

systemctl stop roscore

Para ligar a inicialização automática do serviço

systemctl enable roscore

Para desligar a inicialização automática do serviço

systemctl disable roscore

 

 

ros package opencv-apps

 

http://wiki.ros.org/opencv_apps

https://github.com/ros-perception/opencv_apps

Install ros opencv apps

O pacote do ros opencv apps e as suas dependencias são instalados com os seguintes comandos:

Nota: se a instalação for no kinetic, basta substituir o melodic por kinetic.

sudo apt install ros-melodic-opencv-apps
sudo apt install xterm

Também convem ter instalado uma fonte de imagens video, como pr exemplo o node usb_cam. Este node pode ser instalado com o seguinte comando:

sudo apt install ros-melodic-usb-cam

Criar o ficheiro usbcam.launch para o node usb cam  num pacote de teste com a seguinte configuração:

<launch>

  <arg name="view" default="false" />
  <arg name="tf" default="true" />

  <node if="$(arg tf)" pkg="tf" type="static_transform_publisher" name="usb_cam_tf" args="10.0 0 0.10 0 0 0 /base_link /usb_cam 10" />

  <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
    <param name="video_device" value="/dev/video0" />
    <param name="image_width" value="800" />
    <param name="image_height" value="600" />
    <param name="pixel_format" value="yuyv" />
    <param name="camera_frame_id" value="usb_cam" />
    <param name="io_method" value="mmap"/>
  </node>

  <node if="$(arg view)" name="image_view" pkg="image_view" type="image_view" respawn="false" output="screen">
    <remap from="image" to="/usb_cam/image_raw"/>
    <param name="autosize" value="true" />
  </node>

</launch>

Esta configuração é genérica, inclui a publicação do transform para a camera e a opção de visualização do video.

Pode ser executada com opções com o seguinte comando:

roslaunch pacote usbvideo.launch view:=true tf:=false

Funciona, pelos meus testes em várias cameras, umas capazes de maior resolução que outras, e pode ser modificada para a camera que usamos.

Configure face recognition on opencv apps

De modo a mais facil controlo sobre as configurações de lançamento dos nodes envolvidos no reconhecimento facial copiar para os ficheiros  os seguintes ficheiros launch para um pacote de teste:

  • https://raw.githubusercontent.com/ros-perception/opencv_apps/indigo/launch/face_detection.launch
  • https://raw.githubusercontent.com/ros-perception/opencv_apps/indigo/launch/face_recognition.launch

De seguida adequar as copia dos ficheiros.

No ficheiro face_recognition.launch:

O pacote usado (o nome do pacote para onde foi copiado) deve o opencv_apps, na seguinte linha:

<include file=”$(find opencv_apps)/launch/face_detection.launch”

O tópico da imagem (da camera usb) que o node subscreve, é definido pelo default deve ser trocado  pelo topico que o node usb_cam publica (normalmente /usb_cam/image_raw) na linha:

<arg name=”image” default=”image” />

No ficheiro face_detection.launch:

Proceder do modo descrito para o tópico da imagem.

Executar  o reconhecimento facial

A base de dados de faces reconhecidas fica guardada na seguinte pasta:

~/.ros/opencv_apps/face_data

Na primeira execução não existem faces na base de dados, pelo que é necessário efectuar a sua recolha de pessoas a serem reconhecidas, e uma reinicialização do programa (que deve acontecer após cada sessão de recolha).

Para iniciar o reconhecimento facial deve iniciar primeiro o node que publica a imagem da camera de video, o usb_cam.

roslaunch pacote usbcam.launch view:=false tf:=false

De seguida executar o launch file do reconhecimento facial (face_recognition.launch) com o seguinte comando:

roslaunch pacote face_recognition.launch

Este comando executa os seguintes nodes:

  • face_detection
  • face_recognition
  • face_recognition_trainer

Nesta configuração base acontece o seguinte:

O face_detection abre uma janela com circulos nas faces (e respectivos olhos) detectadas;

O face_recognition abre uma janela com circulos nas faces detectadas e indicação do rosto reconhecido;

face_recognition_trainer abre uma janela que permite adicionar rostos a base de dados de faces a reconhecer.

A abertura destas janelas é opcional, assim como o lançamento do node de treino (face_recognition_trainer),

 

já que numa aplicação prática o resultado do reconhecimento pode ser recolhido pela subscrição do tópico: /face_recognition/output   com mensagens do tipo opencv_apps/FaceArrayStamped.

rostopic echo /face_recognition/output

header: 
seq: 2486
stamp: 
secs: 1572481537
nsecs: 290916277
frame_id: "usb_cam"
faces: 
- 
face: 
x: 372.0
y: 191.0
width: 209.0
height: 209.0
eyes: 
- 
x: 413.0
y: 177.0
width: 49.0
height: 49.0
label: "sergio"
confidence: 2279.43355205

 

roslaunch rospibot6 usbcam.launch view:=false tf:=false

roslaunch rospibot6 face_detection.launch

roslaunch rospibot6 face_recognition.launch

 

Descobri este pacote depois de ter tentado compilar o pacote face_recoginiton, com documentação no seguinte link:

http://wiki.ros.org/face_recognition

No entanto não compila nas versões mais recentes do ros.

Após efectuar o treino, o face_recgnition funciona em duas fases
na primeira detecta a face a reconhecer, e marca a região, na segunda identifica a face exibida nessa região na base de dados que alimentou o treino.

Como a base do pacote é opencv, voltei a minha atenção para ai, e mais especificamente para a documentação da versão que vem com ubuntu/bionic, e descobri este tutorial:

https://docs.opencv.org/3.2.0/da/d60/tutorial_face_main.html

O tutorial parece ser a resposta que me pode permitir fazer um node do ros para reconhecimento facial.

Consegui compilar os 3 exemplos, e do que compreendi, apenas o ultimo faz uma identificação ou não da face.

O exemplo procede à identificação da ultima face de uma base de dados experimental.

Por isso conclui que este seria um bom modelo para poder rescrever o pacote.

A fase da detecção facial está tambem descrita num tutorial do opencv disponivel no seguine endereço:

https://docs.opencv.org/…/d3a/facedetect_8cpp-example.html

Também considerei este exemplo um bom modelo para a parte que faltava.

No entanto o trabalho que tinha pela frente nao ia ser facil e por isso decidi que o melhor era procurar mais um bocado antes de tentar rescrever tudo de novo (para alem dos blocos retirados dos exemplos), que seria o que me esperava. Foi quando descobri o pacote opencv_apps.

Uma ultima nota sobre a performance da detecção facial com o opencv.

A face detection demora menos de 100ms, num portatil com um i7. No pi2 demora quase 1s (750ms).

 

ros package people

http://wiki.ros.org/people

Pelo que eu percebi necessita de uma camera stero.

Para compilar o pacote é necessário instalar as seguintes dependencias:

sudo apt install ros-melodic-easy-markers

sudo apt install ros-melodic-bfl

sudo apt install ros-melodic-kalman-filter