diff --git a/modules/ovis/include/opencv2/ovis.hpp b/modules/ovis/include/opencv2/ovis.hpp index aa95f64bb..fa46f3c06 100644 --- a/modules/ovis/include/opencv2/ovis.hpp +++ b/modules/ovis/include/opencv2/ovis.hpp @@ -130,6 +130,13 @@ public: */ CV_WRAP virtual void getScreenshot(OutputArray frame) = 0; + /** + * get the depth for the current frame. + * + * return the per pixel distance to the camera in world units + */ + CV_WRAP virtual void getDepth(OutputArray depth) = 0; + /** * convenience method to force the "up" axis to stay fixed * diff --git a/modules/ovis/src/ovis.cpp b/modules/ovis/src/ovis.cpp index 95b2735b0..bfedb77b3 100644 --- a/modules/ovis/src/ovis.cpp +++ b/modules/ovis/src/ovis.cpp @@ -240,10 +240,10 @@ class WindowSceneImpl : public WindowScene Ptr bgplane; Ogre::RenderTarget* frameSrc; - + Ogre::RenderTarget* depthRTT; public: WindowSceneImpl(Ptr app, const String& _title, const Size& sz, int flags) - : title(_title), root(app->getRoot()) + : title(_title), root(app->getRoot()), depthRTT(NULL) { if (!app->sceneMgr) { @@ -470,6 +470,38 @@ public: cvtColor(out, out, dst_type == CV_8UC3 ? COLOR_RGB2BGR : COLOR_RGBA2BGRA); } + void getDepth(OutputArray depth) + { + Camera* cam = sceneMgr->getCamera(title); + if (!depthRTT) + { + // render into an offscreen texture + // currently this draws everything twice as OGRE lacks depth texture attachments + TexturePtr tex = TextureManager::getSingleton().createManual( + title + "_Depth", RESOURCEGROUP_NAME, TEX_TYPE_2D, frameSrc->getWidth(), + frameSrc->getHeight(), 0, PF_DEPTH, TU_RENDERTARGET); + depthRTT = tex->getBuffer()->getRenderTarget(); + depthRTT->addViewport(cam); + depthRTT->setAutoUpdated(false); // only update when requested + } + + Mat tmp(depthRTT->getHeight(), depthRTT->getWidth(), CV_16U); + PixelBox pb(depthRTT->getWidth(), depthRTT->getHeight(), 1, PF_DEPTH, tmp.ptr()); + depthRTT->update(false); + depthRTT->copyContentsToMemory(pb, pb); + + // convert to NDC + double alpha = 2.0/std::numeric_limits::max(); + tmp.convertTo(depth, CV_64F, alpha, -1); + + // convert to linear + float n = cam->getNearClipDistance(); + float f = cam->getFarClipDistance(); + Mat ndc = depth.getMat(); + ndc = -ndc * (f - n) + (f + n); + ndc = (2 * f * n) / ndc; + } + void fixCameraYawAxis(bool useFixed, InputArray _up) { Vector3 up = Vector3::UNIT_Y;