如何在esp32 cam示例代码中获取人脸的位置?

问题描述 投票:0回答:1

有一个名为 CameraWebServer 的 esp32 摄像头示例代码,在其中您可以流式传输 esp32 摄像头的视频输出,并且有一个打开面部识别的选项,所以我问我如何访问面部的坐标esp32 cam 正在检测。

我尝试在谷歌中寻找答案并使用chatGPT,但我发现没有任何效果

esp32 arduino-ide arduino-esp32
1个回答
0
投票

我遇到了确切的问题,因为我正在使用 ESP32-Cam 构建面部跟踪系统,并设法弄清楚如何在不使用网络服务器的情况下获取面部位置,但我不确定如何使用这些信息每当我使用 ESP32-Cam 运行伺服系统时,它都会自行重置,因为相机功能和伺服功能会相互干扰。 我首先使用了来自 https://robotzero.one/face-tracking-esp32-cam/ 的旧面部跟踪代码 要使其运行,您需要首先安装 ESP32 库版本 1.0.4,因为新版本不起作用。 然后,我删除了代码中所有 WiFi 和网络服务器部分,现在只要运行它,我就可以在串行端口上获取 320x240 图像大小上的脸部屏幕位置,而无需将其连接为网络服务器。 下一阶段是从属 Arduino nano 并使用我正在研究的 I2C 接口获取数据。

这是当前通过串口读取人脸位置数据的代码,希望对您有所帮助。除了此代码之外,您还需要下载 上面链接中的camera_index.h和camera_pins.h并将它们放在同一目录中。

// MoveHead_ESP_V1_5
// Board AI Thinker ESP-CAM
// This module requires ESP32 ver 1.0.4 to run
// This works identifying the face position without the need of server


#include <ArduinoWebsockets.h>
#include "camera_index.h"
#include "esp_camera.h"
#include "fb_gfx.h"
#include "fd_forward.h"
 

#include <Wire.h>

 // ESP32-CAM doesn't have dedicated i2c pins, so we define our own. Let's choose 15 and 14
#define I2C_SDA 15
#define I2C_SCL 14
TwoWire I2Cbus = TwoWire(0);

int NewPositionX=0;
int NewPositionY=0;

int ScreenPosX = 0;
int ScreenPosY=0;

int ScreenSizeX = 320;
int ScreenSizeY=240;

int MinPan = 30;
int MaxPan = 150;
int MinTilt = 0;
int MaxTilt = 55;

 
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
 
 
static inline mtmn_config_t app_mtmn_config()
{
  mtmn_config_t mtmn_config = {0};
  mtmn_config.type = FAST;
  mtmn_config.min_face = 80;
  mtmn_config.pyramid = 0.707;
  mtmn_config.pyramid_times = 4;
  mtmn_config.p_threshold.score = 0.6;
  mtmn_config.p_threshold.nms = 0.7;
  mtmn_config.p_threshold.candidate_number = 20;
  mtmn_config.r_threshold.score = 0.7;
  mtmn_config.r_threshold.nms = 0.7;
  mtmn_config.r_threshold.candidate_number = 10;
  mtmn_config.o_threshold.score = 0.7;
  mtmn_config.o_threshold.nms = 0.7;
  mtmn_config.o_threshold.candidate_number = 1;
  return mtmn_config;
}
mtmn_config_t mtmn_config = app_mtmn_config();
 
 
void setup()
{
  Serial.begin(115200);
  Serial.println("Loadong...");
  Serial.println();
 

  // Initialize I2C with our defined pins
  I2Cbus.begin(I2C_SDA, I2C_SCL, 100000);

  
 
  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;
  //init with high specs to pre-allocate larger buffers
  if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    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("Camera init failed with error 0x%x", err);
    return;
  }
 
  sensor_t * s = esp_camera_sensor_get();
  s->set_framesize(s, FRAMESIZE_QVGA);
 
 }
 
 

static void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes)
{
  int x, y, w, h, i, half_width, half_height;
  fb_data_t fb;
  fb.width = image_matrix->w;
  fb.height = image_matrix->h;
  fb.data = image_matrix->item;
  fb.bytes_per_pixel = 3;
  fb.format = FB_BGR888;
  for (i = 0; i < boxes->len; i++) {
 
    // Convoluted way of finding face centre...
    x = ((int)boxes->box[i].box_p[0]);
    w = (int)boxes->box[i].box_p[2] - x + 1;
    half_width = w / 2;
    int face_center_pan = x + half_width; // image frame face centre x co-ordinate
 
    y = (int)boxes->box[i].box_p[1];
    h = (int)boxes->box[i].box_p[3] - y + 1;
    half_height = h / 2;
    int face_center_tilt = y + half_height;  // image frame face centre y co-ordinate
 
    //    assume QVGA 320x240
    //    int sensor_width = 320;
    //    int sensor_height = 240;
    //    int lens_fov = 45
  
    Serial.print("Face:");
    Serial.print(face_center_pan); 
    Serial.print(" X ");
    Serial.print(face_center_tilt);

// Map the screen positions to Servo positions
NewPositionX = map(face_center_pan, 0, ScreenSizeX, MinPan, MaxPan);
NewPositionY = map(face_center_tilt, 0, ScreenSizeY, MinTilt, MaxTilt);

// Display X,Y screen coordinate, speed, Pan and Tilt


    Serial.print("   Pan:");
    Serial.print(NewPositionX); 
    Serial.print(" Tilt:");
    Serial.println(NewPositionY);

// this doesn't work, it seems that the servo interfere with the camera
// this is the place to use I2C to send the pan and tilt position to Arduino via I2C




  }
}
 

void loop()
{

 // auto client = socket_server.accept();
  camera_fb_t * fb = NULL;
  dl_matrix3du_t *image_matrix = NULL;
 
  while (true) {
    fb = esp_camera_fb_get();
    image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
 
    fmt2rgb888(fb->buf, fb->len, fb->format, image_matrix->item);
 
    box_array_t *net_boxes = NULL;
    net_boxes = face_detect(image_matrix, &mtmn_config);
 
    if (net_boxes) {
      draw_face_boxes(image_matrix, net_boxes);
      free(net_boxes->score);
      free(net_boxes->box);
      free(net_boxes->landmark);
      free(net_boxes);
    }
 
  
    esp_camera_fb_return(fb);
    fb = NULL;
    dl_matrix3du_free(image_matrix);
  }
  
}
© www.soinside.com 2019 - 2024. All rights reserved.