opencv视频采集rgb to yuv

// ConsoleApplication2.cpp : Defines the entry point for the console application.
//


#include "stdafx.h"
#include <opencv2\opencv.hpp>
using namespace cv;
using namespace std;
FILE* pFile;




IplImage* convert(IplImage* pImage)
{
int nWidth=pImage->width;
int nHeight=pImage->height;
IplImage* yimg = cvCreateImage(cvSize(nWidth, nHeight),IPL_DEPTH_8U,3);  
    //IplImage* uimg = cvCreateImageHeader(cvSize(nWidth/2, nHeight/2),IPL_DEPTH_8U,1);  
    //IplImage* vimg = cvCreateImageHeader(cvSize(nWidth/2, nHeight/2),IPL_DEPTH_8U,1);  


cvCvtColor(pImage,yimg,CV_BGR2YUV);
cout<<"bgr:"<<pImage->nSize<<" "<<pImage->channelSeq<<"  "<<pImage->dataOrder<<"  "<<pImage->depth<<"  "<<pImage->imageSize<<" "<<pImage->nChannels<<" "<<pImage->widthStep<<" "<<pImage->origin<<endl;
cout<<"yuv:"<<yimg->nSize<<" "<<yimg->channelSeq<<"  "<<yimg->dataOrder<<"  "<<yimg->depth<<"  "<<yimg->imageSize<<" "<<yimg->nChannels<<" "<<yimg->widthStep<<" "<<yimg->origin<<endl;


return yimg;
}




IplImage* RgbToYUV420(IplImage* pImage)
{
//cout<<"number of channels:"<<pImage->nChannels<<"  width step:"<<pImage->widthStep<<endl;
cout<<"width:"<<pImage->width<<"  height:"<<pImage->height<<endl;
//cout<<"order of data:"<<pImage->dataOrder<<endl;
//cout<<"channel sequence:"<<pImage->channelSeq<<endl;*/


int width=pImage->width;
int height=pImage->height;
int yuvSize=width*height*3/2;
char* pRgbBuf=pImage->imageData;
char* pYBuf,*pUBuf,*pVBuf;
char* pYUVBuf;


pYUVBuf=(char*)malloc(yuvSize);
pYBuf=pYUVBuf;
memset(pYBuf,0,yuvSize);
//pUBuf=pYBuf+width*height;


//yuv格式按YUV排列
pUBuf=pYBuf+width*height;
pVBuf=pUBuf+width*height/4;



unsigned char r,g,b;
unsigned char y,u,v;

    
for(int i=0;i<height;i++)
for(int j=0;j<width;j++)
{
b=*(pRgbBuf);
g=*(pRgbBuf+1);
r=*(pRgbBuf+2);
/*y = (unsigned char)(  0.299* r + 0.587* g +  0.114 * b )   ;            
            u = (unsigned char)( -0.169 * r -  0.332 * g + 0.500 * b + 128)  ;            
            v = (unsigned char)( 0.500 * r +0.419 * g -  0.0813 * b + 128);  */

//这才是正确的公式????
y=uchar(0.257*r + 0.504*g + 0.098*b + 16); 
u=uchar(-0.148*r - 0.291*g + 0.439*b + 128);
v=uchar(0.439*r - 0.368*g - 0.071*b + 128);


/*y=0.299*r + 0.587*g + 0.114*b;
            u=(r-y)*0.713 + 128;
            v=(b-y)*0.564 + 128;*/




if(y>255)y=255;
else if(y<0)y=0;
if(u>255)u=255;
else if(u<0)u=0;
if(v>255)v=255;
else if(v<0)v=0;
*(pYBuf++)=y;
/**(pVBuf++)=v;
*(pUBuf++)=u;*/

pRgbBuf+=3;
/**(pRgbBuf++)=y;
*(pRgbBuf++)=v;
*(pRgbBuf++)=u;*/



if(i%2==0&&j%2==0)
{
//对uv取样
*(pVBuf++)=v;
*(pUBuf++)=u;
}
}

//pImage->imageData=pYUVBuf;
/*IplImage* yimg = cvCreateImageHeader(cvSize(width, height),IPL_DEPTH_8U,1);  
cvSetData(yimg,pYUVBuf,width);*/



//pImage->imageSize=yuvSize;

//fprintf(pFile,"%s",pYUVBuf);
fwrite(pYUVBuf,1,yuvSize,pFile);

//pImage->imageData=pYBuf;
//pImage->imageDataOrigin=pYBuf;
/*strcpy_s(pImage->channelSeq,"YVU");
pImage->dataOrder=1;*/

return pImage;
}
void JPG2YUV(IplImage* pImage)
{
    unsigned char yBuffer[640*480];
    IplImage *y=cvCreateImageHeader(cvSize(640,480),IPL_DEPTH_8U,1);
    y->imageData=(char*)&yBuffer[0];
    y->widthStep=640;
    y->origin=IPL_ORIGIN_TL;
    
    unsigned char uBuffer[640*480/4];
    IplImage *u=cvCreateImageHeader(cvSize(640/2,480/2),IPL_DEPTH_8U,1);
    u->imageData=(char*)&uBuffer[0];
    u->widthStep=640/2;
    u->origin=IPL_ORIGIN_TL;
    
    unsigned char vBuffer[640*480/4];
    IplImage *v=cvCreateImageHeader(cvSize(640/2,480/2),IPL_DEPTH_8U,1);
    v->imageData=(char*)&vBuffer[0];
    v->widthStep=640/2;
    v->origin=IPL_ORIGIN_TL;
    
    IplImage *uOrigin=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
    IplImage *vOrigin=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
    
    FILE *yuv;
fopen_s(&yuv,"frame.yuv","a");
    
    //for (int i=0;i<263;i++) {
        //char loadname[200];
        //sprintf(loadname,imageFilename,i);
        
   IplImage *frame=pImage;
      //  printf("%d start\n",i);
        cvCvtColor(frame,frame,CV_BGR2YUV);


        cvSplit(frame,y,uOrigin,vOrigin,NULL);
        cvResize(uOrigin,u);
        cvResize(vOrigin,v);
        fwrite(yBuffer,1,640*480,yuv);
        fwrite(uBuffer,1,640*480/4,yuv);
        fwrite(vBuffer,1,640*480/4,yuv);
        //printf("%d done\n",i);
      //  cvReleaseImage(&frame);
        
   // }
    
    fclose(yuv);
}




int main()
{
int frameWidth=320;
int frameHeight=240;
IplImage* pSaveFrame=NULL; 


//CvCapture* capture=cvCaptureFromAVI("camera.avi");
CvCapture* capture=cvCaptureFromCAM(-1);
cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_WIDTH, frameWidth);//设置视频流的帧宽度
cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_HEIGHT, frameHeight);//设置视频流的帧高度  
CvVideoWriter* video=NULL;
IplImage* frame=NULL;
//char filename[20];
int i=0;
//int p[3];  
 //  p[0] = CV_IMWRITE_JPEG_QUALITY;  
 //  p[1] = 10;  //质量值  
 //  p[2] = 0;  




int n;
if(!capture) //如果不能打开摄像头给出警告
{
cout<<"Can not open the camera."<<endl;
return -1;
}
else
{
frame=cvQueryFrame(capture); //首先取得摄像头中的一帧
video=cvCreateVideoWriter("camera.yuv",CV_FOURCC('I','4','2','0'),15,
cvSize(frameWidth,frameHeight)); //创建CvVideoWriter对象并分配空间
//保存的文件名为camera.avi,编码要在运行程序时选择,大小就是摄像头视频的大小,帧频率是15,CV_FOURCC(I,4,2,0)表示yuv420编码
if(video) //如果能创建CvVideoWriter对象则表明成功
{
cout<<"VideoWriter has created."<<endl;
}
cvNamedWindow("Camera Video",1); //新建一个窗口
fopen_s(&pFile,"yuvvideo.yuv","wb");
while(1)
{
frame=cvQueryFrame(capture); //从CvCapture中获得一帧
 
if(!frame)
{
cout<<"Can not get frame from the capture."<<endl;
break;
}




n=cvWriteFrame(video,frame); //判断是否写入成功,如果返回的是1,表示写入成功
cout<<n<<endl;
//frame=convert(frame);
frame=RgbToYUV420(frame);
//JPG2YUV(frame);











cvShowImage("Camera Video",frame); //显示视频内容的图片


//pSaveFrame=cvCreateImage(cvSize(frame->width,frame->height),frame->depth,frame->nChannels); 
//sprintf_s(filename,"%d.jpg",i);
//i++;
 //     cvResize(frame,pSaveFrame,CV_INTER_LINEAR);  
   //        cvSaveImage(filename,pSaveFrame,p);  
   //        cvReleaseImage(&pSaveFrame); 


if(cvWaitKey(1)>0) break; //有其他键盘响应,则退出
}
fclose(pFile);
cvReleaseVideoWriter(&video);
cvReleaseCapture(&capture);
cvDestroyWindow("Camera Video");
}
return 0;
}

转载于:https://my.oschina.net/gujianhan/blog/163259

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值