123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- // This file is part of OpenCV project.
- // It is subject to the license terms in the LICENSE file found in the top-level directory
- // of this distribution and at http://opencv.org/license.html
- #include "perf_precomp.hpp"
- namespace opencv_test { namespace {
- using namespace cv;
- /** Reprojects screen point to camera space given z coord. */
- struct Reprojector
- {
- Reprojector() {}
- inline Reprojector(Matx33f intr)
- {
- fxinv = 1.f / intr(0, 0), fyinv = 1.f / intr(1, 1);
- cx = intr(0, 2), cy = intr(1, 2);
- }
- template<typename T>
- inline cv::Point3_<T> operator()(cv::Point3_<T> p) const
- {
- T x = p.z * (p.x - cx) * fxinv;
- T y = p.z * (p.y - cy) * fyinv;
- return cv::Point3_<T>(x, y, p.z);
- }
- float fxinv, fyinv, cx, cy;
- };
- template<class Scene>
- struct RenderInvoker : ParallelLoopBody
- {
- RenderInvoker(Mat_<float>& _frame, Affine3f _pose,
- Reprojector _reproj, float _depthFactor, bool _onlySemisphere)
- : ParallelLoopBody(),
- frame(_frame),
- pose(_pose),
- reproj(_reproj),
- depthFactor(_depthFactor),
- onlySemisphere(_onlySemisphere)
- { }
- virtual void operator ()(const cv::Range& r) const
- {
- for (int y = r.start; y < r.end; y++)
- {
- float* frameRow = frame[y];
- for (int x = 0; x < frame.cols; x++)
- {
- float pix = 0;
- Point3f orig = pose.translation();
- // direction through pixel
- Point3f screenVec = reproj(Point3f((float)x, (float)y, 1.f));
- float xyt = 1.f / (screenVec.x * screenVec.x +
- screenVec.y * screenVec.y + 1.f);
- Point3f dir = normalize(Vec3f(pose.rotation() * screenVec));
- // screen space axis
- dir.y = -dir.y;
- const float maxDepth = 20.f;
- const float maxSteps = 256;
- float t = 0.f;
- for (int step = 0; step < maxSteps && t < maxDepth; step++)
- {
- Point3f p = orig + dir * t;
- float d = Scene::map(p, onlySemisphere);
- if (d < 0.000001f)
- {
- float depth = std::sqrt(t * t * xyt);
- pix = depth * depthFactor;
- break;
- }
- t += d;
- }
- frameRow[x] = pix;
- }
- }
- }
- Mat_<float>& frame;
- Affine3f pose;
- Reprojector reproj;
- float depthFactor;
- bool onlySemisphere;
- };
- struct Scene
- {
- virtual ~Scene() {}
- static Ptr<Scene> create(Size sz, Matx33f _intr, float _depthFactor, bool onlySemisphere);
- virtual Mat depth(Affine3f pose) = 0;
- virtual std::vector<Affine3f> getPoses() = 0;
- };
- struct SemisphereScene : Scene
- {
- const int framesPerCycle = 72;
- const float nCycles = 0.25f;
- const Affine3f startPose = Affine3f(Vec3f(0.f, 0.f, 0.f), Vec3f(1.5f, 0.3f, -2.1f));
- Size frameSize;
- Matx33f intr;
- float depthFactor;
- bool onlySemisphere;
- SemisphereScene(Size sz, Matx33f _intr, float _depthFactor, bool _onlySemisphere) :
- frameSize(sz), intr(_intr), depthFactor(_depthFactor), onlySemisphere(_onlySemisphere)
- { }
- static float map(Point3f p, bool onlySemisphere)
- {
- float plane = p.y + 0.5f;
- Point3f spherePose = p - Point3f(-0.0f, 0.3f, 1.1f);
- float sphereRadius = 0.5f;
- float sphere = (float)cv::norm(spherePose) - sphereRadius;
- float sphereMinusBox = sphere;
- float subSphereRadius = 0.05f;
- Point3f subSpherePose = p - Point3f(0.3f, -0.1f, -0.3f);
- float subSphere = (float)cv::norm(subSpherePose) - subSphereRadius;
- float res;
- if (!onlySemisphere)
- res = min({ sphereMinusBox, subSphere, plane });
- else
- res = sphereMinusBox;
- return res;
- }
- Mat depth(Affine3f pose) override
- {
- Mat_<float> frame(frameSize);
- Reprojector reproj(intr);
- Range range(0, frame.rows);
- parallel_for_(range, RenderInvoker<SemisphereScene>(frame, pose, reproj, depthFactor, onlySemisphere));
- return std::move(frame);
- }
- std::vector<Affine3f> getPoses() override
- {
- std::vector<Affine3f> poses;
- for (int i = 0; i < framesPerCycle * nCycles; i++)
- {
- float angle = (float)(CV_2PI * i / framesPerCycle);
- Affine3f pose;
- pose = pose.rotate(startPose.rotation());
- pose = pose.rotate(Vec3f(0.f, -0.5f, 0.f) * angle);
- pose = pose.translate(Vec3f(startPose.translation()[0] * sin(angle),
- startPose.translation()[1],
- startPose.translation()[2] * cos(angle)));
- poses.push_back(pose);
- }
- return poses;
- }
- };
- Ptr<Scene> Scene::create(Size sz, Matx33f _intr, float _depthFactor, bool _onlySemisphere)
- {
- return makePtr<SemisphereScene>(sz, _intr, _depthFactor, _onlySemisphere);
- }
- // this is a temporary solution
- // ----------------------------
- typedef cv::Vec4f ptype;
- typedef cv::Mat_< ptype > Points;
- typedef Points Normals;
- typedef Size2i Size;
- template<int p>
- inline float specPow(float x)
- {
- if (p % 2 == 0)
- {
- float v = specPow<p / 2>(x);
- return v * v;
- }
- else
- {
- float v = specPow<(p - 1) / 2>(x);
- return v * v * x;
- }
- }
- template<>
- inline float specPow<0>(float /*x*/)
- {
- return 1.f;
- }
- template<>
- inline float specPow<1>(float x)
- {
- return x;
- }
- inline cv::Vec3f fromPtype(const ptype& x)
- {
- return cv::Vec3f(x[0], x[1], x[2]);
- }
- inline Point3f normalize(const Vec3f& v)
- {
- double nv = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
- return v * (nv ? 1. / nv : 0.);
- }
- void renderPointsNormals(InputArray _points, InputArray _normals, OutputArray image, Affine3f lightPose)
- {
- Size sz = _points.size();
- image.create(sz, CV_8UC4);
- Points points = _points.getMat();
- Normals normals = _normals.getMat();
- Mat_<Vec4b> img = image.getMat();
- Range range(0, sz.height);
- const int nstripes = -1;
- parallel_for_(range, [&](const Range&)
- {
- for (int y = range.start; y < range.end; y++)
- {
- Vec4b* imgRow = img[y];
- const ptype* ptsRow = points[y];
- const ptype* nrmRow = normals[y];
- for (int x = 0; x < sz.width; x++)
- {
- Point3f p = fromPtype(ptsRow[x]);
- Point3f n = fromPtype(nrmRow[x]);
- Vec4b color;
- if (cvIsNaN(p.x) || cvIsNaN(p.y) || cvIsNaN(p.z) )
- {
- color = Vec4b(0, 32, 0, 0);
- }
- else
- {
- const float Ka = 0.3f; //ambient coeff
- const float Kd = 0.5f; //diffuse coeff
- const float Ks = 0.2f; //specular coeff
- const int sp = 20; //specular power
- const float Ax = 1.f; //ambient color, can be RGB
- const float Dx = 1.f; //diffuse color, can be RGB
- const float Sx = 1.f; //specular color, can be RGB
- const float Lx = 1.f; //light color
- Point3f l = normalize(lightPose.translation() - Vec3f(p));
- Point3f v = normalize(-Vec3f(p));
- Point3f r = normalize(Vec3f(2.f * n * n.dot(l) - l));
- uchar ix = (uchar)((Ax * Ka * Dx + Lx * Kd * Dx * max(0.f, n.dot(l)) +
- Lx * Ks * Sx * specPow<sp>(max(0.f, r.dot(v)))) * 255.f);
- color = Vec4b(ix, ix, ix, 0);
- }
- imgRow[x] = color;
- }
- }
- }, nstripes);
- }
- // ----------------------------
- class Settings
- {
- public:
- Ptr<kinfu::Params> _params;
- Ptr<kinfu::Volume> volume;
- Ptr<Scene> scene;
- std::vector<Affine3f> poses;
- Settings(bool useHashTSDF)
- {
- if (useHashTSDF)
- _params = kinfu::Params::hashTSDFParams(true);
- else
- _params = kinfu::Params::coarseParams();
- volume = kinfu::makeVolume(_params->volumeType, _params->voxelSize, _params->volumePose.matrix,
- _params->raycast_step_factor, _params->tsdf_trunc_dist, _params->tsdf_max_weight,
- _params->truncateThreshold, _params->volumeDims);
- scene = Scene::create(_params->frameSize, _params->intr, _params->depthFactor, true);
- poses = scene->getPoses();
- }
- };
- void displayImage(Mat depth, UMat _points, UMat _normals, float depthFactor, Vec3f lightPose)
- {
- Mat points, normals, image;
- AccessFlag af = ACCESS_READ;
- normals = _normals.getMat(af);
- points = _points.getMat(af);
- patchNaNs(points);
- imshow("depth", depth * (1.f / depthFactor / 4.f));
- renderPointsNormals(points, normals, image, lightPose);
- imshow("render", image);
- waitKey(2000);
- }
- static const bool display = false;
- PERF_TEST(Perf_TSDF, integrate)
- {
- Settings settings(false);
- for (size_t i = 0; i < settings.poses.size(); i++)
- {
- Matx44f pose = settings.poses[i].matrix;
- Mat depth = settings.scene->depth(pose);
- startTimer();
- settings.volume->integrate(depth, settings._params->depthFactor, pose, settings._params->intr);
- stopTimer();
- depth.release();
- }
- SANITY_CHECK_NOTHING();
- }
- PERF_TEST(Perf_TSDF, raycast)
- {
- Settings settings(false);
- for (size_t i = 0; i < settings.poses.size(); i++)
- {
- UMat _points, _normals;
- Matx44f pose = settings.poses[i].matrix;
- Mat depth = settings.scene->depth(pose);
- settings.volume->integrate(depth, settings._params->depthFactor, pose, settings._params->intr);
- startTimer();
- settings.volume->raycast(pose, settings._params->intr, settings._params->frameSize, _points, _normals);
- stopTimer();
- if (display)
- displayImage(depth, _points, _normals, settings._params->depthFactor, settings._params->lightPose);
- }
- SANITY_CHECK_NOTHING();
- }
- PERF_TEST(Perf_HashTSDF, integrate)
- {
- Settings settings(true);
- for (size_t i = 0; i < settings.poses.size(); i++)
- {
- Matx44f pose = settings.poses[i].matrix;
- Mat depth = settings.scene->depth(pose);
- startTimer();
- settings.volume->integrate(depth, settings._params->depthFactor, pose, settings._params->intr);
- stopTimer();
- depth.release();
- }
- SANITY_CHECK_NOTHING();
- }
- PERF_TEST(Perf_HashTSDF, raycast)
- {
- Settings settings(true);
- for (size_t i = 0; i < settings.poses.size(); i++)
- {
- UMat _points, _normals;
- Matx44f pose = settings.poses[i].matrix;
- Mat depth = settings.scene->depth(pose);
- settings.volume->integrate(depth, settings._params->depthFactor, pose, settings._params->intr);
- startTimer();
- settings.volume->raycast(pose, settings._params->intr, settings._params->frameSize, _points, _normals);
- stopTimer();
- if (display)
- displayImage(depth, _points, _normals, settings._params->depthFactor, settings._params->lightPose);
- }
- SANITY_CHECK_NOTHING();
- }
- }} // namespace
|