;(function() { window.createMeasureObserver = (measureName) => { var markPrefix = `_uol-measure-${measureName}-${new Date().getTime()}`; performance.mark(`${markPrefix}-start`); return { end: function() { performance.mark(`${markPrefix}-end`); performance.measure(`uol-measure-${measureName}`, `${markPrefix}-start`, `${markPrefix}-end`); performance.clearMarks(`${markPrefix}-start`); performance.clearMarks(`${markPrefix}-end`); } } }; /** * Gerenciador de eventos */ window.gevent = { stack: [], RUN_ONCE: true, on: function(name, callback, once) { this.stack.push([name, callback, !!once]); }, emit: function(name, args) { for (var i = this.stack.length, item; i--;) { item = this.stack[i]; if (item[0] === name) { item[1](args); if (item[2]) { this.stack.splice(i, 1); } } } } }; var runningSearch = false; var hadAnEvent = true; var elementsToWatch = window.elementsToWatch = new Map(); var innerHeight = window.innerHeight; // timestamp da última rodada do requestAnimationFrame // É usado para limitar a procura por elementos visíveis. var lastAnimationTS = 0; // verifica se elemento está no viewport do usuário var isElementInViewport = function(el) { var rect = el.getBoundingClientRect(); var clientHeight = window.innerHeight || document.documentElement.clientHeight; // renderizando antes, evitando troca de conteúdo visível no chartbeat-related-content if(el.className.includes('related-content-front')) return true; // garante que usa ao mínimo 280px de margem para fazer o lazyload var margin = clientHeight + Math.max(280, clientHeight * 0.2); // se a base do componente está acima da altura da tela do usuário, está oculto if(rect.bottom < 0 && rect.bottom > margin * -1) { return false; } // se o topo do elemento está abaixo da altura da tela do usuário, está oculto if(rect.top > margin) { return false; } // se a posição do topo é negativa, verifica se a altura dele ainda // compensa o que já foi scrollado if(rect.top < 0 && rect.height + rect.top < 0) { return false; } return true; }; var asynxNextFreeTime = () => { return new Promise((resolve) => { if(window.requestIdleCallback) { window.requestIdleCallback(resolve, { timeout: 5000, }); } else { window.requestAnimationFrame(resolve); } }); }; var asyncValidateIfElIsInViewPort = function(promise, el) { return promise.then(() => { if(el) { if(isElementInViewport(el) == true) { const cb = elementsToWatch.get(el); // remove da lista para não ser disparado novamente elementsToWatch.delete(el); cb(); } } }).then(asynxNextFreeTime); }; // inicia o fluxo de procura de elementos procurados var look = function() { if(window.requestIdleCallback) { window.requestIdleCallback(findByVisibleElements, { timeout: 5000, }); } else { window.requestAnimationFrame(findByVisibleElements); } }; var findByVisibleElements = function(ts) { var elapsedSinceLast = ts - lastAnimationTS; // se não teve nenhum evento que possa alterar a página if(hadAnEvent == false) { return look(); } if(elementsToWatch.size == 0) { return look(); } if(runningSearch == true) { return look(); } // procura por elementos visíveis apenas 5x/seg if(elapsedSinceLast < 1000/5) { return look(); } // atualiza o último ts lastAnimationTS = ts; // reseta status de scroll para não entrar novamente aqui hadAnEvent = false; // indica que está rodando a procura por elementos no viewport runningSearch = true; const done = Array.from(elementsToWatch.keys()).reduce(asyncValidateIfElIsInViewPort, Promise.resolve()); // obtém todos os elementos que podem ter view contabilizados //elementsToWatch.forEach(function(cb, el) { // if(isElementInViewport(el) == true) { // // remove da lista para não ser disparado novamente // elementsToWatch.delete(el); // cb(el); // } //}); done.then(function() { runningSearch = false; }); // reinicia o fluxo de procura look(); }; /** * Quando o elemento `el` entrar no viewport (-20%), cb será disparado. */ window.lazyload = function(el, cb) { if(el.nodeType != Node.ELEMENT_NODE) { throw new Error("element parameter should be a Element Node"); } if(typeof cb !== 'function') { throw new Error("callback parameter should be a Function"); } elementsToWatch.set(el, cb); } var setEvent = function() { hadAnEvent = true; }; window.addEventListener('scroll', setEvent, { capture: true, ive: true }); window.addEventListener('click', setEvent, { ive: true }); window.addEventListener('resize', setEvent, { ive: true }); window.addEventListener('load', setEvent, { once: true, ive: true }); window.addEventListener('DOMContentLoaded', setEvent, { once: true, ive: true }); window.gevent.on('allJSLoadedAndCreated', setEvent, window.gevent.RUN_ONCE); // inicia a validação look(); })();
  • AssineUOL
Topo

André Noel

OPINIÃO

Texto em que o autor apresenta e defende suas ideias e opiniões, a partir da interpretação de fatos e dados.

Como um programador pode ajudar a combater falhas do reconhecimento facial

Freepik
Imagem: Freepik

13/03/2021 04h00

Você já assistiu ao filme "Minority Report"? Se não assistiu, procure assistir um dia, é um dos filmes mais legais com o Tom Cruise.

"Minority Report" é um filme futurista, onde os crimes graves, como assassinato, são resolvidos antes de acontecerem. Tirando a parte das pessoas envolvidas na cognição dos crimes, todo o resto da tecnologia utilizada por eles durante todo o filme parece viável um dia e encanta os olhos.

Algumas das tecnologias do filme já estão se tornando realidade para nós, como as telas controladas por gestos, telas translúcidas, drones que levam pessoas (não são ainda carros voadores, mas é quase).

Também chama a atenção no filme o reconhecimento biométrico, que permite identificar a pessoa através de características do corpo. No filme, eles utilizam mais o reconhecimento pela íris, identificando as pessoas pelos olhos, mesmo à distância (ótimas câmeras).

Mas o reconhecimento biométrico envolve a boa e velha impressão digital, reconhecimento facial, até mesmo já li que a língua fornece uma impressão ainda mais detalhada do que a impressão digital, mas seria muito estranho usá-la nos sensores, principalmente em tempos de pandemia.

Dessas tecnologias de reconhecimento biométrico, o reconhecimento facial está em alta, principalmente pela facilidade de implementação que temos hoje em dia e pela ótima biblioteca chamada "OpenCV", que é uma biblioteca de código aberto, e que com poucas linhas de código você consegue colocar em seu sistema para aplicações simples.

Você mesmo já deve estar acostumado com o reconhecimento facial. Já aconteceu com você, alguma vez, de publicar uma foto no Facebook, com algumas pessoas, e a própria rede social marcou o rosto das pessoas, identificando até mesmo quem elas eram, colocando links aos perfis corretos?

As fotos que são enviadas para a rede social são verificadas. A plataforma procura as pessoas, se não encontra, ela marca um quadrado no rosto para que você identifique quem é. O reconhecimento de faces é parecido também com o que a sua câmera fotográfica faz.

Um outro assunto que ou bastante pela mídia da internet há um tempo foi a falha no reconhecimento facial do Twitter, onde ele destaca o rosto de pessoas de pele clara, mas não faz o mesmo com o rosto de pessoas de pele escura. É, na verdade, uma tentativa de melhorar a pré-visualização de uma foto dando destaque para o rosto, ao invés de uma área sem informação importante da foto, mas a precisão do reconhecimento facial é menor para pessoas de pele escura.

Isso pode ser um problema bem mais grave do que apenas cortar as fotos de jeito errado. O reconhecimento facial tem muitas aplicações práticas, dentre elas podemos destacar o reconhecimento de pessoas para evitar fraudes em cadastros de comércio, detecção de assaltos, reconhecimento de pessoas procuradas pela polícia, entre outros. E quando o reconhecimento facial envolve a parte de crimes, é preciso de um cuidado muito maior.

Ano ado eu gravei uma conversa com meu amigo Alessandro Faria (o Cabelo), que é uma das pessoas que mais se destaca nessa área de reconhecimento biométrico e visão computacional (você pode ouvir o áudio ali embaixo, no final do texto). Segundo ele, não é um bigode falso, um chapéu ou óculos que vão enganar o reconhecimento facial. Existem pontos na face que dão uma precisão muito boa na identificação.

Mas ele comentou também sobre a questão do reconhecimento de pessoas com pele mais escura (que inclusive ele se identifica), que envolve tanto a quantidade de dados de treinamento dos algoritmos, quanto a própria tonalidade e iluminação que atrapalham algoritmos mais simples, mas existem formas de corrigir.

Trazendo o problema do reconhecimento descuidado mais para perto, é fácil encontrar notícias sobre isso aqui no Brasil mesmo. Segundo as notícias, 90,5% dos presos por monitoramento facial no Brasil são negros, o que gera muitos enganos, principalmente quando a taxa de erros no reconhecimento é mais flexível.

Até mesmo quando não envolve reconhecimento por computador, temos que 83% dos presos injustamente por reconhecimento fotográfico no Brasil são negros.

A dificuldade que existe em diferenciar pessoas através de fotos acaba sendo também reada para o reconhecimento facial automatizado, por isso é importante trabalhar com mais pontos de reconhecimento biométrico combinados.

Resumindo, o reconhecimento facial já é algo muito presente entre nós e tem muitas boas aplicações, mas como toda tecnologia em adoção é preciso que seja bem calibrada e que tenha um fator humano ali de controle para garantir que está sendo bem aplicada.

E nem entramos no assunto de privacidade, como acontecia no "Minority Report", onde as pessoas eram identificadas automaticamente em qualquer estabelecimento que estivessem, mas isso pode ser assunto para um outro momento.

Uma boa semana a todos, cuidem-se e ouçam a boa conversa que tive com o Alessandro Faria.