Você com certeza já deve ter ouvido falar de machine learning, ou inteligência artificial, certo?
Esses são os temas da moda em tecnologia.
Assisti um vídeo muito bom do Filipe Deschamps, no qual ele ficava testando e experimentando uma ferramenta de machine learning do Google chamada Cloud Vision API.
Basicamente, ele inseria uma foto de qualquer coisa, e o Vision API dizia pra ele o que tinha na foto, se fosse uma pessoa ele conseguia identificar as emoções, se fosse um texto ele conseguia escanear o texto por OCR, se fosse um cachorro ele conseguia identificar a raça, enfim, ele usava todo esse conhecimento quase ilimitado da API do Google pra identificar padrões em qualquer imagem.
E se você está atento aqui no meu canal, já percebeu que consegue desenvolver softwares e aplicativos desde básicos à avançados sem usar nenhuma linguagem de programação, certo?
E aí eu pensei: será que a gente não consegue pegar emprestada toda essa inteligência do Google pra criar o NOSSO aplicativo de machine learning, sem código sem programação?
E sim, conseguimos!
Veja como ficou o sistema no vídeo, e como fizemos para construí-lo, e não deixe de ler o tutorial passo a passo abaixo:
Índice
1. Criar a Chave de API do Google Cloud Vision
Para conseguirmos usar a Google Cloud Vision API, precisamos de uma API KEY, é uma chave de autenticação. Para conesguir a sua (gratuita) é só seguir este passo:
Acesse o Google Cloud Platform (https://console.cloud.google.com) e crie um projeto (ou acesse um projeto que você já tenha), e então siga os passos abaixo:
Pronto, agora você tem a Chave da API. Com isso, você já consegue fazer a chamada pro Google Vision API e ela será autorizada.
Agora, vamos acessar o Bubble, criar nossa conta gratuita (caso ainda não tenha), criar um novo Aplicativo, e configurar o Conector de API, que é o que vai nos permitir integrar nosso aplicativo ao Vision API.
2. Criar o Conector de API no Bubble
Nome da Chamada de API: Vision API
Use as: Action
Data type: JSON
POST: https://vision.googleapis.com/v1/images:annotate?key=[key]
URL Parameters: key / adicione aqui a Chave de API do Google Vision API que você obteve no 1° passo
Body (JSON object): Aqui, copie e cole esse texto que está logo abaixo. É uma série de instruções em formato JSON que informa ao Google quais são, exatamente, os dados da API que queremos receber de volta:
{
“requests”:[
{
“image”:{
“source”:{
“imageUri”:
“<URLimagem>“
}
},
“features”:[
{
“type”:”LOGO_DETECTION”,
“maxResults”:3
},
{
“type”:”LABEL_DETECTION”,
“maxResults”:10
},
{
“type”:”LANDMARK_DETECTION”,
“maxResults”:10
},
{
“type”:”TEXT_DETECTION”,
“maxResults”:10
},
{
“type”:”IMAGE_PROPERTIES”,
“maxResults”:10
},
{
“type”:”WEB_DETECTION”,
“maxResults”:10
},
{
“type”:”FACE_DETECTION”,
},
{
“type”:”OBJECT_LOCALIZATION”,
“maxResults”:10
},
{
“type”:”SAFE_SEARCH_DETECTION”,
}
]
}
]
}
Para entender:
- “LOGO_DETECTION” significa que queremos que o Vision API detecte quais logotipos estão presentes na imagem.
- “LABEL_DETECTION” significa que queremos saber quais ‘rótulos’ o Google identifica.
- “LANDMARK_DETECTION” verifica a presença de Locais Históricos ou Pontos de Referência, como a Torre Eiffel.
- “TEXT_DETECTION” solicita quais textos estão presentes na imagem, e o Google escaneia e retorna com caracteres.
- “IMAGE_PROPERTIES” são propriedades das imagens que usamos para obter as cores.
- “WEB_DETECTION” são os termos de pesquisa na internet que mais se assemelham.
- “FACE_DETECTION” busca expressões faciais e de emoção.
- “OBJECT_LOCALIZATION” procura por objetos, como mesas, copos, frutas.
- “SAFE_SEARCH_DETECTION” avalia se a imagem contém conteúdo adulto, de violência, conteúdo racista, médico ou se parece um Meme (que o Google chama de Spoof).
Body Parameters (Key): URLimagem / Aqui, desmarque a caixinha “Private”, pois é o URL da imagem que você vai enviar para o Google para que ele analise. Neste primeiro momento, coloque o URL de uma imagem que preparei especialmente para obter todos os dados possíveis, com uma foto minha, da torre eiffel, e do logo da Apple. Segue abaixo o URL da imagem para você inserir aqui:
https://www.semcodar.com.br/wp-content/uploads/2019/09/TreinarVisionAPI.jpg
Pront, tudo configurado! Agora, clique em Initialize Call.
Com a API configurada, agora vamos montar o layout do nosso aplicativo para exibirmos essa enxurrada de informações que o Google nos enviou.
3. Layout do Aplicativo
Monte o aplicativo com o layout, cores e estilos que você desejar.
O importante é que o aplicativo contenha esses elementos abaixo:
Os elementos que você precisa ter, para receber todos os dados, são:
- INPUT URL tipo texto, onde o usuário irá inserir o URL da imagem que quer analisar
- CONDICIONAL: When PictureUploader’s value is not empty, mudar Initial Content para https:PictureUploader’s value:
- O objetivo dessa formatação condicional é para que, se o usuário optar por carregar uma foto (via câmera de celular ou via computador), o INPUT irá automaticamente perceber que há uma foto carregada, e já vai mudar o próprio texto para informar o endereço URL onde está o arquivo.
- O motivo pelo qual colocamos o “https:” antes do valor do PictureUploader, é porquê ele informa o endereço da imagem somente a partir do “//”, e assim deixamos a informação completa.
- PICTURE UPLOADER, onde o usuário poderá clicar para inserir uma foto do computador dele ou, se estiver no celular, pode bater uma foto na hora e mandar pro Google Vision.
- IMAGE, que irá mostrar a imagem do endereço URL que consta no INPUT.
- DYNAMIC IMAGE: Input URL’s value
- BOTÃO Analisar
- Este é o único botão que irá executar uma ação no nosso aplicativo. As ações estão um pouco mais abaixo neste tutorial.
- Opcional: caso você queira fazer aquela jogadinha que ensino no vídeo pro botão mudar para “Analisando…” enquanto ele pensa após o usuário clicar, você precisa criar um Custom State tipo yes/no neste botão.
- GRUPO CARDS com todos os Cards onde iremos mostrar os dados
- 5a. REPEATING GROUP Rótulos
- Type of content: Vision API labelAnnotation
- Data source: Parent group’s Vision API response’s labelAnnotations
- Dentro do Repeating Group, insira dois textos:
- Current cell’s Vision API labelAnnotation’s description (para mostrar a descrição do rótulo que a Cloud Vision API encontrou)
- Current cell’s Vision API labelAnnotation’s score:formatted as 102.858,00% (para mostrar a porcentagem de certeza que a Cloud Vision API tem sobre este rótulo) – esse “formatted as” é apenas para que ele mostre o número em porcentagem (ex: 80% ao invés de 0,8).
- 5b. REPEATING GROUP Cores
- Type of content: Vision API imagePropertiesAnnotation dominantColors color
- Data source: Parent group’s Vision API response’s imagePropertiesAnnotation dominantColors colors
- Dentro do Repeating Group, insira dois Textos e um Shape:
- TEXTO 1: The Color API – Get HEX from RGB’s name value
- Observação: este “The Color API” é um plugin que criei especificamente para este tutorial, pois o Google Vision API envia os dados de cores em RGB (o Branco, por exemplo, é 255,255,255, na escala de cores RGB, enquanto na escala de cores Hexadecimal é #FFFFFF), mas o Bubble tem mais facilidade em ler a cor Hexadecimal. Se quiser saber mais veja esta breve explicação da Gráfica Printi sobre cores na internet.
- Portanto, basta você instalar no Bubble o plugin The Color API para fazer essa conversão de forma fácil:
- Feita a instalação instantânea do plugin Color API, você já conseguirá criar este texto. Configure assim:
- O que estamos fazendo é o seguinte: para converter a cor de RGB para Hexadecimal, a Color API nos pede 3 valores: o R (Red – vermelho de 0 a 255), o G (Green – verde de 0 a 255) e o B (Blue – azul de 0 a 255). A configuração acima é para enviarmos exatamente estes dados para o Color API, e ele vai nos devolver o nome da cor.
- TEXTO 2: Current cell’s Vision API imagePropertiesAnnotation dominantColors color’s score:formatted as 102.858,00% (para mostrar a porcentagem de predominância da cor na imagem).
- SHAPE: Esse Shape (forma) é apenas para exibir a cor. A única configuração aqui é, em Color, coloque The Color API – Get HEX from RGB’s hex value. Ou seja, ao informarmos a cor em Hexadecimal, esse shape já vai ficar nessa cor.
- TEXTO 1: The Color API – Get HEX from RGB’s name value
- 5c. REPEATING GROUP Pesquisa na Web
- Type of content: Vision API webDetection webEntitie
- Data source: Parent group’s Vision API response’s webDetection webEntities
- Dentro do Repeating Group, insira dois Textos:
- TEXTO 1: Current cell’s Vision API webDetection webEntitie’s description
- TEXTO 2: Current cell’s Vision API webDetection webEntitie’s score:formatted as 102.858,00%
- 5d. REPEATING GROUP Objetos Encontrados
- Type of content: Vision API localizedObjectAnnotation
- Data source: Parent group’s Vision API response’s localizedObjectAnnotations
- Dentro do Repeating Group, insira dois Textos:
- TEXTO 1: Current cell’s Vision API localizedObjectAnnotation’s name
- TEXTO 2: Current cell’s Vision API localizedObjectAnnotation’s score:formatted as 102.858,00%
- 5e. REPEATING GROUP Imagens Similares
- Type of content: Vision API webDetection visuallySimilarImage
- Data source: Parent group’s Vision API response’s webDetection visuallySimilarImages
- Dentro do Repeating Group, insira uma Imagem:
- IMAGEM – Dynamic image: Current cell’s Vision API webDetection visuallySimilarImage‘s URL
- 5f. REPEATING GROUP Palavra na Web
- Type of content: Vision API webDetection bestGuessLabel
- Data source: Parent group’s Vision API webDetection bestGuessLabel
- Dentro do Repeating Group, insira um Texto:
- TEXTO: Current cell’s Vision API webDetection bestGuessLabel‘s label
- 5g. GRUPO Face
- Type of content: Vision API response
- Data source: Parent group’s Vision API response
- Dentro deste grupo, insira 5 novos grupos, um para cada leitura facial:
- GRUPO Alegria
- Type of content: texto
- Data source: Parent group’s Vision API response’s faceAnnotations:first item’s joyLikelihood
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Alegria
- TEXTO 2: Parent group’s text
- GRUPO Tristeza
- Type of content: texto
- Data source: Parent group’s Vision API response’s faceAnnotations:first item’s sorrowLikelihood
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Tristeza
- TEXTO 2: Parent group’s text
- GRUPO Raiva
- Type of content: texto
- Data source: Parent group’s Vision API response’s faceAnnotations:first item’s angerLikelihood
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Raiva
- TEXTO 2: Parent group’s text
- GRUPO Surpresa
- Type of content: texto
- Data source: Parent group’s Vision API response’s faceAnnotations:first item’s surpriseLikelihood
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Surpresa
- TEXTO 2: Parent group’s text
- GRUPO Boné/Chapéu
- Type of content: texto
- Data source: Parent group’s Vision API response’s faceAnnotations:first item’s headwearLikelihood
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Boné / Chapéu
- TEXTO 2: Parent group’s text
- GRUPO Alegria
- 5h. GRUPO Safe Search
- Type of content: Vision API response
- Data source: Parent group’s Vision API response
- Dentro deste grupo, insira 5 novos grupos, um para cada aspecto da busca Safe Search:
- GRUPO Adulto
- Type of content: texto
- Data source: Parent group’s Vision API response’s safeSearchAnnotation adult
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Adulto
- TEXTO 2: Parent group’s text
- GRUPO Spoof / Meme
- Type of content: texto
- Data source: Parent group’s Vision API response’s safeSearchAnnotation spoof
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Spoof / Meme
- TEXTO 2: Parent group’s text
- GRUPO Médico
- Type of content: texto
- Data source: Parent group’s Vision API response’s safeSearchAnnotation medical
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Médico
- TEXTO 2: Parent group’s text
- GRUPO Violência
- Type of content: texto
- Data source: Parent group’s Vision API response’s safeSearchAnnotation violence
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Violência
- TEXTO 2: Parent group’s text
- GRUPO Racista
- Type of content: texto
- Data source: Parent group’s Vision API response’s safeSearchAnnotation racy
- Inserir 2 textos dentro deste grupo:
- TEXTO 1: Racista
- TEXTO 2: Parent group’s text
- GRUPO Adulto
- 5i. GRUPO Textos
- Type of content: Vision API textAnnotation
- Data source: Parent group’s Vision API response’s textAnnotations:first item
- Dentro do grupo colocar um texto:
- TEXTO: Parent group’s Vision API textAnnotation’s description (texto encontrado e escaneado na imagem)
- 5j. REPEATING GROUP Logotipos
- Type of content: Vision API logoAnnotation
- Data source: Parent group’s Vision API response’s logoAnnotation
- Dentro do Grupo Repetidor colocar 2 textos:
- TEXTO 1: Current cell’s Vision API logoAnnotation’s description (essa é a descrição do logotipo encontrado)
- TEXTO 2: Current cell’s Vision API logoAnnotation’s score:formatted as 102.858,00% (probabilidade de certeza informada pelo Google)
- 5k. REPEATING GROUP Locais
- Type of content: Vision API landmarkAnnotation
- Data source: Parent group’s Vision API response’s landmarkAnnotation
- Dentro deste grupo repetidor colocar 2 textos e 1 Repeating Group:
- TEXTO 1: Current cell’s Vision API landmarkAnnotation’s description
- TEXTO 2: Current cell’s Vision API landmarkAnnotation’s score:formatted as 102.858,00%
- REPEATING GROUP Mapas:
- Type of content: Vision API location
- Data source: Current cell’s Vision API landmarkAnnotation’s locations
- Dentro do Repeating Group, inserir somente um MAPA:
- MAPA:
- Number of markers: Single
- Marker address: Calculate Formula -> Coordinates to Address:
- Latitude: Current cell’s Vision API location’s latLng latitude
- Longitude: Current cell’s Vision API location’s latLng longitude
- MAPA:
- 5a. REPEATING GROUP Rótulos
Todo o layout está montado!
Se você estiver com dúvidas em algum ponto, sugiro acessar o Editor do Bubble.io onde montei o aplicativo e você pode visualizar livremente cada item acima.
Agora vamos para a última parte, vamos definir as ações do Botão Analisar:
4. Ações
Veja que o único elemento do nosso aplicativo que executa alguma ação é o Botão Analisar.
Ao clicar no botão, serão executadas 5 ações, vide abaixo:
Ação 1 – Set state loading of btn Analisar (Opcional): Essa é uma ação opcional e somente estética. Ao colocarmos o botão Analisar, comentei ali em cima que poderíamos colocar um “Estado Personalizado” ou “Custom State” chamado ‘loading’, para informarmos quando o botão está carregando, para que ele mude o texto (de “Analisar” para “Analisando”) e que ele não seja mais clicável, para evitar que o usuário envie o mesmo dado duas vezes. Se quiser utilizar, basta alterar o Custom State LOADING do Botão Analisar para YES. E lá no botão, lembre-se de configurar uma Formatação Condicional que irá alterar o texto e o não-clicável quando o Loading for YES.
Ação 2 – Google NoAuth – Vision API: Essa é a ação principal, é a chamada de API na qual enviamos a foto do campo INPUT URL para o Google, e o Google nos devolve os dados. Basta selecionar esta chamada e no parâmetro URLimagem colocar Input URL’s value:
Ação 3 – Display data in Group Cards: Aqui coletamos todos os dados que recebemos na ação 2, e inserimos esse dado no Grupo Cards (aquele que tem todas caixinhas dentro, lembra?). Basta selecionar Group > Display Data > Element Group Cards e, no Data to display colocar Result of step2 (Google NoAuth – V…)’s responses:first item.
Ação 4 – Set state loading of btn Analisar (Opcional): Lembra que na ação 1 colocamos o state LOADING do Botão Analisar como YES? Agora é só colocar como NO, para informar que ele já enviou e já recebeu os dados, portanto o botão pode voltar ao normal.
Ação 5 – Scroll to Group Cards (Opcional): Essa também é uma ação opcional e estética. É só para que, ao terminar todas essas ações, a tela do usuário corra direto para o Grupo Cards. É uma ação bacana pois fica mais claro pro usuário que a ação foi executada e não está mais processando.
E com tudo isso montado, agora já podemos partir pra melhor parte, o teste final.
5. Testar
Agora insira o URL de uma imagem que você quer testar no Input (sugiro fazer com aquela mesma de teste que postei lá em cima), e clicar em Analisar, e todos os dados deverão aparecer.
Se você acessar meu editor do Bubble, vai perceber que tem algumas configurações estéticas que não coloquei aqui, somente para simplificar a explicação.
Espero que tenha gostado de criar seu primeiro aplicativo de Machine Learning!
Não se esqueça de se inscrever no meu Canal do Youtube para acompanhar este e outros vídeos de programação visual e desenvolvimento de aplicativos sem código.
LINKS ÚTEIS:
Aplicativo de Machine Learning Sem Código (veja como ficou pronto)