Проблема рендеринга в Project Tango с использованием обработки изображений OpenCV

Я столкнулся с одной проблемой при рендеринге изображения с камеры после некоторой обработки ее YUV-буфера.

Я использую пример video-overlay-jni-example и в методе OnFrameAvailable я создаю новый буфер кадра, используя метод cv::Mat...

Вот как я создаю новый буфер кадров:

cv::Mat frame((int) yuv_height_ + (int) (yuv_height_ / 2), (int) yuv_width_, CV_8UC1, (uchar *) yuv_temp_buffer_.data());

После обработки я копирую frame.data в yuv_temp_buffer_, чтобы отрендерить его на текстуре: memcpy(&yuv_temp_buffer_[0], frame.data, yuv_size_);

И это нормально работает...

Проблема начинается, когда я пытаюсь выполнить метод OpenCV findChessboardCorners..., используя кадр, который я создал ранее.

Выполнение метода findChessboardCorners занимает около 90 мс (11 кадров в секунду), однако, похоже, он рендерится медленнее. (Кажется, на экране рендеринг происходит со скоростью ~ 0,5 кадра в секунду).

Вот код метода OnFrameAvailable:

void AugmentedRealityApp::OnFrameAvailable(const TangoImageBuffer* buffer) {

    if (yuv_drawable_ == NULL){
        return;
    }

    if (yuv_drawable_->GetTextureId() == 0) {
        LOGE("AugmentedRealityApp::yuv texture id not valid");
        return;
    }

    if (buffer->format != TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP) {
        LOGE("AugmentedRealityApp::yuv texture format is not supported by this app");
        return;
    }

    // The memory needs to be allocated after we get the first frame because we
    // need to know the size of the image.
    if (!is_yuv_texture_available_) {
        yuv_width_ = buffer->width;
        yuv_height_ = buffer->height;
        uv_buffer_offset_ = yuv_width_ * yuv_height_;

        yuv_size_ = yuv_width_ * yuv_height_ + yuv_width_ * yuv_height_ / 2;

        // Reserve and resize the buffer size for RGB and YUV data.
        yuv_buffer_.resize(yuv_size_);
        yuv_temp_buffer_.resize(yuv_size_);
        rgb_buffer_.resize(yuv_width_ * yuv_height_ * 3);

        AllocateTexture(yuv_drawable_->GetTextureId(), yuv_width_, yuv_height_);
        is_yuv_texture_available_ = true;
    }

    std::lock_guard<std::mutex> lock(yuv_buffer_mutex_);
    memcpy(&yuv_temp_buffer_[0], buffer->data, yuv_size_);

    ///
    cv::Mat frame((int) yuv_height_ + (int) (yuv_height_ / 2), (int) yuv_width_, CV_8UC1, (uchar *) yuv_temp_buffer_.data());

    if (!stam.isCalibrated()) {
        Profiler profiler;
        profiler.startSampling();
        stam.initFromChessboard(frame, cv::Size(9, 6), 100);
        profiler.endSampling();
        profiler.print("initFromChessboard", -1);
    }
    ///

    memcpy(&yuv_temp_buffer_[0], frame.data, yuv_size_);
    swap_buffer_signal_ = true;
}

Вот код метода initFromChessBoard:

bool STAM::initFromChessboard(const cv::Mat& image, const cv::Size& chessBoardSize, int squareSize)
{
    cv::Mat rvec = cv::Mat(cv::Size(3, 1), CV_64F);
    cv::Mat tvec = cv::Mat(cv::Size(3, 1), CV_64F);

    std::vector<cv::Point2d> imagePoints, imageBoardPoints;
    std::vector<cv::Point3d> boardPoints;

    for (int i = 0; i < chessBoardSize.height; i++)
    {
        for (int j = 0; j < chessBoardSize.width; j++)
        {
            boardPoints.push_back(cv::Point3d(j*squareSize, i*squareSize, 0.0));
        }
    }

    //getting only the Y channel (many of the functions like face detect and align only needs the grayscale image)
    cv::Mat gray(image.rows, image.cols, CV_8UC1);
    gray.data = image.data;

    bool found = findChessboardCorners(gray, chessBoardSize, imagePoints, cv::CALIB_CB_FAST_CHECK);

#ifdef WINDOWS_VS
    printf("Number of chessboard points: %d\n", imagePoints.size());
#elif ANDROID
    LOGE("Number of chessboard points: %d", imagePoints.size());
#endif

    for (int i = 0; i < imagePoints.size(); i++) {
        cv::circle(image, imagePoints[i], 6, cv::Scalar(149, 43, 0), -1);
    }
}

У кого-нибудь есть такая же проблема после обработки чего-то в буфере YUV для рендеринга текстуры?

Я провел тест, используя другое устройство, а не проект Tango, используя API camera2, и процесс рендеринга на экране, по-видимому, имеет ту же скорость, что и сам процесс функции OpenCV.

Я ценю любую помощь.


person Thúlio Araújo    schedule 22.02.2016    source источник


Ответы (1)


У меня была похожая проблема. Мое приложение замедлилось после использования скопированного буфера yuv и некоторой обработки изображений с помощью OpenCV. Я рекомендую вам использовать библиотеку tango_support для доступа буфер изображения yuv, выполнив следующие действия:

В вашей функции конфигурации:

int AugmentedRealityApp::TangoSetupConfig() {
   TangoSupport_createImageBufferManager(TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP, 1280, 720, &yuv_manager_);
}

В вашей функции обратного вызова:

void AugmentedRealityApp::OnFrameAvailable(const TangoImageBuffer* buffer) {
   TangoSupport_updateImageBuffer(yuv_manager_, buffer);
}

В вашем потоке рендеринга:

void AugmentedRealityApp::Render() {
   TangoImageBuffer* yuv = new TangoImageBuffer();
   TangoSupport_getLatestImageBuffer(yuv_manager_, &yuv);
   cv::Mat yuv_frame, rgb_img, gray_img;
   yuv_frame.create(720*3/2, 1280, CV_8UC1);
   memcpy(yuv_frame.data, yuv->data, 720*3/2*1280);  // yuv image
   cv::cvtColor(yuv_frame, rgb_img, CV_YUV2RGB_NV21); // rgb image
   cvtColor(rgb_img, gray_img, CV_RGB2GRAY); // gray image
}

Вы можете поделиться yuv_manger с другими объектами/потоками, чтобы вы могли получить доступ к буферу изображений yuv, где бы вы ни находились.

person bashbug    schedule 23.02.2016
comment
Большое спасибо @bashbug !!! Ваш ответ был очень полезен. Я не знал о библиотеке tango_support для управления буфером кадров. Теперь он работает нормально! - person Thúlio Araújo; 23.02.2016
comment
Здравствуйте @bashbug, вы знаете, как изменить разрешение Tango Camera? Я имею в виду, что в настоящее время я получаю 1280 * 720, и я хочу получить как минимум 640 * 360. - person Thúlio Araújo; 16.03.2016
comment
Я не знаю, есть ли способ изменить разрешение буфера. Но вы можете использовать openCV для изменения размера изображения answers.opencv.org/question/12825/ - person bashbug; 16.03.2016