Classificação de imagens em ESP32-CAM usando aprendizado de máquina

Tempo de leitura: 6 minutes

Este tutorial aborda como implementar um sistema de classificação de imagens ESP32-CAM usando o aprendizado de máquina. O ESP32-CAM tem a capacidade de adquirir vídeo e imagens, usaremos essa capacidade para classificar imagens usando aprendizado de máquina. Combinando a capacidade de visão ESP32-CAM com aprendizado de máquina em nuvem, neste tutorial, levaremos o poder da visão computacional para um pequeno dispositivo.

A classificação de imagens de aprendizado de máquina é a tarefa de extrair informações de uma imagem usando um modelo treinado.

Para classificar uma imagem, o ESP32-CAM se conectará a uma plataforma de aprendizado de máquina em nuvem chamada Clarifai.com (você pode criar uma conta gratuitamente)..

Como funciona a classificação de imagens ESP32-CAM

Estes são os ajustes para:

  • Adquira imagens usando ESP32-CAM
  • Codifique a imagem em base64
  • Invocar uma API exposta pela plataforma de aprendizado de máquina em nuvem, enviando a imagem adquirida pelo ESP32
  • Analise a resposta e extraia as informações

A vantagem desse método é que não é necessário treinar um modelo para classificar as imagens por nós mesmos, mas o ESP32-CAM usa um modelo pré-treinado construído pelo Clarifai. Este modelo de aprendizado de máquina é capaz de identificar e classificar mais de 10.000 conceitos. A partir das imagens capturadas pelo ESP32-CAM, aplicando o reconhecimento de imagem, é possível extrair informações como:

  • se há uma pessoa ou não
  • interno ou externo
  • objetos
  • humores

e muito mais. O reconhecimento de imagem é um ramo importante da visão computacional.

Se esta é a primeira vez que você usa ESP32-CAM, você deve ler como fazer streaming de vídeo usando ESP32-CAM. Neste artigo, o ESP32-CAM usa um sistema de aprendizado de máquina externo para classificar as imagens. Se você deseja executar diretamente o mecanismo de aprendizado de máquina no seu dispositivo, é necessário ler como usar o Tensorflow Lite com ESP32.

Vamos começar!

Inicializando o ESP32-CAM

A primeira etapa é inicializar o ESP32-CAM. Este tutorial usa PlatformIO como IDE, mas você pode usar outros IDEs se desejar.

Crie um novo nome de arquivo ESP32-Vision.ino e adicione as seguintes linhas:

#include "Arduino.h"
#include "esp_camera.h"
#include <WiFi.h>

// Select camera model
//#define CAMERA_MODEL_WROVER_KIT // Tem PSRAM
//#define CAMERA_MODEL_ESP_EYE // Tem PSRAM
//#define CAMERA_MODEL_M5STACK_PSRAM // Tem PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE	// Tem PSRAM
#define CAMERA_MODEL_AI_THINKER // Tem PSRAM
//#define CAMERA_MODEL_TTGO_T_JOURNAL // Sem PSRAM

#include "camera_pins.h"

const char* ssid = "your_ssid";
const char* password = "wifi_password";

void setup() {
  Serial.begin(9600);
  Serial.setDebugOutput(true);
  Serial.println();

  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  
 // se PSRAM IC estiver presente, init com resolução UXGA e qualidade JPEG superior
 // para buffer de quadro pré-alocado maior.
 if(psramFound()){
    config.frame_size = FRAMESIZE_QVGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_QVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

#if defined(CAMERA_MODEL_ESP_EYE)
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
#endif

  // camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("A inicialização da câmera falhou com erro 0x%x", err);
    return;
  }


#if defined(CAMERA_MODEL_M5STACK_WIDE)
  s->set_vflip(s, 1);
  s->set_hmirror(s, 1);
#endif

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi conectado");
  
  classifyImage();
 
}

Mesmo este código parece complexo, é bastante simples. Primeiro, é necessário selecionar seu tipo de CAM. Altere de acordo com seu ESP32-CAM. Em seguida, temos que definir o ssid wi-fi e o passord wi-fi para que se conecte ao wi-fi.

É importante notar que reduzimos a resolução da câmera porque a codificação base64 requer muita memória. De qualquer forma, não precisamos de uma resolução maior para reconhecer a imagem.

Aquisição de uma imagem usando ESP32-CAM

Em seguida, podemos capturar a imagem que queremos classificar. Adicione as seguintes linhas:

void classifyImage() {
  
  // Capturar imagem
   camera_fb_t * fb = NULL;
   fb = esp_camera_fb_get();
   
   if(!fb) {
    Serial.println("A captura da câmera falhou");
    return;
   }

  size_t size = fb->len;
  String buffer = base64::encode((uint8_t *) fb->buf, fb->len);
  ....
}

camera_fb_t contém as informações da imagem e os dados que representam a imagem capturada. Usando o método esp_camera_fb_get(), o ESP32-CAM captura a imagem.

Finalmente, codificamos a imagem em base64. fb->buf contém os dados e fb->len é o tamanho do buffer. Além disso, adicione a seguinte linha no início do arquivo:

#include <base64.h>

Aplicação de reconhecimento de imagem usando ESP32-CAM

Uma vez que a imagem é capturada, o próximo passo é reconhecer a imagem e extrair informações dela. Mesmo que seja possível usar o modelo de aprendizado de máquina em execução no ESP32, queremos usar uma plataforma de aprendizado de máquina em nuvem que usa modelos pré-treinados. Para isso, é necessário invocar uma API e enviar a imagem codificada. No método classifyImage, adicione as seguintes linhas:

String payload = "{\"inputs\": [{ \"data\": {\"image\": {\"base64\": \"" + buffer + "\"}}}]}";

  buffer = "";
  // Remova o comentário se quiser mostrar a carga útil
  // Serial.println(payload);

  esp_camera_fb_return(fb);
  
  // Generic model
  String model_id = "aaa03c23b3724a16a56b629203edc62c";

  HTTPClient http;
  http.begin("https://api.clarifai.com/v2/models/" + model_id + "/outputs");
  http.addHeader("Content-Type", "application/json");     
  http.addHeader("Authorization", "Key your_key"); 
  int response_code = http.POST(payload);

O código na linha 10 é o id do modelo que queremos usar para reconhecer a imagem. Por enquanto, não considere a linha 14 a chave. É uma chave de autorização. Veremos mais tarde como fazer isso.

Adicione esta linha no início:

#include <HTTPClient.h>

Adicionando capacidade de visão computacional ao ESP32-CAM

Depois de enviarmos a imagem base64 para a plataforma de nuvem de aprendizado de máquina, obtemos a resposta com todos os conceitos extraídos da imagem.

Conceitos são rótulos usados para classificar a imagem e reconhecê-la. Usando os rótulos, obtemos uma descrição da imagem. Cada rótulo tem uma probabilidade.

Adicione ao método anterior as seguintes linhas:

// Analise a resposta json: assistente do Arduino
const int jsonSize = JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(20) + 3*JSON_OBJECT_SIZE(1) + 6*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 20*JSON_OBJECT_SIZE(4) + 2*JSON_OBJECT_SIZE(6);
DynamicJsonDocument doc(jsonSize);
deserializeJson(doc, response);


for (int i=0; i < 10; i++) {
  const name = doc["outputs"][0]["data"]["concepts"][i]["name"];
  const float p = doc["outputs"][0]["data"]["concepts"][i]["value"];
    
  Serial.println("=====================");
  Serial.print("Nome:");
  Serial.println(name[);
  Serial.print("Prob:");
  Serial.println(prob);
  Serial.println();
}

Neste código, usamos a biblioteca ArduinoJson para analisar a saída. Além disso, adicione a seguinte linha no topo do arquivo:

#include <ArduinoJson.h>

Finalmente, faça o ESP32-CAM dormir esperando a pressão do botão de reset:

Serial.println("\nDormir....");
esp_deep_sleep_start();

 

Teste o reconhecimento de imagem

Estamos prontos para testar como funciona a classificação de imagens com nosso ESP32-CAM. Depois de enviar o esboço para o ESP32-CAM, você deve pressionar o botão reset para iniciar o processo de reconhecimento de imagem.

Para visualizar a imagem capturada, você pode usar um decodificador de imagem base64 passando o fluxo de bytes codificado que representa a imagem.

Estes são alguns exemplos:

ESP-CAM

O ESP32-CAM identificou corretamente todos os conceitos: flor, nenhuma pessoa, natureza e folhas.

Este é outro exemplo:

ESP-CAM

Observe todas as informações extraídas da imagem: nenhuma pessoa, bola, recreação, futebol. Como você pode ver, aplicando a visão computacional ao ESP32-CAM, podemos extrair conceitos interessantes de uma imagem. A câmera ESP32 é capaz de identificar a imagem corretamente.

Testando modelo de aprendizado de máquina usando alimentos

Neste último exemplo, testaremos o reconhecimento de imagem ESP32-CAM usando alimentos. Portanto, é necessário mudar o modelo. Se você está se perguntando onde estão os modelos, você pode usar este link.

Altere o id do modelo no código anterior comentando o modelo antigo e esta linha:

// Generic model
//String model_id = "aaa03c23b3724a16a56b629203edc62c";

// Food model
String model_id = "bd367be194cf45149e75f01d59f77ba7";

Em seguida, carregue o sketch novamente no ESP32-CAM e verifique como o ESP32-CAM reconhece objetos usando os novos modelos de aprendizado de máquina:

Conforme afirmado na imagem anterior, a probabilidade de que seja uma maçã é de 96%. Portanto, o ESP32-CAM identificou a imagem corretamente novamente.

Finalmente, o último exemplo:

Empacotando

No final deste tutorial, descobrimos como implementar a classificação de imagem ESP32-CAM usando uma API de aprendizado de máquina em nuvem fornecida pela Clarifai. Demonstramos como é fácil implementar um sistema de visão computacional baseado em ESP32-CAM. A integração entre a capacidade ESP32-CAM e o modelo de aprendizado de máquina pode fazer com que este pequeno dispositivo detecte objetos e os reconheça. Além disso, por meio de visão computacional, extraímos informações de imagem usando os modelos pré-treinados de aprendizado de máquina.