Desenvolvimento

29 dez, 2017

Melhores 2017 – Criando um espelho inteligente com uma Up Board, MagicMirror2 e uma câmera RealSense

Publicidade

Nesta série, estamos revivendo alguns dos melhores artigos publicados no Portal iMasters durante o ano de 2017. A ideia é que o material não se perca e você possa relembrá-lo, entrando em 2018 preparado para receber mais conteúdos tão bons quanto esse!

***

Eu sempre quis criar um espelho inteligente para deixar meu apartamento aqui no Brasil mais geek. A ideia é muito simples: adicionar uma pequena placa e um monitor por trás de um espelho e criar um código que dê informações úteis para a pessoa em sua frente.

Eu vi algumas implementações assim na Internet, mas eu queria dar informações personalizadas para a pessoa em frente ao espelho, utilizando uma câmera e algoritmos de reconhecimento facial. Algo como o tempo para chegar ao trabalho e os próximos compromissos, e mudar as informações quando a outra pessoa – como minha esposa, estiver na frente dele.

Então, quais materiais eu utilizei:

  • Monitor AOC E1670swu USB
  • Up Board rodando o Windows 10 full
  • Câmera RealSense SR300
  • Caixa de notebook como gabinete
  • Placa de acrílico transparente de 1mm x 25cm x 35cm
  • Cabo VGA
  • Adaptador HDMI-VGA
  • Fita isolante, cola, parafusos pequenos
  • Estilete

Vamos criar um espelho inteligente

O software

Interagindo com a câmera RealSense SR300

Como eu queria utilizar o C#, eu teria que adaptar a biblioteca open source librealsense de C++ para .Net. Eu fiz isso e publiquei o novo projeto no GitHub como OpenRealSense e ela está disponível para os usuários do .Net via nugget. Essa biblioteca é necessária para capturar as transmissões da câmera RealSense.

O código básico para capturar as transmissões é:

  var context = Context.Create();
  
  var width = 640;
  var height = 480;
  
  device.EnableStream(StreamType.Color, width, height, FormatType.bgr8, 30);
  device.Start();
  
  while (true) {
    device.WaitForFrames();
    var frame = device.GetFrameData(StreamType.Color);
    ...
  }

Para a parte de reconhecimento facial, eu utilizei uma adaptação para .Net do framework OpenCV e chamei de Emgu.CV

A maneira de converter os quadros RealSense para OpenCV/Emgu.CV é mostrada abaixo.

var realSenseFrame = device.GetFrameData(StreamType.Color);

var openCvImage = new Image<Bgr, byte>(realSenseFrame.Width, realSenseFrame.Height) {
    Bytes = realSenseFrame.Bytes
};

Para detectar um rosto nos quadros, converta a imagem para escala de cinza e use a função DetectHaarCascade:

var gray = openCvImage.Convert<Gray, Byte>();
var facesDetected = gray.DetectHaarCascade(
                    _face,
                    1.2,
                    10,
                    HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
                    new Size(20, 20));
gray.Dispose();

Quando você tiver detectado o rosto, faça um crop da imagem e compare com os rostos do banco de dados. Se você ainda não tem um banco de dados, você pode utilizar o mesmo procedimento acima para encontrar os rostos que você quer e salvá-los, para que você possa utilizá-los para comparação no futuro. Como não estou preocupado com a segurança, vou utilizar o EigenObjectRecognizer para realizar o reconhecimento facial.

//crop the face and resize it
MCvAvgComp faceInfo = facesDetected[0].First();
var faceImage = frame.Copy(faceInfo.rect)
                     .Convert<Gray, byte>()
                     .Resize(100, 100,
                     INTER.CV_INTER_CUBIC);

//compare the face with our database
//_images is an array of Image<Gray, byte>
//_labels is an array of labels, same size and order of _images array
var termCrit = new MCvTermCriteria(_images.Count, 0.001);
var _recognizer = new EigenObjectRecognizer(
                       _images.ToArray(),
                       _labels.ToArray(),
                       3000,
                       ref termCrit);
var label = _recognizer.Recognize(faceImage);

Com nosso rótulo (usuário) em mãos, é somente uma questão de utilizar um HTTPClient para atualizar o usuário atual exibido em nosso espelho inteligente.

O código completo para a aplicação de detecção de rosto é open source e está disponível no GitHub.

A Interface do espelho inteligente

Eu encontrei um projeto popular open source chamado MagicMirror2, que tem módulos de extensão fáceis de serem escritos para termos novas funcionalidades. Minha ideia era instalar ele e escrever um novo módulo para fazer ele reconhecer múltiplos usuários e integrá-lo ao nosso aplicativo de reconhecimento facial.

A arquitetura resultante é algo assim:

  • As caixas vermelhas foram desenvolvidas por mim
  • As caixas azuis são bibliotecas open source existentes

Instalando o MagicMirror2

  1. Baixe e instale a versão mais recente do Node.js
  2. Clone o repositório e verifique a parte principal: git clone https://github.com/MichMich/MagicMirror.git
  3. Entre no repositório: cd MagicMirror
  4. Instale e execute o aplicativo: npn install && npn start

O MagicMirror2 já vem com muitos módulos. Veja sua documentação para habilitar e configurar.

Para criar um novo módulo para o Magic Mirror, você precisa somente adicionar uma sub-pasta para seu módulo dentro da pasta “Módulos” e escrever um arquivo JavaScript para iniciar o seu código.

Um módulo mínimo que não faria nada muito elegante seria:

//modules/helloworldModule/helloworld.js:

Module.register("helloworld",{
    // Default module config.
    defaults: {
        text: "Hello World!"
    },

    // Override dom generator.
    getDom: function() {
        var wrapper = document.createElement("div");
        wrapper.innerHTML = this.config.text;
        return wrapper;
    }
});

Nosso módulo RealSense

Vamos criar um módulo chamado MMM-RealSense. Vamos nos beneficiar de uma propriedade presente em todos os módulos chamada “classes”. Vamos utilizar palavras especiais para configurar essa propriedade conforme segue:

  • default: módulos configurados se nenhum usuário for detectado.
  • everyone: módulos que deverão ser exibidos para todos os usuários
  • [usuário]: módulos que deverão ser exibidos para um usuário específico

O usuário é, na verdade, qualquer rótulo utilizado em nosso aplicativo WPF acima quando reconhece você ou qualquer outra pessoa. Em meu caso, eu utilizei andrecarlucci para mim e robertacarlucci para minha esposa.

Existe também um arquivo especial chamado node_helper.js que você pode adicionar à sua pasta de módulo para adicionar funcionalidades extras. Em nosso caso, vamos criar uma abertura para nosso aplicativo WFP enviar solicitações para ele sempre que detectar novos usuários.

Node_helper.js
const NodeHelper = require("node_helper");
const url = require("url");

module.exports = NodeHelper.create({
    
    start: function() {
        this.expressApp.get('/login', (req, res) => {
        var query = url.parse(req.url, true).query;
            var user = query.user;

        if (user == null){
                res.send({"status": "failed", "error": "No user given."});
        }
            else {
                //notify our main file so it shows and hides the other modules accordingly 
                this.sendSocketNotification('login', user );
        res.send({"status": "success", "login": user});
        }
        });

        this.expressApp.get('/logout', function (req, res) {
        this.sendSocketNotification('logout', user);
            res.send({"status": "success", "logout": user});
        });
    }   
});

Agora temos um webservice que pode ser acessado via http://yourMagicMirrorServer:port/login?user=[username]. Nosso aplicativo WFP deverá realizar a chamada exatamente para esse endereço. Veja o código no GitHub para mais detalhes.

Instalando o Módulo MMM-Real-Sense

  1. Entre no repositório: cd MagicMirror/modules
  2. Clone o repositório e verifique a parte principal: git clone https://github.com/andrecarlucci/MMM-RealSense.git.
  3. Adicione o módulo à lista de módulos em seu arquivo MagicMirror/config/config.js
Config.js
...
{
    module: 'MMM-RealSense',
        config: {
        welcomeMessage: true,
            users: [            
                {
                    name: "some ser", 
                    message: "Hello User1, you look AWESOME!"
                },
                {
                    name: "your other user",
                    message: "Hi Foo, you're the most beautiful woman I have ever seen!"
                }
            ],
        }
}

Sob “users”, coloque a array dos rótulos e mensagens de boas-vindas para que nosso Smart Mirror possa cumprimentar os usuários quando eles interagirem com o espelho.

E é isso! Inicie o MagicMirror2, inicie o WpfApp e está pronto!

Montando o espelho inteligente

A ideia é conectar o monitor à câmera e à Up Board.

A Up Board tem um hardware incrível com o tamanho de um Raspberry Pi, mas pode executar o Windows 10 full sem problemas. Veja como é incrível.

Eu comprei um adaptador wifi, conectei à Up Board e configurei para utilizar minha rede. Então, eu instalei o MagicMirror2, nosso aplicativo de reconhecimento facial, e um servidor VNC para que eu possa atualizar a placa sem abrir o gabinete (você pode utilizar um adaptador bluetooth e um mouse e teclado sem fio se quiser). Se você estiver procurando por um bom aplicativo cliente/servidor VNC, uma sugestão é o http://www.tightvnc.com/

A primeira coisa a ser feita é encontrar um monitor para ser utilizado. Eu utilizei o AOC e1670swu porque ele é realmente leve e consome apenas 7 Watts. O ponto negativo é que a emissão de luz não é a mais forte, então os widgets apareceram no espelho um pouco mais fracos do que eu gostaria. De qualquer maneira, eu acho que está bom, pelo preço que paguei. Outro ponto é que ele tem somente a saída VGA e nossa placa utiliza HDMI, então, eu precisei comprar um adaptador.

Desmonte o monitor, tirando a moldura frontal. Você pode utilizar uma chave de fenda de ponta lisa para ajudar no processo, mas não se esqueça: se a moldura não estiver saindo facilmente, você está fazendo errado. Não force demais, tenha cuidado.

A Câmera RealSense

A câmera RealSense SR300 é a mais recente e mais avançada câmera frontal da Intel. Ela utiliza várias tecnologias de percepção para alcançar uma percepção profunda, imagens 3D, mapeamento interno e rastreamento de atributos. Utilizando o librealsense, agora adaptada ao C#, podemos capturar os fluxos das imagens (profundidade, cores, infravermelho e fisheye) e mexer com eles utilizando o OpenCV. A câmera estará no topo do gabinete e será conectada à placa utilizando um cabo USB 3.0.

O Gabinete

O próximo passo é encontrar um gabinete para seu espelho. Você pode utilizar um armário de banheiro, uma caixa de madeira ou qualquer outra coisa que pareça servir para você. Por sorte, eu encontrei uma caixa de notebook que poderia se encaixar perfeitamente ao espelho.

Eu fiz um furo na parte de trás da caixa e fixei a placa de acrílico utilizando a fita isolante.

Com um estilete, eu abri um furo para os cabos de alimentação e para a câmera RealSense.

Então, eu fixei a Up Board, o adaptador wifi e os cabos no interior da caixa.

Depois, as placas do monitor e o monitor desmontado. Utilizei a fita isolante novamente.

Feche a caixa, fixe a câmera no topo e pendure na parede. É isso! Você é o orgulhoso proprietário de um Smart Mirror!

Próximos passos?

Não consigo parar de pensar sobre adicionar funcionalidades ao Smart Mirror. A próxima que estou pensando é utilizar a profundidade da câmera RealSense para detectar o dedo do usuário em frente ao espelho e utilizá-lo como ponteiro. Assim, será possível habilitar, desabilitar e personalizar as ações no espelho sem precisar utilizar mouse e teclado.

Uma maneira simples para fazer isso seria:

  • Excluir todos os pontos a mais de um metro;
  • Capturar o ponto mais próximo ao espelho que tenha uma distância maior do que 40cm (vou encontrar o melhor valor para isso) do mais distante;
  • Utilizar esse ponto como ponteiro;

Acho que a única maneira de conseguir alcançar essa configuração é se o usuário levantar seu braço a sua frente. Não é perfeito, mas seria simples e rápido.

Bem, eu aviso vocês se funcionar. Até lá, divirta-se com o espelho!

***

Artigo traduzido com autorização. Publicado originalmente em http://www.andrecarlucci.com/en/creating-a-smart-mirror-with-an-upboard-magicmirror2-and-a-realsense-camera/