Артинтрек — это модуль, осуществляющий обработку видеопотока с помощью нейронных сетей и компьютерного зрения, содержащий в себе:
Модуль Артинтрек может использоваться для изучения основ искусственного интеллекта и компьютерного зрения. Готовые скрипты позволят передавать результаты работы нейронных сетей на контроллер для управления робототехническими моделями. Для обучения основам работы с нейронными сетями, а также для их разработки реализовано дополнительно специальное ПО - NNWizard. Обучение реализовано по 3 модулям: 1 и 2 модули позволяют детям разного возраста изучать основы построения и обучения нейронных сетей, перспективу их развития и использования в современном обществе с помощью курсов: «Искусственный интеллект в окружающем мире» (предназначенный для детей от 7 лет), «Изучение основ искусственного интеллекта» (предназначенный для детей от 12 лет).
Оба блока предполагают использование готовых обученных нейронных сетей. С их помощью дети на практике могут научиться использовать искусственный интеллект для распознавания текста, изображений, эмоций, жестов, возраста человека и многое другое.
Артинтрек поставляется с набором предустановленных моделей нейронных сетей для обработки видеопотока:
Модуль Артинтрек получает питание от внешнего источника по шине UART, для полноценной работы необходимо использовать источник питания с напряжением 5V и силой тока 3А.
Рекомендуется подключать модуль Артинтрек к плате Трекдуино или Трекдуино ПРО следующим образом:
Модуль Артинтрек снабжен системой охлаждения как графического ускорителя, так и внутреннего процессора.
Для подключения внешних устройств и обмена информацией на корпус выведены 2 порта USB.
Для работы модуля требуется подключить внешнюю USB-видеокамеру в один из портов USB.
void trackcv_neural_start(Neural_script_id script_id);
Запуск производится при первом запросе информации.
void trackcv_neural_stop();
Остановка анализатора производится при запуске другого режима распознавания.
Neural_script_id_dummy = 0, // Пустышка Neural_script_id_mnist = 1, // MNIST Neural_script_id_imagenet = 2, // ImageNet Neural_script_id_text_detection = 3, // Нахождение текста Neural_script_id_face_detection = 4, // Нахождение лиц Neural_script_id_head_pose = 5, // Углы поворота головы Neural_script_id_age_gender = 6, // Оценка пола и возраста Neural_script_id_emotion = 7, // Определение эмоции Neural_script_id_gesture = 8, // Определение жестов руки Neural_script_id_landmarks_5 = 9, // 5 ключевых точек лица Neural_script_id_landmarks_35 = 10, // 35 ключевых точек лица Neural_script_id_face_recognition = 11 // Определение лиц
Neural_gesture_UP = 1, // Указывает наверх Neural_gesture_DOWN = 2, // Указывает вниз Neural_gesture_LEFT = 3, // Указывает влево Neural_gesture_RIGHT = 4, // Указывает вправо Neural_gesture_OPEN = 5, // Открытая ладонь с отставленными пальцами Neural_gesture_CLOSE = 6, // Открытая сторона кулака Neural_gesture_STOP = 7 // Закрытая сторона кулака
Neural_emotion_NEUTRAL = 0, // Нейтральная Neural_emotion_HAPPY = 1, // Счастье Neural_emotion_SAD = 2, // Грусть Neural_emotion_SURPRISE = 3, // Удивление Neural_emotion_ANGER = 4 // Злоба
Для удобства создайте 2 функции, облегчающие операции чтения и записи по протоколу UART:
bool comm_send(char data)
Например:
bool comm_send(char data) { return Serial2.write(data) == 1; }
Здесь Serial2 отвечает за использование разъема UART2 платы Трекдуино. Для использования UART1 используйте Serial1.
Отправляет символ data по протоколу UART.
Возвращает:
bool comm_recv()
Например:
int32_t comm_recv() { return (int32_t)Serial2.read(); }
Здесь Serial2 отвечает за использование разъема UART2 платы Трекдуино. Для использования UART1 используйте Serial1.
Получает целочисленное значение типа int32t по протоколу UART.
Добавьте строку Trackcv_init(comm_recv, comm_send, 0); в тело функции setup().
void setup() { /* Ваш код ... */ Trackcv_init(comm_recv, comm_send, 0); /* Ваш код ... */ }
Модуль инициализируется с помощью передачи функций работы с UART-портом.
Добавьте переменную, отвечающую за состояние инициализации:
bool inited = false;
В главном цикле необходимо удостовериться в том, что модуль готов к работе:
void loop() { // Если модуль не инициализирован if (!inited) { // Если код ошибки != OK if (trackcv_get_errno() != ERR_OK) { Serial.println("TrackCV: Fail"); // Сигнализируем красным цветом светодиода builtInRGB(RED); // Если модуль отвечает, но еще не готов к работе if (trackcv_check()) { Serial.println("Check: OK"); } else { Serial.println("Check: Fail"); } delay(250); return; } else { Serial.println("TrackCV: OK"); // Запускаем нужную нейронную сеть (здесь - MNIST) trackcv_neural_start(Neural_script_id_mnist); // Переключаем флаг инициализации inited = true; // Выключаем светодиод, сигнализируя о готовности к работе builtInRGB(OFF); } } /* Ваш код ... */ // Проверяем наличие ошибок в работе Errno errno = trackcv_get_errno(); // Если код ошибки != OK if (errno != ERR_OK) { Serial.println("TrackCV: Error " + String(errno)); // Переключаем флаг инициализации inited = false; return; } }
В Артинтрек добавлена возможность использовать библиотеку компьютерного зрения TrackCV, применяемую в работе модуля Витрек. Для запуска данной библиотеки необходимо использовать следующие функции:
Работа с модулем должна начинаться с вызова этой функции:
bool Trackcv_init(int32_t (*reader)(void), bool (*writer)(char), int32_t (*putfunc)(unsigned char));
Параметры:
Возвращает:
Проверка доступности и работоспособности модуля.
bool trackcv_check(void);
Возвращает:
void trackcv_set_frame_x(uint32_t frame_x);
Устанавливает левую границу кадра для анализа. Значение по умолчанию: 0.
Параметры frame_x : Координата X левой границы кадра (в процентах относительно ширины кадра).
void trackcv_set_frame_y(uint32_t frame_y);
Устанавливает нижнюю границу кадра для анализа. Значение по умолчанию: 0.
Параметры frame_y : Координата Y нижней границы кадра (в процентах относительно высоты кадра).
void trackcv_set_frame_height(uint32_t frame_height);
Устанавливает высоту кадра для анализа. Значение по умолчанию: 0.
Параметры frame_height : Высота кадра (в процентах относительно высоты кадра).
void trackcv_set_frame_width(uint32_t frame_width);
Устанавливает ширину кадра для анализа. Значение по умолчанию: 0.
Параметры frame_width : Ширина кадра (в процентах относительно ширины кадра).
После осуществления обращения к переменной пользователь может получить информацию о том, выполнилась ли функция корректно или с ошибкой, вернув значение по умолчанию.
typedef enum { ERR_OK = 0, // нормальная работа WRONG_INDEX = 1, // неправильный индекс массива NO_MODULE = 2, // нет ответа от модуля MODULE_ERR = 3, // ошибка модуля COMM_ERR = 4, // ошибка библиотеки связи MODULE_NOREADY = 5 // модуль не готов } Errno;
Получение кода ошибки
Errno trackcv_get_errno()
Возвращает Значение типа Errno.
Для работы с модулем Артинтрек из среды разработки Robotrack IDE необходимо скачать и обновить библиотеку TrackCV.
Для удобного начала работы с модулем Артинтрек вы можете загрузить готовые примеры программ для прошивки контроллера Трекдуино. Вся информация о текущей работе нейронной сети будет приходить в монитор порта, а результат работы алгоритма будет идентифицироваться изменением цвета RGB светодиода, встроенного в контроллер Трекдуино. Все примеры можно загрузить по ссылке
При распознавании цифры светодиод мигает столько же раз.
#include "Trackcv.h" bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) {return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); // put your setup code here, to run once: } bool inited = false; int cached_num = -1; void loop() { // проверка запуска модуля Артинтрек if(!inited) { if (trackcv_get_errno() != ERR_OK) { // если есть ошибки Serial.println("trackcv...fail"); builtInRGB(RED); //зажигаем красным RGB светодиод if(trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; // проверяем до тех пор, пока модуль не запустится } else { // если нет ошибки Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_mnist); // запускаем нейронную сеть MNIST inited = true; builtInRGB(OFF); //отключаем RGB светодиод } } if(trackcv_neural_count() > 0) { if( trackcv_neural_width(0) > 13 && trackcv_neural_class_count(0) > 0 && trackcv_neural_class_p(0, 0) > 80 ) { int num = trackcv_neural_class_id(0, 0); if(num != cached_num) { // если цифра распознана Serial.print("found "); //выводим текст "found" Serial.println(num); //выводим значение цифры for(int i = 0; i < num; i++) { // повторяем в зависимости от распознанного числа builtInRGB(GREEN); // при обнаружении рукописной цифры включаем зеленым встроенный RGB светодоид delay(100); builtInRGB(OFF); delay(150); } cached_num = num; // сохраняем полученное значение } } } else { if(cached_num != -1) { // если новая цифра не найдена Serial.print("lost num\n"); // выводим прошлое значение builtInRGB(BLUE); // зажигаем синим RGB светодиод delay(200); builtInRGB(OFF); cached_num = -1; } } delay(100); Errno errno = ERR_OK; // в случае обнаружения ошибки if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); // выводим ее номер inited = false; return; } }
При обнаружении объекта из базы данных включается зеленый светодиод, и выводится номер объекта в монитор порта. Список объектов содержится в папке с примером.
#include "Trackcv.h" bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) {return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; void loop() { if(!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if(trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_imagenet); inited = true; builtInRGB(OFF); } } // если найден объект if(trackcv_neural_count() > 0) { // получаем достоверность определения объекта Serial.print("p:"); Serial.println(trackcv_neural_class_p(0, 0)); if(trackcv_neural_class_p(0, 0) > 70) { Serial.print("id:"); Serial.println(trackcv_neural_class_id(0, 0)); if(trackcv_neural_class_id(0, 0) == COFFEE_MUG) { builtInRGB(GREEN); } } else { builtInRGB(OFF); } } else { builtInRGB(OFF); } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); inited = false; return; } }
Выводим достоверность и содержимое текста в монитор порта.
#include "Trackcv.h" bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) {return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; void loop() { if(!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if(trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_text_detection); inited = true; builtInRGB(OFF); } } Serial.println("===="); for(int i = 0; i < trackcv_neural_count(); i++) { if(trackcv_neural_class_count(i) != 1) { Serial.println("wrong description"); delay(100); } Serial.print("x:"); Serial.print(trackcv_neural_x(i)); Serial.print(" y:"); Serial.print(trackcv_neural_y(i)); Serial.print(" p:"); Serial.print(trackcv_neural_class_p(i, 0)); Serial.print(" "); Serial.println(trackcv_neural_class_meta(i, 0)); } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); inited = false; return; } }
При обнаружении лица выводятся его координаты в монитор порта.
#include "Trackcv.h" bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) {return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; void loop() { if(!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if(trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_face_detection); inited = true; builtInRGB(OFF); } } if(trackcv_neural_count() > 0) { if( trackcv_neural_class_count(0) > 0 && trackcv_neural_class_p(0, 0) > 80 ) { Serial.print("face: "); Serial.print(trackcv_neural_x(0)); Serial.print(" "); Serial.println(trackcv_neural_y(0)); } } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); inited = false; return; }}
Выводится значения вращения головы относительно 3 координат.
#include "Trackcv.h" bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) {return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; void loop() { if(!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if(trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_head_pose); inited = true; builtInRGB(OFF); } } // если найдено хотя бы одно лицо if(trackcv_neural_count() > 0) { // описание положения головы должно содержать 4 параметра if(trackcv_neural_class_count(0) != 4) { Serial.println("wrong description"); delay(100); } // проверяем достоверность нахождения лица if(trackcv_neural_class_p(0, 0) > 80) { // получаем углы наклона int yaw = trackcv_neural_class_p(0, 1); int pitch = trackcv_neural_class_p(0, 2); int roll = trackcv_neural_class_p(0, 3); Serial.print("yaw: "); Serial.print(yaw); Serial.print(" , pitch: "); Serial.print(pitch); Serial.print(" , roll: "); Serial.println(roll); } } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); inited = false; return; } }
Выводится в монитор порта значение возраста пола и значение достоверности определения.
#include "Trackcv.h" bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) {return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; void loop() { if(!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if(trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_age_gender); inited = true; builtInRGB(OFF); } } // если найдено хотя бы одно лицо if(trackcv_neural_count() > 0) { // описание возраста и пола должно содержать 4 параметра if(trackcv_neural_class_count(0) != 4) { Serial.println("wrong description"); delay(100); } // проверяем достоверность нахождения лица if(trackcv_neural_class_p(0, 0) > 80) { // получаем информацию int female_p = trackcv_neural_class_p(0, 1); int male_p = trackcv_neural_class_p(0, 2); int age = trackcv_neural_class_p(0, 3); Serial.print("age: "); Serial.print(age); Serial.print(" , female %: "); Serial.print(female_p); Serial.print(" , male %: "); Serial.println(male_p); } } else { } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); inited = false; return; } }
Выводится в монитор порта значение эмоции и значение определения её достоверности. Если улыбнуться, встроенный RGB светодиод загорится зеленым. Если показать эмоцию печали, то встроенный RGB светодиод загорится красным.
#include "Trackcv.h" bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) {return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; void loop() { if(!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if(trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_emotion); inited = true; builtInRGB(OFF); } } if(trackcv_neural_count() > 0) { if( trackcv_neural_class_count(0) > 0 && trackcv_neural_class_p(0, 0) > 80 ) { Serial.print("face: "); Serial.print(trackcv_neural_x(0)); Serial.print(" "); Serial.println(trackcv_neural_y(0)); if(trackcv_neural_class_p(0,1) == Neural_emotion_HAPPY) { // happy builtInRGB(GREEN); } else if (trackcv_neural_class_p(0,1) == Neural_emotion_SAD) { // sad builtInRGB(RED); } else { builtInRGB(BLUE); } } } else { builtInRGB(OFF); } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); builtInRGB(OFF); inited = false; return; } }
При распознавании жестов будет выводится информация в монитор порта, а встроенный светодиод загораться соответствующим цветом RGB.
#include "Trackcv.h" bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) {return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; void loop() { if(!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if(trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_gesture); inited = true; builtInRGB(OFF); } } // если найден жест if(trackcv_neural_count() > 0) { // получаем достоверность определения жеста Serial.println(trackcv_neural_class_p(0, 0)); // проверяем достоверность нахождения жеста if(trackcv_neural_class_p(0, 0) > 80) { int gesture_id = trackcv_neural_class_id(0, 0); // open palm if(gesture_id == Neural_gesture_OPEN) { builtInRGB(GREEN); } // closed palm if(gesture_id == Neural_gesture_CLOSE) { builtInRGB(RED); } // right if(gesture_id == Neural_gesture_RIGHT) { builtInRGB(BLUE); } Serial.print("gesture: "); if (gesture_id == Neural_gesture_OPEN) { Serial.println("OPEN"); } else if (gesture_id == Neural_gesture_CLOSE) { Serial.println("CLOSE"); } else if (gesture_id == Neural_gesture_LEFT) { Serial.println("LEFT"); } else if (gesture_id == Neural_gesture_RIGHT) { Serial.println("RIGHT"); } else if (gesture_id == Neural_gesture_UP) { Serial.println("UP"); } else if (gesture_id == Neural_gesture_DOWN) { Serial.println("DOWN"); } } } else { } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); inited = false; return; } }
Вывод координаты одной из 5 точек лица в монитор порта.
#include "Trackcv.h" bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) {return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; void loop() { if(!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if(trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_landmarks_5); inited = true; builtInRGB(OFF); } } // если найдено хотя бы одно лицо if(trackcv_neural_count() > 0) { // описание положения головы должно содержать 2 параметра (достоверность лица + точки) if(trackcv_neural_class_count(0) != 2) { Serial.println("wrong description"); delay(100); } // проверяем достоверность нахождения лица if(trackcv_neural_class_p(0, 0) > 80) { // получаем одну из точек char* landmarks = trackcv_neural_class_meta(0, 1); int point_x = landmarks[0]; int point_y = landmarks[1]; Serial.print("x: "); Serial.print(point_x); Serial.print(" , y: "); Serial.println(point_y); } } else { } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); inited = false; return; } }
Вывод координаты одной из 35 точек лица в монитор порта.
#include "Trackcv.h" bool comm_send(char data) { return Serial2.write(data) == 1; } int32_t comm_recv() { return (int32_t)Serial2.read(); } void delay_ms(uint32_t value) { delay(value); } uint32_t TS_ms(void) { return (uint32_t)millis(); } void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; void loop() { if (!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if (trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_landmarks_35); inited = true; builtInRGB(OFF); } } // если найдено хотя бы одно лицо if (trackcv_neural_count() > 0) { // описание положения головы должно содержать 2 параметра (достоверность лица + точки) if (trackcv_neural_class_count(0) != 2) { Serial.println("wrong description"); delay(100); } // проверяем достоверность нахождения лица if (trackcv_neural_class_p(0, 0) > 80) { // получаем одну из точек char *landmarks = trackcv_neural_class_meta(0, 1); for (size_t i = 0; i < 70; i += 2) { int point_x = landmarks[i]; int point_y = landmarks[i + 1]; char s[12]; sprintf(s, "%d: %d, %d", 1 + (i / 2), point_x, point_y); Serial.println(s); //Serial.println(String(1 + (i / 2)) + ": " + String(point_x) + ", " + String(point_y)); } } } else { } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); inited = false; return; } }
В ходе работы программы делаем фотографию 2 эталонных лиц по нажатию кнопки вниз контроллера Трекдуино, при нахождении первого лица включаем зеленым встроенный RGB светодиод контроллера Трекдуино, а второго - синим. При нажатии вверх очищаем эталонные лица.
#include "Trackcv.h" extern "C" { #include "trackcv/xprintf.h" } bool comm_send(char data) {return Serial2.write(data) == 1;} int32_t comm_recv() {return (int32_t)Serial2.read();} void delay_ms(uint32_t value) {delay(value);} uint32_t TS_ms(void) { return (uint32_t)millis();} void setup() { Serial.begin(115200); Serial2.begin(115200); Serial.print("start trackcv...\n"); Trackcv_init(comm_recv, comm_send, 0); } bool inited = false; /* По нажатию кнопки вверх -- очищаем список лиц По нажатию кнопки вниз -- сохраняем лицо. Сохраняются с именами "1.png" и "2.png" При обнаружении первое лицо светит зеленым, второе лицо светит синим. */ int current_face_id = 1; void clear_faces() { current_face_id = 1; if (trackcv_neural_clear_faces()) { Serial.println("clear faces ok"); } else { Serial.println("clear faces err"); } } void save_face() { if (trackcv_neural_count() != 1) { Serial.println("no face"); return; } if (current_face_id > 2) { Serial.println("faces limit exceed"); return; } char face_id_str[2]; xsprintf(face_id_str, "%d", current_face_id); if (trackcv_neural_save_face(face_id_str)) { Serial.print(face_id_str); Serial.println(" save face ok"); current_face_id++; } else { Serial.print(face_id_str); Serial.println(" save face err"); } } void check_face() { if (trackcv_neural_count() != 1) { Serial.println("no face"); builtInRGB(OFF); return; } bool is_face = false; int person_id = -1; int person_max_p = 0; for (int class_id = 0; class_id < trackcv_neural_class_count(0); class_id++) { if (trackcv_neural_class_p(0, class_id) > 90) { Serial.print("\tfound "); Serial.print(trackcv_neural_class_meta(0, class_id)); Serial.print("\tp = "); Serial.println(trackcv_neural_class_p(0, class_id)); if ((strstr(trackcv_neural_class_meta(0, class_id), "1.png") != 0 || strstr(trackcv_neural_class_meta(0, class_id), "2.png") != 0) && trackcv_neural_class_p(0, class_id) > 0) { is_face = true; if (trackcv_neural_class_p(0, class_id) > person_max_p) { person_max_p = trackcv_neural_class_p(0, class_id); person_id = class_id; } } } switch (person_id) { case 0: { Serial.println("Person 1"); builtInRGB(GREEN); break; } case 1: { Serial.println("Person 2"); builtInRGB(BLUE); break; } } } if (!is_face) { Serial.println("no face"); builtInRGB(OFF); } } void loop() { if (!inited) { if (trackcv_get_errno() != ERR_OK) { Serial.println("trackcv...fail"); builtInRGB(RED); if (trackcv_check()) { Serial.print("check ok\n"); } else { Serial.print("check fail\n"); } delay(250); return; } else { Serial.print("trackcv...ok\n"); trackcv_neural_start(Neural_script_id_face_recognition); inited = true; builtInRGB(OFF); } } check_face(); if (!digitalRead(BTN_UP)) { save_face(); builtInRGB(RED); delay(500); builtInRGB(OFF); } if (!digitalRead(BTN_DOWN)) { clear_faces(); builtInRGB(RED); delay(500); builtInRGB(OFF); } delay(100); Errno errno = ERR_OK; if ((errno = trackcv_get_errno()) != ERR_OK) { Serial.print("trackcv err "); Serial.println(errno); inited = false; return; } }