zoukankan      html  css  js  c++  java
  • AVFrame转换到Mat,yuv420p转换到RGB源代码

    FFmpeg中AVFrame到OpenCV中Mat的两种转换方法

    方法一:查表法

    void AVFrame2Img(AVFrame *pFrame, cv::Mat& img)
    {
        int frameHeight = pFrame->height;
        int frameWidth = pFrame->width;
        int channels = 3;
        //输出图像分配内存
        img = cv::Mat::zeros(frameHeight, frameWidth, CV_8UC3);
        //反转图像
        pFrame->data[0] += pFrame->linesize[0] * (frameHeight - 1);
        pFrame->linesize[0] *= -1;
        pFrame->data[1] += pFrame->linesize[1] * (frameHeight / 2 - 1);
        pFrame->linesize[1] *= -1;
        pFrame->data[2] += pFrame->linesize[2] * (frameHeight / 2 - 1);
        pFrame->linesize[2] *= -1;
    
        //创建保存yuv数据的buffer
        uchar* pDecodedBuffer = (uchar*)malloc(frameHeight*frameWidth * sizeof(uchar)*channels);
    
        //从AVFrame中获取yuv420p数据,并保存到buffer
        int i, j, k;
        //拷贝y分量
        for (i = 0; i < frameHeight; i++)
        {
            memcpy(pDecodedBuffer + frameWidth*i,
                pFrame->data[0] + pFrame->linesize[0] * i,
                frameWidth);
        }
        //拷贝u分量
        for (j = 0; j < frameHeight / 2; j++)
        {
            memcpy(pDecodedBuffer + frameWidth*i + frameWidth / 2 * j,
                pFrame->data[1] + pFrame->linesize[1] * j,
                frameWidth / 2);
        }
        //拷贝v分量
        for (k = 0; k < frameHeight / 2; k++)
        {
            memcpy(pDecodedBuffer + frameWidth*i + frameWidth / 2 * j + frameWidth / 2 * k,
                pFrame->data[2] + pFrame->linesize[2] * k,
                frameWidth / 2);
        }
    
        //将buffer中的yuv420p数据转换为RGB;
        YUV2RGB(pDecodedBuffer, frameWidth, frameHeight, channels, img.data);
    
        //释放buffer
        free(pDecodedBuffer);
    }

     子函数YUV2RGB( )实现yuv420p到RGB的转换

    bool YUV2RGB(uchar* pYuvBuf, int nWidth, int nHeight, int channels, uchar* pRgbBuf)
    {
    #define PIXELSIZE nWidth * nHeight  
        const int Table_fv1[256] = { -180, -179, -177, -176, -174, -173, -172, -170, -169, -167, -166, -165, -163, -162, -160, -159, -158, -156, -155, -153, -152, -151, -149, -148, -146, -145, -144, -142, -141, -139, -138, -137, -135, -134, -132, -131, -130, -128, -127, -125, -124, -123, -121, -120, -118, -117, -115, -114, -113, -111, -110, -108, -107, -106, -104, -103, -101, -100, -99, -97, -96, -94, -93, -92, -90, -89, -87, -86, -85, -83, -82, -80, -79, -78, -76, -75, -73, -72, -71, -69, -68, -66, -65, -64, -62, -61, -59, -58, -57, -55, -54, -52, -51, -50, -48, -47, -45, -44, -43, -41, -40, -38, -37, -36, -34, -33, -31, -30, -29, -27, -26, -24, -23, -22, -20, -19, -17, -16, -15, -13, -12, -10, -9, -8, -6, -5, -3, -2, 0, 1, 2, 4, 5, 7, 8, 9, 11, 12, 14, 15, 16, 18, 19, 21, 22, 23, 25, 26, 28, 29, 30, 32, 33, 35, 36, 37, 39, 40, 42, 43, 44, 46, 47, 49, 50, 51, 53, 54, 56, 57, 58, 60, 61, 63, 64, 65, 67, 68, 70, 71, 72, 74, 75, 77, 78, 79, 81, 82, 84, 85, 86, 88, 89, 91, 92, 93, 95, 96, 98, 99, 100, 102, 103, 105, 106, 107, 109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 124, 126, 127, 129, 130, 131, 133, 134, 136, 137, 138, 140, 141, 143, 144, 145, 147, 148, 150, 151, 152, 154, 155, 157, 158, 159, 161, 162, 164, 165, 166, 168, 169, 171, 172, 173, 175, 176, 178 };
        const int Table_fv2[256] = { -92, -91, -91, -90, -89, -88, -88, -87, -86, -86, -85, -84, -83, -83, -82, -81, -81, -80, -79, -78, -78, -77, -76, -76, -75, -74, -73, -73, -72, -71, -71, -70, -69, -68, -68, -67, -66, -66, -65, -64, -63, -63, -62, -61, -61, -60, -59, -58, -58, -57, -56, -56, -55, -54, -53, -53, -52, -51, -51, -50, -49, -48, -48, -47, -46, -46, -45, -44, -43, -43, -42, -41, -41, -40, -39, -38, -38, -37, -36, -36, -35, -34, -33, -33, -32, -31, -31, -30, -29, -28, -28, -27, -26, -26, -25, -24, -23, -23, -22, -21, -21, -20, -19, -18, -18, -17, -16, -16, -15, -14, -13, -13, -12, -11, -11, -10, -9, -8, -8, -7, -6, -6, -5, -4, -3, -3, -2, -1, 0, 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24, 25, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 40, 41, 42, 42, 43, 44, 45, 45, 46, 47, 47, 48, 49, 50, 50, 51, 52, 52, 53, 54, 55, 55, 56, 57, 57, 58, 59, 60, 60, 61, 62, 62, 63, 64, 65, 65, 66, 67, 67, 68, 69, 70, 70, 71, 72, 72, 73, 74, 75, 75, 76, 77, 77, 78, 79, 80, 80, 81, 82, 82, 83, 84, 85, 85, 86, 87, 87, 88, 89, 90, 90 };
        const int Table_fu1[256] = { -44, -44, -44, -43, -43, -43, -42, -42, -42, -41, -41, -41, -40, -40, -40, -39, -39, -39, -38, -38, -38, -37, -37, -37, -36, -36, -36, -35, -35, -35, -34, -34, -33, -33, -33, -32, -32, -32, -31, -31, -31, -30, -30, -30, -29, -29, -29, -28, -28, -28, -27, -27, -27, -26, -26, -26, -25, -25, -25, -24, -24, -24, -23, -23, -22, -22, -22, -21, -21, -21, -20, -20, -20, -19, -19, -19, -18, -18, -18, -17, -17, -17, -16, -16, -16, -15, -15, -15, -14, -14, -14, -13, -13, -13, -12, -12, -11, -11, -11, -10, -10, -10, -9, -9, -9, -8, -8, -8, -7, -7, -7, -6, -6, -6, -5, -5, -5, -4, -4, -4, -3, -3, -3, -2, -2, -2, -1, -1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43 };
        const int Table_fu2[256] = { -227, -226, -224, -222, -220, -219, -217, -215, -213, -212, -210, -208, -206, -204, -203, -201, -199, -197, -196, -194, -192, -190, -188, -187, -185, -183, -181, -180, -178, -176, -174, -173, -171, -169, -167, -165, -164, -162, -160, -158, -157, -155, -153, -151, -149, -148, -146, -144, -142, -141, -139, -137, -135, -134, -132, -130, -128, -126, -125, -123, -121, -119, -118, -116, -114, -112, -110, -109, -107, -105, -103, -102, -100, -98, -96, -94, -93, -91, -89, -87, -86, -84, -82, -80, -79, -77, -75, -73, -71, -70, -68, -66, -64, -63, -61, -59, -57, -55, -54, -52, -50, -48, -47, -45, -43, -41, -40, -38, -36, -34, -32, -31, -29, -27, -25, -24, -22, -20, -18, -16, -15, -13, -11, -9, -8, -6, -4, -2, 0, 1, 3, 5, 7, 8, 10, 12, 14, 15, 17, 19, 21, 23, 24, 26, 28, 30, 31, 33, 35, 37, 39, 40, 42, 44, 46, 47, 49, 51, 53, 54, 56, 58, 60, 62, 63, 65, 67, 69, 70, 72, 74, 76, 78, 79, 81, 83, 85, 86, 88, 90, 92, 93, 95, 97, 99, 101, 102, 104, 106, 108, 109, 111, 113, 115, 117, 118, 120, 122, 124, 125, 127, 129, 131, 133, 134, 136, 138, 140, 141, 143, 145, 147, 148, 150, 152, 154, 156, 157, 159, 161, 163, 164, 166, 168, 170, 172, 173, 175, 177, 179, 180, 182, 184, 186, 187, 189, 191, 193, 195, 196, 198, 200, 202, 203, 205, 207, 209, 211, 212, 214, 216, 218, 219, 221, 223, 225 };
        int len = channels * nWidth * nHeight;
        if (!pYuvBuf || !pRgbBuf)
            return false;
        const long nYLen = long(PIXELSIZE);
        const int nHfWidth = (nWidth >> 1);
        if (nYLen<1 || nHfWidth<1)
            return false;
        // Y data  
        unsigned char* yData = pYuvBuf;
        // v data  
        unsigned char* vData = &yData[nYLen];
        // u data  
        unsigned char* uData = &vData[nYLen >> 2];
        if (!uData || !vData)
            return false;
        int rgb[3];
        int i, j, m, n, x, y, pu, pv, py, rdif, invgdif, bdif;
        m = -nWidth;
        n = -nHfWidth;
        bool addhalf = true;
        for (y = 0; y<nHeight; y++) {
            m += nWidth;
            if (addhalf) {
                n += nHfWidth;
                addhalf = false;
            }
            else {
                addhalf = true;
            }
            for (x = 0; x<nWidth; x++) {
                i = m + x;
                j = n + (x >> 1);
                py = yData[i];
                // search tables to get rdif invgdif and bidif  
                rdif = Table_fv1[vData[j]];    // fv1  
                invgdif = Table_fu1[uData[j]] + Table_fv2[vData[j]]; // fu1+fv2  
                bdif = Table_fu2[uData[j]]; // fu2       
                rgb[0] = py + rdif;    // R  
                rgb[1] = py - invgdif; // G  
                rgb[2] = py + bdif;    // B  
                j = nYLen - nWidth - m + x;
                i = (j << 1) + j;
                // copy this pixel to rgb data  
                for (j = 0; j<3; j++)
                {
                    if (rgb[j] >= 0 && rgb[j] <= 255) {
                        pRgbBuf[i + j] = rgb[j];
                    }
                    else {
                        pRgbBuf[i + j] = (rgb[j] < 0) ? 0 : 255;
                    }
                }
            }
        }
        return true;
    }

     

    方法二逐像素转换法:

    void AVFrame2Img(AVFrame *pFrame, cv::Mat& img)
    {
        int frameHeight = pFrame->height;
        int frameWidth = pFrame->width;
        int channels = 3;
        //输出图像分配内存
        img = cv::Mat::zeros(frameHeight, frameWidth, CV_8UC3);
    
        //创建保存yuv数据的buffer
        uchar* pDecodedBuffer = (uchar*)malloc(frameHeight*frameWidth * sizeof(uchar)*channels);
    
        //从AVFrame中获取yuv420p数据,并保存到buffer
        int i, j, k;
        //拷贝y分量
        for (i = 0; i < frameHeight; i++)
        {
            memcpy(pDecodedBuffer + frameWidth*i,
                pFrame->data[0] + pFrame->linesize[0] * i,
                frameWidth);
        }
        //拷贝u分量
        for (j = 0; j < frameHeight / 2; j++)
        {
            memcpy(pDecodedBuffer + frameWidth*i + frameWidth / 2 * j,
                pFrame->data[1] + pFrame->linesize[1] * j,
                frameWidth / 2);
        }
        //拷贝v分量
        for (k = 0; k < frameHeight / 2; k++)
        {
            memcpy(pDecodedBuffer + frameWidth*i + frameWidth / 2 * j + frameWidth / 2 * k,
                pFrame->data[2] + pFrame->linesize[2] * k,
                frameWidth / 2);
        }
    
        //将buffer中的yuv420p数据转换为RGB;
        Yuv420p2Rgb32(pDecodedBuffer, img.data, frameWidth, frameHeight);
    
        //释放buffer
        free(pDecodedBuffer);
    }

    子函数Yuv420p2Rgb32( )函数实现yuv420p到RGB32的转换

    void Yuv420p2Rgb32(const uchar *yuvBuffer_in, const uchar *rgbBuffer_out, int width, int height)
    {
        uchar *yuvBuffer = (uchar *)yuvBuffer_in;
        uchar *rgb32Buffer = (uchar *)rgbBuffer_out;
    
        int channels = 3;
    
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                int index = y * width + x;
    
                int indexY = y * width + x;
                int indexU = width * height + y / 2 * width / 2 + x / 2;
                int indexV = width * height + width * height / 4 + y / 2 * width / 2 + x / 2;
    
                uchar Y = yuvBuffer[indexY];
                uchar U = yuvBuffer[indexU];
                uchar V = yuvBuffer[indexV];
                
                int R = Y + 1.402 * (V - 128);
                int G = Y - 0.34413 * (U - 128) - 0.71414*(V - 128);
                int B = Y + 1.772*(U - 128);
                R = (R < 0) ? 0 : R;
                G = (G < 0) ? 0 : G;
                B = (B < 0) ? 0 : B;
                R = (R > 255) ? 255 : R;
                G = (G > 255) ? 255 : G;
                B = (B > 255) ? 255 : B;
    
                rgb32Buffer[(y*width + x)*channels + 2] = uchar(R);
                rgb32Buffer[(y*width + x)*channels + 1] = uchar(G);
                rgb32Buffer[(y*width + x)*channels + 0] = uchar(B);
            }
        }
    }
  • 相关阅读:
    java 在线网络考试系统源码 springboot mybaits vue.js 前后分离跨域
    springboot 整合flowable 项目源码 mybiats vue.js 前后分离 跨域
    flowable Springboot vue.js 前后分离 跨域 有代码生成器 工作流
    Flowable 工作流 Springboot vue.js 前后分离 跨域 有代码生成器
    java 企业 网站源码 后台 springmvc SSM 前台 静态化 代码生成器
    java 进销存 商户管理 系统 管理 库存管理 销售报表springmvc SSM项目
    基于FPGA的电子计算器设计(中)
    基于FPGA的电子计算器设计(上)
    FPGA零基础学习:SPI 协议驱动设计
    Signal tap 逻辑分析仪使用教程
  • 原文地址:https://www.cnblogs.com/riddick/p/7719298.html
Copyright © 2011-2022 走看看