;(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

Robô faz maratona de vídeos de médicos e aprende a dar ponto cirúrgico

Precisão do robô para fazer suturas é de 85,5% - Reprodução
Precisão do robô para fazer suturas é de 85,5% Imagem: Reprodução

Thiago Varella

Colaboração para Tilt

21/06/2020 04h00

Em uma cirurgia, você confiaria a um robô a tarefa de fechar os pontos de um corte no seu corpo? Se depender da equipe do médico Ajay Tanwani, da Universidade da Califórnia em Berkeley, nos Estados Unidos, não estamos tão distante assim do momento em que uma máquina fará uma sutura.

Tanwani e seu time desenvolveram um sistema chamado Motion2Vec, criado para aprender a suturar assistindo a cirurgias realizadas por médicos reais. Trata-se de um sistema de aprendizado semissupervisionado de inteligência artificial capaz de imitar movimentos de inserção, extração e transferência de agulhas de um humano na hora de fechar um ponto cirúrgico.

A precisão do robô para fazer suturas, hoje, é de 85,5%, com uma média de 0,94 cm de erro. Sim, para ajudar uma equipe médica em uma cirurgia ainda é pouco. Mas, é bom lembrar, que o sistema precisou de apenas 78 vídeos de médicos realizando o procedimento para aprender a técnica.

"O YouTube recebe 500 horas de material novo a cada minuto. É um repositório incrível. Qualquer humano pode assistir a quase qualquer um desses vídeos e entendê-lo, mas um robô atualmente não pode —eles apenas o veem como um fluxo de pixels", afirmou, ao site Engadget, Ken Goldberg, diretor do laboratório da UC Berkeley e membro da equipe de Tanwani.

"Por isso, o objetivo deste trabalho é tentar entender esses pixels. Isso é, olhar para o vídeo, analisá-lo e poder segmentá-lo em sequências que significam algo", completou.

O robô da UC Berkeley utilizou uma rede neural siamesa para aprender a suturar. A ideia desse algoritmo é classificar o grau de semelhanças entre duas entradas de informação.

No caso do Motion2Vec, a equipe usa a rede para comparar o vídeo de um médico humano fazendo uma sutura ao vídeo de um braço mecânico tentando repetir os mesmos movimentos. No fim, a rede neural deve aprender com os erros e a a imitar melhor o humano.

É a mesma lógica de serviços de reconhecimento de imagem por inteligência artificial que comparam as imagens de câmeras de vigilância com a foto da carteira de motorista de determinada pessoa.

Tanwani sabe que ainda vai demorar alguns anos até que um robô consiga participar da cirurgia de um humano de forma quase autônoma. Segundo ele, a ideia é que esse tipo de equipamento ajude um cirurgião em tarefas menos complicadas.

"Acreditamos que isso ajudaria os cirurgiões a concentrar produtivamente seu tempo na execução de tarefas mais complicadas e usar a tecnologia para ajudá-los a cuidar da rotina corriqueira, disse Tanwani.