【genius_platform软件平台开发】第七十五讲:YUY2转RGB24实现源码

该博客介绍了如何将YUV422格式的伪彩图像数据转换为RGB24或BGR24格式。提供了C++实现的转换源码,包括`Yuy2FrameProcess`类及其`yuy2ToRgb24Convert`和`yuy2ToBgr24Convert`方法,用于处理红外传感器的数据流。测试表明,转换后的文件在软件平台上播放显示正确。
摘要由CSDN通过智能技术生成

YUY2转RGB24实现源码

  • 今日在对接大力ir红外sensor时,需要对前半部分YUV422的伪彩图像数据进行RGB24转换,源码可以实现转RGB24或者BGR24,部分函数可以删除掉,只关注重点转换函数即可

1. 实现源码

  • Yuy2FrameProcess.h
#ifndef __YUY2_FRAME_PROCESS_H__
#define __YUY2_FRAME_PROCESS_H__

#include "OLeiIrFrameDef.h"
#include "Stream/GpIrFrameProcess.h"

//
// yuv420数据流处理类
class CYuy2FrameProcess : public CGpIrFrameProcess
{
public:
    CYuy2FrameProcess();
    virtual ~CYuy2FrameProcess();

    // yuy2图像数据到rgb24图像数据转换
    INT32 yuy2ToRgb24Convert(unsigned char* pSrc, unsigned char* pDst, int nImageWidth, int nImageHeight);
    // yuy2图像数据到bgr24图像数据转换
    INT32 yuy2ToBgr24Convert(unsigned char* pSrc, unsigned char* pDst, int nImageWidth, int nImageHeight);

public:
	// 帧处理函数(目前与IR流处理没有差异)
    virtual INT32 ProcessFrame(void* pData = NULL);
};
#endif //__YUY2_FRAME_PROCESS_H__
  • Yuy2FrameProcess.cpp
#include "Yuy2FrameProcess.h"
#include "Base/Thread/GpFrameProcessThread.h"
#include "Stream/GpFrameProcessCenter.h"
#include "Stream/Gpts/Yuy2FrameDef.h"

//
//
CYuy2FrameProcess::CYuy2FrameProcess()
{
    LOGMSG("CYuy2FrameProcess::CYuy2FrameProcess");

    // 等待耗时统计
    TimePoint nTotalCostTm = currentTime();

    // 设置type
    this->setType(FrameProcessType_Yuv420);

    LOGMSG("CYuy2FrameProcess::CYuy2FrameProcess is suc... nTotalCostTm=[%u]", (currentTime() - nTotalCostTm).count());
}

//
//
CYuy2FrameProcess::~CYuy2FrameProcess()
{
    LOGMSG("CYuy2FrameProcess::~CYuy2FrameProcess");

    // 等待耗时统计
    TimePoint nTotalCostTm = currentTime();

    // 释放线程资源
    this->releaseFrameProcThread();

    LOGMSG("CYuy2FrameProcess::~CYuy2FrameProcess is suc... nTotalCostTm=[%llu]", (currentTime() - nTotalCostTm).count());
}

//
// 处理数据流
INT32 CYuy2FrameProcess::ProcessFrame(void *pData)
{
    CGpFrameProcessThread* pThread = static_cast<CGpFrameProcessThread*>(pData);
    CHECKI(pThread);
    CHECKF(m_pFrameProcessCenter);

    CGpFrame* pFrame = this->takeFirst();
    if (!pFrame || pFrame->isEmpty())
    {
        // 阻塞等待,后续有空时测试下效率
        /*
        * 1.锁导致上下文切换开销很大,导致帧率30~10帧
        */
        //std::unique_lock<std::mutex> ulock(m_Mtx);
        //m_Cond.wait(ulock);
        msSleep(10);
        return ReturnCode_Empty;
    }

    GpFrameType frameType = pFrame->getFrameType();
    CHECKI(frameType == FRAME_TYPE_EXT_IR);

    int nConvertFormat = CONVERT_FORMAT_RGB24;
    // 计算所需内存大小(w * h * 3) 每个像素点3通道
    int nRgb24Size = pFrame->getWidth() * pFrame->getHeight() * 3;
     // 构造ir数据帧
    CGpFrame* pRgb24Frame = new CGpFrame(nRgb24Size);
    if (pRgb24Frame == NULL)
    {
        LOGERROR("CYuy2FrameProcess::ProcessFrame new CGpFrame pRgb24Frame is NULL");
        goto delete_frame;
    }
    pRgb24Frame->setBlockId(pFrame->getBlockId());
    pRgb24Frame->setNetCode(pFrame->getNetCode());   
    pRgb24Frame->setCompressType(DATA_COMPRESS_RAW);
    pRgb24Frame->setFrameType(FRAME_TYPE_RGB24);
    pRgb24Frame->setWidth(pFrame->getWidth());
    pRgb24Frame->setHeight(pFrame->getHeight());
    pRgb24Frame->setChannelIndex(pFrame->getChannelIndex());
    pRgb24Frame->setFrameCount(pFrame->getFrameCount());
    pRgb24Frame->setTimestamp(pFrame->getTimestamp());

    // 生产rgb或者bgr
    if (nConvertFormat == CONVERT_FORMAT_RGB24)
    {
        // yuy2图像数据到rgb24图像数据转换
        this->yuy2ToRgb24Convert((unsigned char*)pFrame->getData(), (unsigned char*)pRgb24Frame->getData(), pFrame->getWidth(), pFrame->getHeight());
    }
    else if (nConvertFormat == CONVERT_FORMAT_BGR24)
    {
        // yuy2图像数据到bgr24图像数据转换
        this->yuy2ToRgb24Convert((unsigned char*)pFrame->getData(), (unsigned char*)pRgb24Frame->getData(), pFrame->getWidth(), pFrame->getHeight());
    }
    else
    {
        LOGERROR("CYuy2FrameProcess::yuy2ToRgb24Convert nConvertFormat is error... nConvertFormat=[%d]", nConvertFormat);
        goto delete_frame;
    }


    CGpFrameProcessCenter* pFrameProcessCenter = dynamic_cast<CGpFrameProcessCenter*>(this->getFrameProcessCenter());
    if (pFrameProcessCenter == NULL)
    {
        LOGERROR("CYuy2FrameProcess::ProcessFrame pFrameProcessCenter is NULL");
        goto delete_frame;
    }
    // 送数据处理
    pFrameProcessCenter->outputFrame(pRgb24Frame);

delete_frame:
    // 释放pIrFrame
    SAFE_DELETE(pFrame);
    // 释放pRgb24Frame
    SAFE_DELETE(pRgb24Frame);

    return ReturnCode_Success;
}

//
// yuy2图像数据到rgb24图像数据转换
// 原文链接:https://blog.csdn.net/tong5956/article/details/112037131
INT32 CYuy2FrameProcess::yuy2ToRgb24Convert(unsigned char* pSrc, unsigned char* pDst, int nImageWidth, int nImageHeight)
{
    CHECKI(pSrc);
    CHECKI(pDst);
    CHECKI(nImageWidth > 0);
    CHECKI(nImageHeight > 0);

    // 获取yuyv数据指针
    unsigned char* pYuyvData = pSrc;

    int z = 0;
    int i = 0;
    int j = 0;

    for (i = 0; i < nImageHeight; i++) 
    {
        for (j = 0; j < nImageWidth; j++) 
        {
            int r, g, b;
            int y, u, v;

            // YUYV格式
            if (!z)
            {
                y = pYuyvData[0] << 8;
            }
            else
            {
                y = pYuyvData[2] << 8;
            }

            u = pYuyvData[1] - 128;
            v = pYuyvData[3] - 128;

            // yuv分量到rgb分量转换
            r = (y + (359 * v)) >> 8;
            g = (y - (88 * u) - (183 * v)) >> 8;
            b = (y + (454 * u)) >> 8;

            // 如果溢出>255或者小于0
            r = (r > 255) ? 255 : ((r < 0) ? 0 : r);
            g = (g > 255) ? 255 : ((g < 0) ? 0 : g);
            b = (b > 255) ? 255 : ((b < 0) ? 0 : b);

            // 转换出来是rgb图像
            *pDst++ = r;
            *pDst++ = g;
            *pDst++ = b;

            // 执行0/1重置和数据指针偏移
            if (z++) 
            {
                z = 0;
                pYuyvData += 4;
            }
        }
    }

    return ReturnCode_Success;
}


//
// yuy2图像数据到bgr24图像数据转换
INT32 CYuy2FrameProcess::yuy2ToBgr24Convert(unsigned char* pSrc, unsigned char* pDst, int nImageWidth, int nImageHeight)
{
    CHECKI(pSrc);
    CHECKI(pDst);
    CHECKI(nImageWidth > 0);
    CHECKI(nImageHeight > 0);

    // 获取yuyv数据指针
    unsigned char* pYuyvData = pSrc;

    int z = 0;
    int i = 0;
    int j = 0;

    for (i = 0; i < nImageHeight; i++)
    {
        for (j = 0; j < nImageWidth; j++)
        {
            int r, g, b;
            int y, u, v;

            // YUYV格式
            if (!z)
            {
                y = pYuyvData[0] << 8;
            }
            else
            {
                y = pYuyvData[2] << 8;
            }

            u = pYuyvData[1] - 128;
            v = pYuyvData[3] - 128;

            // yuv分量到rgb分量转换
            r = (y + (359 * v)) >> 8;
            g = (y - (88 * u) - (183 * v)) >> 8;
            b = (y + (454 * u)) >> 8;

            // 如果溢出>255或者小于0
            r = (r > 255) ? 255 : ((r < 0) ? 0 : r);
            g = (g > 255) ? 255 : ((g < 0) ? 0 : g);
            b = (b > 255) ? 255 : ((b < 0) ? 0 : b);

            // 转换出来是bgr图像
            *pDst++ = b;
            *pDst++ = g;
            *pDst++ = r;

            // 执行0/1重置和数据指针偏移
            if (z++)
            {
                z = 0;
                pYuyvData += 4;
            }
        }
    }

    return ReturnCode_Success;
}

2. 测试文件

  • 执行程序生产2个test_rgb24.bin和test_bgr24.bin文件,使用软件平台离线工具播放显示正确无误;
    在这里插入图片描述
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隨意的風

如果你觉得有帮助,期待你的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值