mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-18 08:44:11 +08:00

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>
260 lines
8.1 KiB
C++
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;
|
|
}
|