Ogre利用OpenCV實現視頻紋理

原文寫於2011年

http://blog.csdn.net/zhuxiaoyang2000/article/details/6758407


由於Ogre自身沒有實現視頻紋理,我們需要自己想辦法讀取視頻並顯示到某個物體上。網上已有人通過TheoraVideoPlugin實現視頻播放,但需要編譯libogg等幾個第三方庫,其自身帶的Demo也不完善,不便於利用。由於最近在搞OpenCV,就想到是不是可以通過OpenCV來讀取視頻,並將每幀圖片轉化爲Ogre可讀的Buffer,然後將其顯示到實體上。Google之後發現,已經有人有類似的想法,但給出的答案沒有處理好圖片的RGB問題,總是報錯。經過幾個小時的修改,我已經成功實現了Ogre的視頻紋理。
(1)首先當然要有OpenCV庫(include文件、lib文件、dll文件),可以自己編譯或下載已經編譯好的版本。我採用的是OpenCV 2.0。

需要的lib文件是cv200.lib,cxcore200.lib和highgui200.lib(根據OpenCV的版本不同,文件的名稱也會不同)及相應的dll文件。

(2)讀取視頻文件

  1. IplImage*  mVideoFrame;  
  2. CvCapture* mVideoCapture;  
  3. mVideoCapture = cvCreateFileCapture("..\\media\\xxx.avi");  

(3)創建視頻幀的圖片及其相應的材質文件

這裏要特別注意的就是OpenCV的IplImage的圖片數據中RGB的存儲順序,它默認的存儲順序是BGR。故在設置TexturePtr時我們也應該注意其圖片格式,否則會出現各種詭異的錯誤。這裏我們添加了A通道,圖片格式爲PF_B8G8R8A8。

  1. void createVideoTexture()  
  2. {  
  3.     mVideoFrame = cvQueryFrame(mVideoCapture);  
  4.     if(!mVideoFrame)  
  5.     {  
  6.         return;  
  7.     }  
  8.       
  9.     // Implementing a video texture  
  10.     Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().createManual(  
  11.         "VideoTexture",      // name  
  12.         Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,  
  13.         Ogre::TEX_TYPE_2D,   // type  
  14.         mVideoFrame->width,  // width  
  15.         mVideoFrame->height, // height  
  16.         0,                   // number of mipmaps  
  17.         Ogre::PF_B8G8R8A8,   // pixel format  
  18.         Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE // usage, for textures updated very often  
  19.         );  
  20.     // Get the pixel buffer  
  21.     Ogre::HardwarePixelBufferSharedPtr pixelBuffer = texture->getBuffer();  
  22.     // Lock the pixel buffer and get a pixel box  
  23.     unsigned char* buffer = static_cast<unsigned char*>(  
  24.         pixelBuffer->lock(0, mVideoFrame->width*mVideoFrame->height*4, Ogre::HardwareBuffer::HBL_DISCARD) );  
  25.     for(int y = 0; y < mVideoFrame->height; ++y)  
  26.     {  
  27.         for(int x = 0; x < mVideoFrame->width; ++x)  
  28.         {  
  29.             buffer[ ((y*mVideoFrame->width)+x)*4 + 0 ] = mVideoFrame->imageData[ ((y*mVideoFrame->width)+x)*3 + 0 ]; // B  
  30.             buffer[ ((y*mVideoFrame->width)+x)*4 + 1 ] = mVideoFrame->imageData[ ((y*mVideoFrame->width)+x)*3 + 1 ]; // G  
  31.             buffer[ ((y*mVideoFrame->width)+x)*4 + 2 ] = mVideoFrame->imageData[ ((y*mVideoFrame->width)+x)*3 + 2 ]; // R  
  32.             buffer[ ((y*mVideoFrame->width)+x)*4 + 3 ] = 255;                                                        // A  
  33.         }  
  34.     }  
  35.     // Unlock the pixel buffer  
  36.     pixelBuffer->unlock();  
  37.   
  38.     // Create a materail using the texture  
  39.     Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create(  
  40.         "VideoTextureMaterial"// name  
  41.         Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);  
  42.     material->getTechnique(0)->getPass(0)->createTextureUnitState("VideoTexture");  
  43.     material->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);  
  44.     material->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);  
  45.     material->getTechnique(0)->getPass(0)->setLightingEnabled(false);  
  46. }  
(4)創建一個長方形實體來展示視頻紋理
  1. Ogre::Rectangle2D* mVideoScreen = new Ogre::Rectangle2D(true);  
  2. mVideoScreen->setCorners(-0.5f, 1.0f, 0.5f, -1.0f);  
  3. mVideoScreen->setBoundingBox(Ogre::AxisAlignedBox(-100000.0f * Ogre::Vector3::UNIT_SCALE, 100000.0f * Ogre::Vector3::UNIT_SCALE));  
  4. mVideoScreen->setMaterial( material->getName() );  
  5. // Attach it to a SceneNode  
  6. Ogre::SceneNode* videoScreenNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("VideoScreenNode");  
  7. videoScreenNode->attachObject(mVideoScreen);  
(5)每幀更新視頻
方法和(3)差不多,這裏就不贅述了。

實現效果如下:


源代碼可在http://download.csdn.net/detail/zhuxiaoyang2000/3582906找到。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章