Понадобилось тут мне сконвертировать  AVFrame в Mat для дальнейших издевательст с помощью OpenCV, загуглил я это дело, и нашёл кучу способов.

Вот один из них:

void AVFrameToMat(const AVFrame * frame, Mat& image)
{
    int width = frame->width;
    int height = frame->height;
    image = Mat(height, width, CV_8UC3);
    int cvLinesizes[1];
    cvLinesizes[0] = image.step1();
    SwsContext* conversion = sws_getContext(width, height, (AVPixelFormat) frame->format, width, height, PIX_FMT_BGR24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
    sws_scale(conversion, frame->data, frame->linesize, 0, height, &image.data, cvLinesizes);
    sws_freeContext(conversion);
}

Мне одному кажется, что столько преобразований излишни?  Ведь OpenCV напрямую позволяет работать со всеми форматами и можно сделать преобразование напрямую! 

В моём случае я работаю с форматом видео YUV420P.

if ( m_picture->format == AV_PIX_FMT_YUV420P ) {
    int numBytes=avpicture_get_size(AV_PIX_FMT_YUV420P, m_picture->width, m_picture->height);        
    uint8_t * buffer = reinterpret_cast<uint8_t *>(av_malloc(numBytes));
    avpicture_layout( ( AVPicture*)m_picture, AV_PIX_FMT_YUV420P, m_picture->width, m_picture->height, buffer, numBytes); //av_image_copy_to_buffer() в новом API


    Mat yuv = Mat(m_picture->height+m_picture->height/2, m_picture->width, CV_8UC1, buffer );
    Mat gray = Mat(m_picture->height, m_picture->width, CV_8UC1, buffer ); //-- Если нужно получить сразу в градациях серого (формат YUV содержит в первом канале как раз в градациях серого кадр)

    Mat rgb = Mat(m_picture->height, m_picture->width, CV_8UC3);
    cvtColor(yuv, rgb, CV_YUV420p2RGB);

    imshow("RGB", rgb);
    imshow("GRAY", gray);
}

ВАЖНО: Не забудьте очистить память из под buffer, так как после удаления Mat она не очищается самостоятельно!

В вашем случае замените форматы на те, с которыми работаете.

Вот как-то так…

Leave a Comment

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

You may also like