espressif / esp-who

Face detection and recognition framework
Other
1.64k stars 458 forks source link

human_face_recognition/lcd中,相机输出格式改为JPEG时输出图像不正确 (AIV-604) #253

Closed CaoJu600 closed 1 year ago

CaoJu600 commented 1 year ago

人脸识别例程中默认的摄像头输出格式是RGB565,我将它改为了JPEG并在识别前进行解码,程序运行没什么问题,但是解码后的图像不正确。 app_main中: register_camera(PIXFORMAT_RGB565, FRAMESIZE_240X240, 2, xQueueAIFrame); 改为 register_camera(PIXFORMAT_JPEG, FRAMESIZE_240X240, 2, xQueueAIFrame);

然后主要修改的是who_human_face_recognition.cpp中下图框选部分,lcd刷屏函数搬过来是为了方便调试,原先的lcd任务已经禁用。 111 当相机格式选用RGB565时,输出画面一切正常 IMG_20230410_213539 改用jpeg后 IMG_20230410_213117

frame->buf拷贝到oldbuf的过程应该没问题,我尝试过将oldbuf通过wifi发送到电脑并保存为jpg格式,图片完全正常。 但经过jpg2rgb565函数解码后的newbuf,用lcd显示就是上图的错误效果。 调试了很久也没找到问题出在哪里,希望有大佬解惑,感激不尽!

下面是who_human_face_recognition.cpp中static void task_process_handler(void arg)修改后的完整代码: extern scr_driver_t g_lcd; static void task_process_handler(void arg) { camera_fb_t *frame = NULL; HumanFaceDetectMSR01 detector(0.3F, 0.3F, 10, 0.3F); HumanFaceDetectMNP01 detector2(0.4F, 0.3F, 10);

if CONFIG_MFN_V1

if CONFIG_S8

FaceRecognition112V1S8 *recognizer = new FaceRecognition112V1S8();

elif CONFIG_S16

FaceRecognition112V1S16 *recognizer = new FaceRecognition112V1S16();

endif

endif

show_state_t frame_show_state = SHOW_STATE_IDLE;
recognizer_state_t _gEvent;
recognizer->set_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "fr");
int partition_result = recognizer->set_ids_from_flash();

//malloc了两个buffer用来存放解码前和解码后的图像
uint8_t *oldbuf = (uint8_t *)heap_caps_malloc(1024 * 8, MALLOC_CAP_SPIRAM);
uint8_t *newbuf = (uint8_t *)heap_caps_malloc(240 * 240 * 2, MALLOC_CAP_SPIRAM);
while (true)
{
    xSemaphoreTake(xMutex, portMAX_DELAY);
    _gEvent = gEvent;
    gEvent = DETECT;
    xSemaphoreGive(xMutex);
    if (_gEvent)
    {
        bool is_detected = false;

        if (xQueueReceive(xQueueFrameI, &frame, portMAX_DELAY))
        {
            //这样输出的图像错误
            if (frame->format == PIXFORMAT_JPEG)
            {
                memcpy(oldbuf, frame->buf, frame->len);
                jpg2rgb565(oldbuf, frame->len, newbuf, JPG_SCALE_NONE);
                g_lcd.draw_bitmap(0, 0, 240, 240, (uint16_t *)newbuf);
            }
           //这样没问题
            else if(frame->format == PIXFORMAT_RGB565)
            {
                g_lcd.draw_bitmap(0, 0, 240, 240, (uint16_t *)frame->buf);
            }

            std::list<dl::detect::result_t> &detect_candidates = detector.infer((uint16_t *)frame->buf, {(int)frame->height, (int)frame->width, 3});
            std::list<dl::detect::result_t> &detect_results = detector2.infer((uint16_t *)frame->buf, {(int)frame->height, (int)frame->width, 3}, detect_candidates);

            if (detect_results.size() == 1)
                is_detected = true;

            if (is_detected)
            {
                switch (_gEvent)
                {
                case ENROLL:
                    recognizer->enroll_id((uint16_t *)frame->buf, {(int)frame->height, (int)frame->width, 3}, detect_results.front().keypoint, "", true);
                    ESP_LOGW("ENROLL", "ID %d is enrolled", recognizer->get_enrolled_ids().back().id);
                    frame_show_state = SHOW_STATE_ENROLL;
                    break;

                case RECOGNIZE:
                    recognizer->set_thresh(0.8);
                    recognize_result = recognizer->recognize((uint16_t *)frame->buf, {(int)frame->height, (int)frame->width, 3}, detect_results.front().keypoint);
                    print_detection_result(detect_results);
                    if (recognize_result.id > 0)
                        ESP_LOGI("RECOGNIZE", "Similarity: %f, Match ID: %d", recognize_result.similarity, recognize_result.id);
                    else
                        ESP_LOGE("RECOGNIZE", "Similarity: %f, Match ID: %d", recognize_result.similarity, recognize_result.id);
                    frame_show_state = SHOW_STATE_RECOGNIZE;
                    break;

                case DELETE:
                    vTaskDelay(10);
                    recognizer->delete_id(true);
                    ESP_LOGE("DELETE", "% d IDs left", recognizer->get_enrolled_id_num());
                    frame_show_state = SHOW_STATE_DELETE;
                    break;

                default:
                    break;
                }
            }

            if (frame_show_state != SHOW_STATE_IDLE)
            {
                static int frame_count = 0;
                switch (frame_show_state)
                {
                case SHOW_STATE_DELETE:
                    rgb_printf(frame, RGB565_MASK_RED, "%d IDs left", recognizer->get_enrolled_id_num());
                    break;

                case SHOW_STATE_RECOGNIZE:
                    if (recognize_result.id > 0)
                        rgb_printf(frame, RGB565_MASK_GREEN, "ID %d", recognize_result.id);
                    else
                        rgb_print(frame, RGB565_MASK_RED, "who ?");
                    break;

                case SHOW_STATE_ENROLL:
                    rgb_printf(frame, RGB565_MASK_BLUE, "Enroll: ID %d", recognizer->get_enrolled_ids().back().id);
                    break;

                default:
                    break;
                }

                if (++frame_count > FRAME_DELAY_NUM)
                {
                    frame_count = 0;
                    frame_show_state = SHOW_STATE_IDLE;
                }
            }

            if (detect_results.size())
            {

if !CONFIG_IDF_TARGET_ESP32S3

                print_detection_result(detect_results);

endif

                draw_detection_result((uint16_t *)frame->buf, frame->height, frame->width, detect_results);
            }
        }

        if (xQueueFrameO)
        {
            esp_camera_fb_return(frame);
            //xQueueSend(xQueueFrameO, &frame, portMAX_DELAY);
        }
        else if (gReturnFB)
        {
            esp_camera_fb_return(frame);
        }
        else
        {
            free(frame);
        }

        if (xQueueResult && is_detected)
        {
            xQueueSend(xQueueResult, &recognize_result, portMAX_DELAY);
        }
    }
}

}

WangYuxin-esp commented 1 year ago

这里应该是一个字节序问题。你可以参考:https://github.com/espressif/esp32-camera/pull/428

uint8_t rgbBuf[...];

jpg2rgb565(fb->buf, fb->len, rgbBuf, JPG_SCALE_8X);

// swap the byte order and the image looks ok
size_t i;
for(i = 0; i < sizeof(rgbBuf); i+=2){
    const uint8_t tmp = rgbBuf[i];
    rgbBuf[i] = rgbBuf[i+1];
    rgbBuf[i+1] = tmp;
}
CaoJu600 commented 1 year ago

这里应该是一个字节序问题。你可以参考:https://github.com/espressif/esp32-camera/pull/428。

uint8_t rgbBuf[...];

jpg2rgb565(fb->buf, fb->len, rgbBuf, JPG_SCALE_8X);

// swap the byte order and the image looks ok
size_t i;
for(i = 0; i < sizeof(rgbBuf); i+=2){
    const uint8_t tmp = rgbBuf[i];
    rgbBuf[i] = rgbBuf[i+1];
    rgbBuf[i+1] = tmp;
}

解决了,非常感谢!