opencv读取yuv序列到opencv 1.0 图片格式IplImage

两种方式,一种通过cvCvtColor,一种通过自己写的转换子函数

出来的bmp完全相同


#include <highgui.h>

#include "cv.h"
#include <stdio.h>


#define MR(Y,U,V) (Y + (1.403)*(V-128))


#define MG(Y,U,V) (Y - (0.344) * (U-128) - (0.714) * (V-128) ) 


#define MB(Y,U,V) (Y + ((1.773) * (U-128)))




#define nWidth 1280
#define nHeight 720
#define nSize  nWidth*nHeight*3/2
#define FrameSize nWidth*nHeight*3/2




void YUV420_C_RGB (char* pYUV, unsigned char* pRGB, int height, int width)
{
    char* pY = pYUV;
    char* pU = pYUV + height*width;
    char* pV = pU + (height*width / 4);




    unsigned char* pBGR = NULL;
    unsigned char R = 0;
    unsigned char G = 0;
    unsigned char B = 0;
    char Y = 0;
    char U = 0;
    char V = 0;
    double tmp = 0;
    for (int i = 0; i < height; ++i)
    {
        for (int j = 0; j < width; ++j)
        {
            pBGR = pRGB + i*width * 3 + j * 3;


            Y = *(pY + i*width + j);
            U = *pU;
            V = *pV;


            //B  
            tmp = MB (Y, U, V);
            //B = (tmp > 255) ? 255 : (char)tmp;  
            //B = (B<0) ? 0 : B;  
            B = (unsigned char) tmp;
            //G  
            tmp = MG (Y, U, V);
            //G = (tmp > 255) ? 255 : (char)tmp;  
            // G = (G<0) ? 0 : G;  
            G = (unsigned char) tmp;
            //R  
            tmp = MR (Y, U, V);
            //R = (tmp > 255) ? 255 : (char)tmp;  
            //R = (R<0) ? 0 : R;  
            R = (unsigned char) tmp;




            *pBGR = R;
            *(pBGR + 1) = G;
            *(pBGR + 2) = B;




            if (i % 2 == 0 && j % 2 == 0)
            {
                *pU++;
                //*pV++;  
            }
            else
            {
                if (j % 2 == 0)
                {
                    *pV++;
                }
            }
        }


    }
}














int main (int argc, char* argv [])
{


    FILE *f;
    if (!(f = fopen ("i:\\in_to_tree_420_720p50.yuv", "rb")))
    {
        printf ("file open error!");
    }




    // calculate the frame num
    fseek (f, 0, SEEK_END);
    int frame_count = 0;
    long file_size = 0;
    frame_count = (int) ((int) ftell (f) / ((nWidth * nHeight * 3) / 2));  // ftell 用于求文件大小
    printf ("frame num is %d \n", frame_count);
    printf ("file length is   %d", ftell (f));




    fseek (f, 0, SEEK_SET);//文件内位置定位到文件头


    IplImage *rgbimg = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 3);
    IplImage *image = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 3);
    IplImage *yimg = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 1);
    IplImage *uimg = cvCreateImageHeader (cvSize (nWidth / 2, nHeight / 2), IPL_DEPTH_8U, 1);
    IplImage *vimg = cvCreateImageHeader (cvSize (nWidth / 2, nHeight / 2), IPL_DEPTH_8U, 1);
    IplImage *uuimg = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 1);
    IplImage *vvimg = cvCreateImage (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 1);


    //----------------------------------------------------------------------读取yuv文件的y部分 类似于播放器效果 
    char *pBuf = new char[nWidth*nHeight * 3 / 2];
    int pos = 0;
    //     for (int i = 0; i < frame_count - 1; i++)
    //     {
    int i = 1;
    printf ("frame  %d/%d\n", i, frame_count);
    fseek (f, pos, SEEK_SET);
    fread (pBuf, 1, FrameSize, f);
    cvSetData (yimg, pBuf, nWidth);
    cvSetData (vimg, pBuf + nWidth * nHeight, nWidth / 2);
    cvSetData (uimg, pBuf + long (nWidth * nHeight * 1.25), nWidth / 2);
    cvResize (uimg, uuimg, CV_INTER_NN);
    cvResize (vimg, vvimg, CV_INTER_NN);
    cvMerge (yimg, vvimg, uuimg, NULL, image);                          //yuv输入 但是420 iyuv 是yvu
    cvCvtColor (image, rgbimg, CV_YCrCb2RGB);
    cvNamedWindow ("RGB");
    cvShowImage ("RGB", rgbimg);
    cvSaveImage ("m:\\RGB.bmp", rgbimg);
    cvWaitKey (10);
    pos += FrameSize;
    //    }


    cvDestroyWindow ("RGB");






    unsigned char* pRGB = NULL;


    pRGB = (unsigned char*) malloc (nSize*sizeof (unsigned char*) * 2);


    YUV420_C_RGB (pBuf, pRGB, nWidth, nHeight);


    IplImage *img;
    img = cvCreateImageHeader (cvSize (nWidth, nHeight), IPL_DEPTH_8U, 3);
    cvSetData (img, pRGB, nWidth * 3);
    cvSaveImage ("m:\\rgb-1.bmp", rgbimg);




    //cvReleaseImage (&yimg);
    delete []pBuf;


    fclose (f);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV可以通过cv::VideoCapture类读取常见的视频文件格式,如.avi和.mp4等。然而,在某些应用场景中,我们需要读取yuv格式的原始视频数据,例如压缩算法的研究或图像处理的探索。在这种情况下,OpenCV提供了一个cv::VideoCapture类,可以读取yuv格式的视频数据。 使用cv::VideoCapture::open()打开yuv文件时,需要指定文件的路径,并设置四个参数:视频宽度、视频高度、帧率和视频格式。对于yuv文件,格式通常是YUV 4:2:0或YUV 4:2:2。例如: cv::VideoCapture capture; std::string filename = "path/to/yuvfile.yuv"; int width = 1920; int height = 1080; int fps = 30; int format = CV_8UC1; // YUV格式通常为单通道 bool success = capture.open(filename, cv::CAP_ANY); if (!success) { std::cerr << "Error: Failed to open the video file." << std::endl; return -1; } 读取yuv文件时,每个帧通常由Y、U和V三个分量组成。因此,我们需要使用不同的函数读取不同的分量。例如: cv::Mat yuv_image; cv::Mat y_plane(height, width, format); cv::Mat u_plane(height / 2, width / 2, format); cv::Mat v_plane(height / 2, width / 2, format); while (capture.read(yuv_image)) { // 分离y、u、v分量 cv::extractChannel(yuv_image, y_plane, 0); cv::extractChannel(yuv_image, u_plane, 1); cv::extractChannel(yuv_image, v_plane, 2); // 处理y分量 // ... // 将分量合并以重构原始图像 cv::Mat bgr_image; cv::merge(std::vector<cv::Mat>{y_plane, u_plane, v_plane}, bgr_image); // 显示图像 cv::imshow("Video", bgr_image); cv::waitKey(1); } 需要注意的是,由于yuv文件的像素值通常不是8位,而是10位,12位等,因此需要根据实际情况对像素值进行缩放和偏移。此外,在将Y、U和V三个分量合并以重构原始图像之前,需要将U和V分量上采样到与Y分量相同的分辨率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值