因研究需要,这几天想把Opecv获取的视频帧转到OSG中作为纹理背景输出,关键的一步就是Opencv帧图像的传递。
那么问题来了:Opencv存放图像数据的格式和OSG的差异大吗?
因为自己也是个新手,首先找到了
osg抓帧放到openCV里
http://wenku.baidu.com/link?url=PXeAHmmV7vyA7s2fEK30_gEQvJzpHA9uDl9y1YIUHstCXCj_HKOTGjs_5PMnesuFDocCapTlBOyp5UjzWDu0LE7VayoDq98X3jzpPpyiQCm
原作者无从可考,但是留下了一句重要的代码:
memcpy((unsigned char*)pIplImg->imageData,pCImg->data(),pCImg->getImageSizeInBytes());
给出的信息就是两者数据转换,只要知道长和宽,以及像素数据的指针位置就可以了。完整的代码如下:
IplImage * CImage2IplImage ( osg :: ref_ptr < osg :: Image > pCImg , IplImage * pIplImg ){//输出图像设置pIplImg -> origin = IPL_ORIGIN_BL ;//输入图像信息memcpy (( unsigned char * ) pIplImg -> imageData , pCImg -> data (), pCImg -> getImageSizeInBytes ());//将RGB存储为BGRunsigned int temp = 0 ;for ( int y = 0 ; y < pIplImg -> height ; y ++ ){uchar * ptr = ( uchar * )( pIplImg -> imageData + y * pIplImg -> widthStep );for ( int x = 0 ; x < pIplImg -> width ; x ++ ){temp = ptr [ 3 * x ]; //保存原始的R值ptr [ 3 * x ] = ptr [ 3 * x + 2 ];ptr [ 3 * x + 2 ] = temp ;}}return pIplImg ;}
顺藤摸瓜,再重申下我的目的是Opencv的图转成OSG的,因为配置了Opencv2.0,所以使用了最新的图像格式Mat(同时包括了老版本的IplImage和cvMat)
于是任务变成:Opencv Mat->OSG::Image
去Image看构造函数,只有setImage中要求设定长款和char* data,数据格式相符。OSG源码:
/** Set the image dimensions, format and data. */
virtual void setImage(int s,int t,int r,
GLint internalTextureformat,
GLenum pixelFormat,GLenum type,
unsigned char* data,
AllocationMode mode,
int packing=1, int rowLength=0);
之后试了一下居然成了。我的代码:
osg :: ref_ptr < osg :: Image > mat2img :: mat2image ( Mat cvimg ){osgframe = new osg :: Image ;osgframe -> setImage ( cvimg . cols , cvimg . rows , 3 ,GL_BGR , GL_BGR , GL_UNSIGNED_BYTE , cvimg . data ,osg :: Image :: NO_DELETE , 1 );if ( osgframe )printf ( "convert done!" );osgDB :: writeImageFile ( * osgframe , "D: \\ OV2OV \\ OV2OV \\ osgframe.bmp" );return osgframe ;}
调试输出的图片和文字信息全部正确。
之后就是重新加工视频流了,用osg纹理贴图即可。