1
0
mirror of https://github.com/opencv/opencv_contrib.git synced 2025-10-18 08:44:11 +08:00
Files
opencv_contrib/modules/rgbd/samples/large_kinfu_demo.cpp
DumDereDum 7ede6585f5 Merge pull request #2734 from DumDereDum:new_HashTSDF_GPU_class
New HashTSDFVolumeGPU class

* create new class

* rewrite makeHashTSDFVolume

* it builds

* minor fi

* raycast - done

* all code builds

* Docs fix

* –fetch_normals fix

* I want it to work

* minor fix

* valid points checking passed

* it works!

* minor fixes

* warning fix

* last replacements

* warning fix

* create hash_tsdf.cl

* add preCalculationPixNormGPU

* add integrateVolumeUnitGPU

* Docs fix

* create simple volume table

* add functionality to the table

* add new functions

* create new hash table implementation

* minor fix

* create new hash tsdf implementaton

* add expand feature

* minorfix

* error fix

* it builds

* new hash table work

* Docs fix

* warnings fix

* warning fix 1

* warning fix 2

* warning fix

* remove extra coments

* create new function integrateAllVolumeUnitsGPU

* add hash table function

* extend kernel signature

* minor fix

* extent Volume_NODE signature and add functionality

* kernel args fix

* smth

* minor fix

* kernal args fix

* try to fix reading bug

* hash table fix

* add totalVolUnits feature

* it builds

* minor fix

* integrate fix

* fix work with table

* minor table fi

* I am stumped

* try to fix

* add checking to find error

* add copyto

* vol2cam fix

* try to fix

* we are the champions

* remove some comments

* remove last comments

* docs fix

* warning fix

* warning fix 1

* warning fix 2

* create raycast kernel

* extend raycast gpu signature

* minor fix

* integrate all volUnits - done

* docs fix

* warning fix

* extend raycast signature

* raycast work

* bug fix

* calc point4 fix

* minor fix

* add _at function

* raycast done, but work incorrect

* fin dug

* bug fix

* getNorm works correctly

* minor fix

* raycast - done

* minor fixes

* docs fix

* warning fix

* minor fix

* minor fix

* warning fix

* warning fix 1

* win warning fix

* mac fix

* win debug fix

* mac cl warning fix

* allCam2vol fix

* rename num with bufferNum

* remove nums hardcode

* minor fix

* change logic of calculating hash

* replace float16 by vload16

* replace true with false in zFirstMemOrder

* poses fix

* add new tests

* debug print

* debug print 1

* replace [] with .s

* minor fix

* minor fix 1

* remove print

* hashtsdf work fix

* hashtable fix

* resrite hashtasble update

* test_tsdf fix

* override warning fix

* docs fix

* mutex fix

* setUseOptimizes replace false with true

* minor fix

* merge with master

* all minor fixes

* add CPU code for debug

* settings set

* move code from hpp to cpp

* minor opencl fix

* fid bug

* coment fix

* minor fix

* bug fix

* integrate fixed

* speed up

* remove extra code

* raycast fix, but still not work

* raycast fix

* HT refactoring: constants

* HT refactoring: calc_hash()

* HT refactoring: methods set shortened

* no typedef VolumeIndex

* fix a bug in CPU version

* VolumeIndex

* identation

* HashTSDF refactoring: a lot of things

* less TODOs

* lastVisibleIndex dropped from HT

* HT refactor: find -> findRow

* interpolate & getNormal small hash: no queried

* totalVolUnits, indexes -> volumeUnitIndices, better iteration

* raycast artifacts fixed

* interpolation in getNormal is on

* minors

* findRow() refactored

* volStrides, lastVolIndex, volDims, neighbourCoords

* normals, vectorization

* interpolation in getNormalVoxel()

* no 16*16*16, use volumeUnitResolution instead

* resolution, stride...

* raycast: cur idx, etc.

* CPU debugging code removed

* volUnitsData moved to OpenCL memory

* raycast: no copy

* allocate accelerated a bit

* hash_tsdf.cl: pointers fixed

* allVol2cam, poses moved to kernel; rowRange for volUnitsData init

* TSDF voxel: constructor; row range fixed

* rowRange

* pixNorms fix + minors

* depth is now UMat

* markActive is done on GPU, lastVisibleIndices and isActiveFlags moved to GPU

* CL: minor

* volumeUnitIndices -> GPU

* ToyHashMap instead of HT, volumeUnitIndices removed, lastVolIndex removed,
 + a lot of debugging code

* warning about local pix capacity

* CPU allocation: find in global HT first

* ToyHashMap: -> tsdf_functions.hpp

* debugging code + to be removed

* ptr -> at

* volumeUnitResolution is limited to a power of 2

* rename ToyHashMap to ToyHashSet, hashMap to hashTable

* minor

* getNormalVoxel .cl: no float conversions

* getNormalVoxel does not need voxelSizeInv anymore; orig and dir pre-scaled to get rid of extra multiplication

* minor fix

* linux critical bug fix

* docs fix

* mac warning fix

* remove extra test code

* linux warning fix

* remove comments

* capacity = 2048

* capacity = 1024

* hashtables fixes

* minor code removement

* change pixNorm calculation

* remove buff_lvl and neighboorCoords; rename degree

* move volStrides to HashTSDFVolume

* HashTSDFVolumeGPU constructor fix

* move preCalculatePixNormsGPU to tsdf_functions

* minor code removement

* replace copyto() with getUMat()

* remove debug code

* replace copyTo with getUmat again

* replace types in cl

* remove NAN_ELEMENT

* remove Volume_NODE struct and findRow()

* make hash_divisor constant

* uncomment camTrans

* rename data; remove extra val

* fix merge conflict

* create empty UMat

* cl fix

* build error fix

* clear HashTSDFVolumeGPU()

* use constuctor delegation at HashTSDFVolumeCPU

* remove cam2volTransGPU

* add minor fix

Co-authored-by: Saratovtsev <artem.saratovtsev@intel.com>
Co-authored-by: Rostislav Vasilikhin <rostislav.vasilikhin@intel.com>
2021-02-20 16:33:19 +00:00

260 lines
8.1 KiB
C++

// 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
// This code is also subject to the license terms in the LICENSE_KinectFusion.md file found in this
// module's directory
#include <fstream>
#include <iostream>
#include <opencv2/calib3d.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/rgbd/large_kinfu.hpp>
#include "io_utils.hpp"
using namespace cv;
using namespace cv::kinfu;
using namespace cv::large_kinfu;
using namespace cv::io_utils;
#ifdef HAVE_OPENCV_VIZ
#include <opencv2/viz.hpp>
#endif
#ifdef HAVE_OPENCV_VIZ
const std::string vizWindowName = "cloud";
struct PauseCallbackArgs
{
PauseCallbackArgs(LargeKinfu& _largeKinfu) : largeKinfu(_largeKinfu) {}
LargeKinfu& largeKinfu;
};
void pauseCallback(const viz::MouseEvent& me, void* args);
void pauseCallback(const viz::MouseEvent& me, void* args)
{
if (me.type == viz::MouseEvent::Type::MouseMove ||
me.type == viz::MouseEvent::Type::MouseScrollDown ||
me.type == viz::MouseEvent::Type::MouseScrollUp)
{
PauseCallbackArgs pca = *((PauseCallbackArgs*)(args));
viz::Viz3d window(vizWindowName);
UMat rendered;
pca.largeKinfu.render(rendered, window.getViewerPose().matrix);
imshow("render", rendered);
waitKey(1);
}
}
#endif
static const char* keys = {
"{help h usage ? | | print this message }"
"{depth | | Path to depth.txt file listing a set of depth images }"
"{camera |0| Index of depth camera to be used as a depth source }"
"{coarse | | Run on coarse settings (fast but ugly) or on default (slow but looks better),"
" in coarse mode points and normals are displayed }"
"{idle | | Do not run LargeKinfu, just display depth frames }"
"{record | | Write depth frames to specified file list"
" (the same format as for the 'depth' key) }"
};
static const std::string message =
"\nThis demo uses live depth input or RGB-D dataset taken from"
"\nhttps://vision.in.tum.de/data/datasets/rgbd-dataset"
"\nto demonstrate Submap based large environment reconstruction"
"\nThis module uses the newer hashtable based TSDFVolume (relatively fast) for larger "
"reconstructions by default\n";
int main(int argc, char** argv)
{
bool coarse = false;
bool idle = false;
std::string recordPath;
CommandLineParser parser(argc, argv, keys);
parser.about(message);
if (!parser.check())
{
parser.printMessage();
parser.printErrors();
return -1;
}
if (parser.has("help"))
{
parser.printMessage();
return 0;
}
if (parser.has("coarse"))
{
coarse = true;
}
if (parser.has("record"))
{
recordPath = parser.get<String>("record");
}
if (parser.has("idle"))
{
idle = true;
}
Ptr<DepthSource> ds;
if (parser.has("depth"))
ds = makePtr<DepthSource>(parser.get<String>("depth"));
else
ds = makePtr<DepthSource>(parser.get<int>("camera"));
if (ds->empty())
{
std::cerr << "Failed to open depth source" << std::endl;
parser.printMessage();
return -1;
}
Ptr<DepthWriter> depthWriter;
if (!recordPath.empty())
depthWriter = makePtr<DepthWriter>(recordPath);
Ptr<large_kinfu::Params> params;
Ptr<LargeKinfu> largeKinfu;
params = large_kinfu::Params::hashTSDFParams(coarse);
// These params can be different for each depth sensor
ds->updateParams(*params);
cv::setUseOptimized(true);
if (!idle)
largeKinfu = LargeKinfu::create(params);
#ifdef HAVE_OPENCV_VIZ
cv::viz::Viz3d window(vizWindowName);
window.setViewerPose(Affine3f::Identity());
bool pause = false;
#endif
UMat rendered;
UMat points;
UMat normals;
int64 prevTime = getTickCount();
for (UMat frame = ds->getDepth(); !frame.empty(); frame = ds->getDepth())
{
if (depthWriter)
depthWriter->append(frame);
#ifdef HAVE_OPENCV_VIZ
if (pause)
{
// doesn't happen in idle mode
largeKinfu->getCloud(points, normals);
if (!points.empty() && !normals.empty())
{
viz::WCloud cloudWidget(points, viz::Color::white());
viz::WCloudNormals cloudNormals(points, normals, /*level*/ 1, /*scale*/ 0.05,
viz::Color::gray());
window.showWidget("cloud", cloudWidget);
window.showWidget("normals", cloudNormals);
Vec3d volSize = largeKinfu->getParams().volumeParams.voxelSize *
Vec3d(largeKinfu->getParams().volumeParams.resolution);
window.showWidget("cube", viz::WCube(Vec3d::all(0), volSize),
largeKinfu->getParams().volumeParams.pose);
PauseCallbackArgs pca(*largeKinfu);
window.registerMouseCallback(pauseCallback, (void*)&pca);
window.showWidget("text",
viz::WText(cv::String("Move camera in this window. "
"Close the window or press Q to resume"),
Point()));
window.spin();
window.removeWidget("text");
window.removeWidget("cloud");
window.removeWidget("normals");
window.registerMouseCallback(0);
}
pause = false;
}
else
#endif
{
UMat cvt8;
float depthFactor = params->depthFactor;
convertScaleAbs(frame, cvt8, 0.25 * 256. / depthFactor);
if (!idle)
{
imshow("depth", cvt8);
if (!largeKinfu->update(frame))
{
largeKinfu->reset();
std::cout << "reset" << std::endl;
}
#ifdef HAVE_OPENCV_VIZ
else
{
if (coarse)
{
largeKinfu->getCloud(points, normals);
if (!points.empty() && !normals.empty())
{
viz::WCloud cloudWidget(points, viz::Color::white());
viz::WCloudNormals cloudNormals(points, normals, /*level*/ 1,
/*scale*/ 0.05, viz::Color::gray());
window.showWidget("cloud", cloudWidget);
window.showWidget("normals", cloudNormals);
}
}
// window.showWidget("worldAxes", viz::WCoordinateSystem());
Vec3d volSize = largeKinfu->getParams().volumeParams.voxelSize *
largeKinfu->getParams().volumeParams.resolution;
window.showWidget("cube", viz::WCube(Vec3d::all(0), volSize),
largeKinfu->getParams().volumeParams.pose);
window.setViewerPose(largeKinfu->getPose());
window.spinOnce(1, true);
}
#endif
largeKinfu->render(rendered);
}
else
{
rendered = cvt8;
}
}
int64 newTime = getTickCount();
putText(rendered,
cv::format("FPS: %2d press R to reset, P to pause, Q to quit",
(int)(getTickFrequency() / (newTime - prevTime))),
Point(0, rendered.rows - 1), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 255));
prevTime = newTime;
imshow("render", rendered);
int c = waitKey(1);
switch (c)
{
case 'r':
if (!idle)
largeKinfu->reset();
break;
case 'q': return 0;
#ifdef HAVE_OPENCV_VIZ
case 'p':
if (!idle)
pause = true;
#endif
default: break;
}
}
return 0;
}