mirror of
https://github.com/introlab/rtabmap.git
synced 2026-09-02 01:20:25 +08:00
Memory efficiency: changed std::vector<unsigned char> bytes arrays to cv::Mat to avoid multiple copies when Signature objects are copied.
git-svn-id: http://rtabmap.googlecode.com/svn/trunk/rtabmap@1937 f169173b-cf89-36c8-b27e-44dbe73f0c83
This commit is contained in:
@@ -404,9 +404,9 @@ void DBDriver::loadNodeData(std::list<Signature *> & signatures, bool loadMetric
|
||||
//TODO Check also in the trash ?
|
||||
void DBDriver::getNodeData(
|
||||
int signatureId,
|
||||
std::vector<unsigned char> & image,
|
||||
std::vector<unsigned char> & depth,
|
||||
std::vector<unsigned char> & depth2d,
|
||||
cv::Mat & imageCompressed,
|
||||
cv::Mat & depthCompressed,
|
||||
cv::Mat & depth2dCompressed,
|
||||
float & fx,
|
||||
float & fy,
|
||||
float & cx,
|
||||
@@ -414,15 +414,15 @@ void DBDriver::getNodeData(
|
||||
Transform & localTransform) const
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
this->getNodeDataQuery(signatureId, image, depth, depth2d, fx, fy, cx, cy, localTransform);
|
||||
this->getNodeDataQuery(signatureId, imageCompressed, depthCompressed, depth2dCompressed, fx, fy, cx, cy, localTransform);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
}
|
||||
|
||||
//TODO Check also in the trash ?
|
||||
void DBDriver::getNodeData(int signatureId, std::vector<unsigned char> & image) const
|
||||
void DBDriver::getNodeData(int signatureId, cv::Mat & imageCompressed) const
|
||||
{
|
||||
_dbSafeAccessMutex.lock();
|
||||
this->getNodeDataQuery(signatureId, image);
|
||||
this->getNodeDataQuery(signatureId, imageCompressed);
|
||||
_dbSafeAccessMutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -515,9 +515,7 @@ void DBDriverSqlite3::loadNodeDataQuery(std::list<Signature *> & signatures, boo
|
||||
//Create the image
|
||||
if(dataSize>4 && data)
|
||||
{
|
||||
std::vector<unsigned char> image(dataSize);
|
||||
memcpy(image.data(), data, dataSize);
|
||||
(*iter)->setImage(image);
|
||||
(*iter)->setImageCompressed(cv::Mat(1, dataSize, CV_8UC1, (void *)data).clone());
|
||||
}
|
||||
|
||||
if(loadMetricData)
|
||||
@@ -526,17 +524,16 @@ void DBDriverSqlite3::loadNodeDataQuery(std::list<Signature *> & signatures, boo
|
||||
dataSize = sqlite3_column_bytes(ppStmt, index++);
|
||||
|
||||
//Create the depth image
|
||||
std::vector<unsigned char> depth;
|
||||
cv::Mat depthCompressed;
|
||||
if(dataSize>4 && data)
|
||||
{
|
||||
depth.resize(dataSize);
|
||||
memcpy(depth.data(), data, dataSize);
|
||||
depthCompressed = cv::Mat(1, dataSize, CV_8UC1, (void *)data).clone();
|
||||
}
|
||||
|
||||
if(uStrNumCmp(_version, "0.7.0") < 0)
|
||||
{
|
||||
float depthConstant = sqlite3_column_double(ppStmt, index++);
|
||||
(*iter)->setDepth(depth, 1.0f/depthConstant, 1.0f/depthConstant, 0, 0);
|
||||
(*iter)->setDepthCompressed(depthCompressed, 1.0f/depthConstant, 1.0f/depthConstant, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -544,7 +541,7 @@ void DBDriverSqlite3::loadNodeDataQuery(std::list<Signature *> & signatures, boo
|
||||
float fy = sqlite3_column_double(ppStmt, index++);
|
||||
float cx = sqlite3_column_double(ppStmt, index++);
|
||||
float cy = sqlite3_column_double(ppStmt, index++);
|
||||
(*iter)->setDepth(depth, fx, fy, cx, cy);
|
||||
(*iter)->setDepthCompressed(depthCompressed, fx, fy, cx, cy);
|
||||
}
|
||||
|
||||
data = sqlite3_column_blob(ppStmt, index); // local transform
|
||||
@@ -559,13 +556,12 @@ void DBDriverSqlite3::loadNodeDataQuery(std::list<Signature *> & signatures, boo
|
||||
data = sqlite3_column_blob(ppStmt, index);
|
||||
dataSize = sqlite3_column_bytes(ppStmt, index++);
|
||||
//Create the depth2d
|
||||
std::vector<unsigned char> depth2d;
|
||||
cv::Mat depth2dCompressed;
|
||||
if(dataSize>4 && data)
|
||||
{
|
||||
depth2d.resize(dataSize);
|
||||
memcpy(depth2d.data(), data, dataSize);
|
||||
(*iter)->setDepth2DCompressed(cv::Mat(1, dataSize, CV_8UC1, (void *)data).clone()); // depth2d
|
||||
}
|
||||
(*iter)->setDepth2D(depth2d); // depth2d
|
||||
|
||||
}
|
||||
|
||||
rc = sqlite3_step(ppStmt); // next result...
|
||||
@@ -586,9 +582,9 @@ void DBDriverSqlite3::loadNodeDataQuery(std::list<Signature *> & signatures, boo
|
||||
|
||||
void DBDriverSqlite3::getNodeDataQuery(
|
||||
int signatureId,
|
||||
std::vector<unsigned char> & image,
|
||||
std::vector<unsigned char> & depth,
|
||||
std::vector<unsigned char> & depth2d,
|
||||
cv::Mat & imageCompressed,
|
||||
cv::Mat & depthCompressed,
|
||||
cv::Mat & depth2dCompressed,
|
||||
float & fx,
|
||||
float & fy,
|
||||
float & cx,
|
||||
@@ -645,8 +641,7 @@ void DBDriverSqlite3::getNodeDataQuery(
|
||||
//Create the image
|
||||
if(dataSize>4 && data)
|
||||
{
|
||||
image.resize(dataSize);
|
||||
memcpy(image.data(), data, dataSize);
|
||||
imageCompressed = cv::Mat(1, dataSize, CV_8UC1).clone();
|
||||
}
|
||||
|
||||
data = sqlite3_column_blob(ppStmt, index);
|
||||
@@ -655,8 +650,7 @@ void DBDriverSqlite3::getNodeDataQuery(
|
||||
//Create the depth image
|
||||
if(dataSize>4 && data)
|
||||
{
|
||||
depth.resize(dataSize);
|
||||
memcpy(depth.data(), data, dataSize);
|
||||
depthCompressed = cv::Mat(1, dataSize, CV_8UC1).clone();
|
||||
}
|
||||
|
||||
if(uStrNumCmp(_version, "0.7.0") < 0)
|
||||
@@ -687,11 +681,10 @@ void DBDriverSqlite3::getNodeDataQuery(
|
||||
//Create the depth2d
|
||||
if(dataSize>4 && data)
|
||||
{
|
||||
depth2d.resize(dataSize);
|
||||
memcpy(depth2d.data(), data, dataSize);
|
||||
depth2dCompressed = cv::Mat(1, dataSize, CV_8UC1).clone();
|
||||
}
|
||||
|
||||
if(depth.empty() || fx <= 0 || fy <= 0 || cx < 0 || cy < 0)
|
||||
if(depthCompressed.empty() || fx <= 0 || fy <= 0 || cx < 0 || cy < 0)
|
||||
{
|
||||
UWARN("No metric data loaded!? Consider using getNodeDataQuery() with image only.");
|
||||
}
|
||||
@@ -708,7 +701,7 @@ void DBDriverSqlite3::getNodeDataQuery(
|
||||
}
|
||||
}
|
||||
|
||||
void DBDriverSqlite3::getNodeDataQuery(int signatureId, std::vector<unsigned char> & image) const
|
||||
void DBDriverSqlite3::getNodeDataQuery(int signatureId, cv::Mat & imageCompressed) const
|
||||
{
|
||||
if(_ppDb)
|
||||
{
|
||||
@@ -744,8 +737,7 @@ void DBDriverSqlite3::getNodeDataQuery(int signatureId, std::vector<unsigned cha
|
||||
//Create the image
|
||||
if(dataSize>4 && data)
|
||||
{
|
||||
image.resize(dataSize);
|
||||
memcpy(image.data(), data, dataSize);
|
||||
imageCompressed = cv::Mat(1, dataSize, CV_8UC1).clone();
|
||||
}
|
||||
|
||||
rc = sqlite3_step(ppStmt); // next result...
|
||||
@@ -1823,9 +1815,9 @@ void DBDriverSqlite3::saveQuery(const std::list<Signature *> & signatures) const
|
||||
|
||||
for(std::list<Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
|
||||
{
|
||||
if((*i)->getImage().size())
|
||||
if(!(*i)->getImageCompressed().empty())
|
||||
{
|
||||
stepImage(ppStmt, (*i)->id(), (*i)->getImage());
|
||||
stepImage(ppStmt, (*i)->id(), (*i)->getImageCompressed());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1841,9 +1833,9 @@ void DBDriverSqlite3::saveQuery(const std::list<Signature *> & signatures) const
|
||||
for(std::list<Signature *>::const_iterator i=signatures.begin(); i!=signatures.end(); ++i)
|
||||
{
|
||||
//metric
|
||||
if((*i)->getDepth().size() || (*i)->getDepth2D().size())
|
||||
if(!(*i)->getDepthCompressed().empty() || !(*i)->getDepth2DCompressed().empty())
|
||||
{
|
||||
stepDepth(ppStmt, (*i)->id(), (*i)->getDepth(), (*i)->getDepth2D(), (*i)->getDepthFx(), (*i)->getDepthFy(), (*i)->getDepthCx(), (*i)->getDepthCy(), (*i)->getLocalTransform());
|
||||
stepDepth(ppStmt, (*i)->id(), (*i)->getDepthCompressed(), (*i)->getDepth2DCompressed(), (*i)->getDepthFx(), (*i)->getDepthFy(), (*i)->getDepthCx(), (*i)->getDepthCy(), (*i)->getLocalTransform());
|
||||
}
|
||||
}
|
||||
// Finalize (delete) the statement
|
||||
@@ -1948,9 +1940,9 @@ std::string DBDriverSqlite3::queryStepImage() const
|
||||
}
|
||||
void DBDriverSqlite3::stepImage(sqlite3_stmt * ppStmt,
|
||||
int id,
|
||||
const std::vector<unsigned char> & image) const
|
||||
const cv::Mat & imageBytes) const
|
||||
{
|
||||
UDEBUG("Save image %d (size=%d)", id, (int)image.size());
|
||||
UDEBUG("Save image %d (size=%d)", id, (int)imageBytes.cols);
|
||||
if(!ppStmt)
|
||||
{
|
||||
UFATAL("");
|
||||
@@ -1962,9 +1954,9 @@ void DBDriverSqlite3::stepImage(sqlite3_stmt * ppStmt,
|
||||
rc = sqlite3_bind_int(ppStmt, index++, id);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
if(image.size())
|
||||
if(!imageBytes.empty())
|
||||
{
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, image.data(), (int)image.size(), SQLITE_STATIC);
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, imageBytes.data, (int)imageBytes.cols, SQLITE_STATIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1993,15 +1985,15 @@ std::string DBDriverSqlite3::queryStepDepth() const
|
||||
}
|
||||
void DBDriverSqlite3::stepDepth(sqlite3_stmt * ppStmt,
|
||||
int id,
|
||||
const std::vector<unsigned char> & depth,
|
||||
const std::vector<unsigned char> & depth2d,
|
||||
const cv::Mat & depthBytes,
|
||||
const cv::Mat & depth2dBytes,
|
||||
float fx,
|
||||
float fy,
|
||||
float cx,
|
||||
float cy,
|
||||
const Transform & localTransform) const
|
||||
{
|
||||
UDEBUG("Save depth %d (size=%d) depth2d = %d", id, (int)depth.size(), (int)depth2d.size());
|
||||
UDEBUG("Save depth %d (size=%d) depth2d = %d", id, (int)depthBytes.cols, (int)depth2dBytes.cols);
|
||||
if(!ppStmt)
|
||||
{
|
||||
UFATAL("");
|
||||
@@ -2013,9 +2005,9 @@ void DBDriverSqlite3::stepDepth(sqlite3_stmt * ppStmt,
|
||||
rc = sqlite3_bind_int(ppStmt, index++, id);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
if(depth.size())
|
||||
if(!depthBytes.empty())
|
||||
{
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, depth.data(), (int)depth.size(), SQLITE_STATIC);
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, depthBytes.data, (int)depthBytes.cols, SQLITE_STATIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2043,9 +2035,9 @@ void DBDriverSqlite3::stepDepth(sqlite3_stmt * ppStmt,
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, localTransform.data(), localTransform.size()*sizeof(float), SQLITE_STATIC);
|
||||
UASSERT_MSG(rc == SQLITE_OK, uFormat("DB error: %s", sqlite3_errmsg(_ppDb)).c_str());
|
||||
|
||||
if(depth2d.size())
|
||||
if(!depth2dBytes.empty())
|
||||
{
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, depth2d.data(), (int)depth2d.size(), SQLITE_STATIC);
|
||||
rc = sqlite3_bind_blob(ppStmt, index++, depth2dBytes.data, (int)depth2dBytes.cols, SQLITE_STATIC);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -77,15 +77,15 @@ private:
|
||||
virtual void loadNodeDataQuery(std::list<Signature *> & signatures, bool loadMetricData) const;
|
||||
virtual void getNodeDataQuery(
|
||||
int signatureId,
|
||||
std::vector<unsigned char> & image,
|
||||
std::vector<unsigned char> & depth,
|
||||
std::vector<unsigned char> & depth2d,
|
||||
cv::Mat & imageCompressed,
|
||||
cv::Mat & depthCompressed,
|
||||
cv::Mat & depth2dCompressed,
|
||||
float & fx,
|
||||
float & fy,
|
||||
float & cx,
|
||||
float & cy,
|
||||
Transform & localTransform) const;
|
||||
virtual void getNodeDataQuery(int signatureId, std::vector<unsigned char> & image) const;
|
||||
virtual void getNodeDataQuery(int signatureId, cv::Mat & imageCompressed) const;
|
||||
virtual void getPoseQuery(int signatureId, Transform & pose, int & mapId) const;
|
||||
virtual void getAllNodeIdsQuery(std::set<int> & ids, bool ignoreChildren) const;
|
||||
virtual void getLastIdQuery(const std::string & tableName, int & id) const;
|
||||
@@ -102,12 +102,12 @@ private:
|
||||
void stepImage(
|
||||
sqlite3_stmt * ppStmt,
|
||||
int id,
|
||||
const std::vector<unsigned char> & image) const;
|
||||
const cv::Mat & imageBytes) const;
|
||||
void stepDepth(
|
||||
sqlite3_stmt * ppStmt,
|
||||
int id,
|
||||
const std::vector<unsigned char> & depth,
|
||||
const std::vector<unsigned char> & depth2d,
|
||||
const cv::Mat & depthBytes,
|
||||
const cv::Mat & depth2dBytes,
|
||||
float fx,
|
||||
float fy,
|
||||
float cx,
|
||||
|
||||
@@ -207,9 +207,9 @@ void DBReader::getNextImage(
|
||||
|
||||
if(!this->isKilled() && _currentId != _ids.end())
|
||||
{
|
||||
std::vector<unsigned char> imageBytes;
|
||||
std::vector<unsigned char> depthBytes;
|
||||
std::vector<unsigned char> depth2dBytes;
|
||||
cv::Mat imageBytes;
|
||||
cv::Mat depthBytes;
|
||||
cv::Mat depth2dBytes;
|
||||
int mapId;
|
||||
_dbDriver->getNodeData(*_currentId, imageBytes, depthBytes, depth2dBytes, fx, fy, cx, cy, localTransform);
|
||||
_dbDriver->getPose(*_currentId, pose, mapId);
|
||||
@@ -220,9 +220,9 @@ void DBReader::getNextImage(
|
||||
UWARN("No image loaded from the database for id=%d!", *_currentId);
|
||||
}
|
||||
|
||||
util3d::CompressionThread ctImage(&imageBytes, true);
|
||||
util3d::CompressionThread ctDepth(&depthBytes, true);
|
||||
util3d::CompressionThread ctDepth2D(&depth2dBytes, false);
|
||||
util3d::CompressionThread ctImage(imageBytes, true);
|
||||
util3d::CompressionThread ctDepth(depthBytes, true);
|
||||
util3d::CompressionThread ctDepth2D(depth2dBytes, false);
|
||||
ctImage.start();
|
||||
ctDepth.start();
|
||||
ctDepth2D.start();
|
||||
|
||||
@@ -1129,7 +1129,7 @@ std::map<int, float> Memory::computeLikelihood(const Signature * signature, cons
|
||||
{
|
||||
UFATAL("Signature %d not found in WM ?!?", *iter);
|
||||
}
|
||||
sim = signature->compareTo(sB);
|
||||
sim = signature->compareTo(*sB);
|
||||
}
|
||||
|
||||
likelihood.insert(likelihood.end(), std::pair<int, float>(*iter, sim));
|
||||
@@ -1809,12 +1809,12 @@ Transform Memory::computeIcpTransform(int oldId, int newId, Transform guess, boo
|
||||
if(icp3D)
|
||||
{
|
||||
//Depth required, if not in RAM, load it from LTM
|
||||
if(oldS->getDepth().empty())
|
||||
if(oldS->getDepthCompressed().empty())
|
||||
{
|
||||
depthToLoad.push_back(oldS);
|
||||
added.insert(oldS->id());
|
||||
}
|
||||
if(newS->getDepth().empty())
|
||||
if(newS->getDepthCompressed().empty())
|
||||
{
|
||||
depthToLoad.push_back(newS);
|
||||
added.insert(newS->id());
|
||||
@@ -1823,11 +1823,11 @@ Transform Memory::computeIcpTransform(int oldId, int newId, Transform guess, boo
|
||||
else
|
||||
{
|
||||
//Depth required, if not in RAM, load it from LTM
|
||||
if(oldS->getDepth2D().size() == 0 && added.find(oldS->id()) == added.end())
|
||||
if(oldS->getDepth2DCompressed().empty() && added.find(oldS->id()) == added.end())
|
||||
{
|
||||
depthToLoad.push_back(oldS);
|
||||
}
|
||||
if(newS->getDepth2D().size() == 0 && added.find(newS->id()) == added.end())
|
||||
if(newS->getDepth2DCompressed().empty() && added.find(newS->id()) == added.end())
|
||||
{
|
||||
depthToLoad.push_back(newS);
|
||||
}
|
||||
@@ -1846,22 +1846,22 @@ Transform Memory::computeIcpTransform(int oldId, int newId, Transform guess, boo
|
||||
{
|
||||
if(oldS->getDepthRaw().empty())
|
||||
{
|
||||
oldS->setDepthRaw(util3d::uncompressImage(oldS->getDepth()));
|
||||
oldS->setDepthRaw(util3d::uncompressImage(oldS->getDepthCompressed()));
|
||||
}
|
||||
if(newS->getDepthRaw().empty())
|
||||
{
|
||||
newS->setDepthRaw(util3d::uncompressImage(newS->getDepth()));
|
||||
newS->setDepthRaw(util3d::uncompressImage(newS->getDepthCompressed()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(oldS->getDepth2DRaw().empty())
|
||||
{
|
||||
oldS->setDepth2DRaw(util3d::uncompressData(oldS->getDepth2D()));
|
||||
oldS->setDepth2DRaw(util3d::uncompressData(oldS->getDepth2DCompressed()));
|
||||
}
|
||||
if(newS->getDepth2DRaw().empty())
|
||||
{
|
||||
newS->setDepth2DRaw(util3d::uncompressData(newS->getDepth2D()));
|
||||
newS->setDepth2DRaw(util3d::uncompressData(newS->getDepth2DCompressed()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2089,7 +2089,7 @@ Transform Memory::computeScanMatchingTransform(
|
||||
{
|
||||
Signature * s = _getSignature(iter->first);
|
||||
UASSERT(s != 0);
|
||||
if(s->getDepth2D().size() == 0)
|
||||
if(s->getDepth2DCompressed().empty())
|
||||
{
|
||||
depthToLoad.push_back(s);
|
||||
}
|
||||
@@ -2106,9 +2106,9 @@ Transform Memory::computeScanMatchingTransform(
|
||||
if(iter->first != newId)
|
||||
{
|
||||
const Signature * s = this->getSignature(iter->first);
|
||||
if(s->getDepth2D().size())
|
||||
if(!s->getDepth2DCompressed().empty())
|
||||
{
|
||||
*assembledOldClouds += *util3d::cvMat2Cloud(util3d::uncompressData(s->getDepth2D()), iter->second);
|
||||
*assembledOldClouds += *util3d::cvMat2Cloud(util3d::uncompressData(s->getDepth2DCompressed()), iter->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2127,7 +2127,7 @@ Transform Memory::computeScanMatchingTransform(
|
||||
const Signature * newS = getSignature(newId);
|
||||
pcl::PointCloud<pcl::PointXYZ>::Ptr newCloud;
|
||||
UASSERT(uContains(poses, newId));
|
||||
newCloud = util3d::cvMat2Cloud(util3d::uncompressData(newS->getDepth2D()), poses.at(newId));
|
||||
newCloud = util3d::cvMat2Cloud(util3d::uncompressData(newS->getDepth2DCompressed()), poses.at(newId));
|
||||
|
||||
//voxelize
|
||||
if(newCloud->size() && _icp2VoxelSize > 0.0f)
|
||||
@@ -2394,7 +2394,7 @@ void Memory::rehearsal(Signature * signature, Statistics * stats)
|
||||
{
|
||||
UFATAL("Signature %d null?!?", id);
|
||||
}
|
||||
float sim = signature->compareTo(sB);
|
||||
float sim = signature->compareTo(*sB);
|
||||
|
||||
int merged = 0;
|
||||
if(sim >= _similarityThreshold)
|
||||
@@ -2556,13 +2556,13 @@ int Memory::getMapId(int signatureId) const
|
||||
return mapId;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> Memory::getImage(int signatureId) const
|
||||
cv::Mat Memory::getImageCompressed(int signatureId) const
|
||||
{
|
||||
std::vector<unsigned char> image;
|
||||
cv::Mat image;
|
||||
const Signature * s = this->getSignature(signatureId);
|
||||
if(s)
|
||||
{
|
||||
image = s->getImage();
|
||||
image = s->getImageCompressed();
|
||||
}
|
||||
if(image.empty() && this->isRawDataKept() && _dbDriver)
|
||||
{
|
||||
@@ -2576,7 +2576,7 @@ Signature Memory::getSignatureData(int locationId, bool uncompressedData)
|
||||
UDEBUG("");
|
||||
Signature r;
|
||||
Signature * s = this->_getSignature(locationId);
|
||||
if(s && s->getImage().size())
|
||||
if(s && !s->getImageCompressed().empty())
|
||||
{
|
||||
r = *s;
|
||||
}
|
||||
@@ -2600,7 +2600,7 @@ Signature Memory::getSignatureData(int locationId, bool uncompressedData)
|
||||
if(signatures.size())
|
||||
{
|
||||
Signature * sTmp = signatures.front();
|
||||
if(sTmp->getImage().size() == 0)
|
||||
if(sTmp->getImageCompressed().empty())
|
||||
{
|
||||
_dbDriver->loadNodeData(signatures, !sTmp->getPose().isNull());
|
||||
}
|
||||
@@ -2619,7 +2619,7 @@ Signature Memory::getSignatureData(int locationId, bool uncompressedData)
|
||||
}
|
||||
UDEBUG("");
|
||||
|
||||
if(uncompressedData && r.getImageRaw().empty() && r.getImage().size())
|
||||
if(uncompressedData && r.getImageRaw().empty() && !r.getImageCompressed().empty())
|
||||
{
|
||||
//uncompress data
|
||||
if(s)
|
||||
@@ -2961,25 +2961,25 @@ void Memory::copyData(const Signature * from, Signature * to)
|
||||
|
||||
if(from->isSaved() && _dbDriver)
|
||||
{
|
||||
std::vector<unsigned char> image;
|
||||
std::vector<unsigned char> depth;
|
||||
std::vector<unsigned char> depth2d;
|
||||
cv::Mat image;
|
||||
cv::Mat depth;
|
||||
cv::Mat depth2d;
|
||||
float fx, fy, cx, cy;
|
||||
Transform localTransform;
|
||||
_dbDriver->getNodeData(from->id(), image, depth, depth2d, fx, fy, cx, cy, localTransform);
|
||||
|
||||
to->setImage(image);
|
||||
to->setDepth(depth, fx, fy, cx, cy);
|
||||
to->setDepth2D(depth2d);
|
||||
to->setImageCompressed(image);
|
||||
to->setDepthCompressed(depth, fx, fy, cx, cy);
|
||||
to->setDepth2DCompressed(depth2d);
|
||||
to->setLocalTransform(localTransform);
|
||||
|
||||
UDEBUG("Loaded image data from database");
|
||||
}
|
||||
else
|
||||
{
|
||||
to->setImage(from->getImage());
|
||||
to->setDepth(from->getDepth(), from->getDepthFx(), from->getDepthFy(), from->getDepthCx(), from->getDepthCy());
|
||||
to->setDepth2D(from->getDepth2D());
|
||||
to->setImageCompressed(from->getImageCompressed());
|
||||
to->setDepthCompressed(from->getDepthCompressed(), from->getDepthFx(), from->getDepthFy(), from->getDepthCx(), from->getDepthCy());
|
||||
to->setDepth2DCompressed(from->getDepth2DCompressed());
|
||||
to->setLocalTransform(from->getLocalTransform());
|
||||
}
|
||||
|
||||
@@ -3400,7 +3400,7 @@ Signature * Memory::createSignature(const SensorData & data, bool keepRawData, S
|
||||
words,
|
||||
words3D,
|
||||
data.pose(),
|
||||
util3d::compressData(data.depth2d()));
|
||||
util3d::compressData2(data.depth2d()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -858,7 +858,7 @@ bool Rtabmap::process(const SensorData & data)
|
||||
//============================================================
|
||||
if(_scanMatchingSize>0 &&
|
||||
signature->getNeighbors().size() == 1 &&
|
||||
signature->getDepth2D().size() &&
|
||||
!signature->getDepth2DCompressed().empty() &&
|
||||
rehearsedId == 0) // don't do it if rehearsal happened
|
||||
{
|
||||
UINFO("Odometry correction by scan matching (size=%d)...", _scanMatchingSize);
|
||||
@@ -1382,7 +1382,7 @@ bool Rtabmap::process(const SensorData & data)
|
||||
int localSpaceNearestId = 0;
|
||||
if(_lcHypothesisId == 0 &&
|
||||
_localLoopClosureDetectionSpace &&
|
||||
signature->getDepth2D().size())
|
||||
!signature->getDepth2DCompressed().empty())
|
||||
{
|
||||
//============================================================
|
||||
// Scan matching LOCAL LOOP CLOSURE SPACE
|
||||
|
||||
@@ -57,9 +57,9 @@ Signature::Signature(
|
||||
const std::multimap<int, cv::KeyPoint> & words,
|
||||
const std::multimap<int, pcl::PointXYZ> & words3, // in base_link frame (localTransform applied)
|
||||
const Transform & pose,
|
||||
const std::vector<unsigned char> & depth2D, // in base_link frame
|
||||
const std::vector<unsigned char> & image, // in camera_link frame
|
||||
const std::vector<unsigned char> & depth, // in camera_link frame
|
||||
const cv::Mat & depth2DCompressed, // in base_link frame
|
||||
const cv::Mat & imageCompressed, // in camera_link frame
|
||||
const cv::Mat & depthCompressed, // in camera_link frame
|
||||
float fx,
|
||||
float fy,
|
||||
float cx,
|
||||
@@ -73,9 +73,9 @@ Signature::Signature(
|
||||
_neighborsModified(true),
|
||||
_words(words),
|
||||
_enabled(false),
|
||||
_image(image),
|
||||
_depth(depth),
|
||||
_depth2D(depth2D),
|
||||
_imageCompressed(imageCompressed),
|
||||
_depthCompressed(depthCompressed),
|
||||
_depth2DCompressed(depth2DCompressed),
|
||||
_fx(fx),
|
||||
_fy(fy),
|
||||
_cx(cx),
|
||||
@@ -88,7 +88,7 @@ Signature::Signature(
|
||||
|
||||
Signature::~Signature()
|
||||
{
|
||||
//ULOGGER_DEBUG("id=%d", _id);
|
||||
//UDEBUG("id=%d", _id);
|
||||
}
|
||||
|
||||
void Signature::addNeighbors(const std::map<int, Transform> & neighbors)
|
||||
@@ -165,10 +165,10 @@ void Signature::changeLoopClosureId(int idFrom, int idTo)
|
||||
}
|
||||
|
||||
|
||||
float Signature::compareTo(const Signature * s) const
|
||||
float Signature::compareTo(const Signature & s) const
|
||||
{
|
||||
float similarity = 0.0f;
|
||||
const std::multimap<int, cv::KeyPoint> & words = s->getWords();
|
||||
const std::multimap<int, cv::KeyPoint> & words = s.getWords();
|
||||
if(words.size() != 0 && _words.size() != 0)
|
||||
{
|
||||
std::list<std::pair<int, std::pair<cv::KeyPoint, cv::KeyPoint> > > pairs;
|
||||
@@ -217,10 +217,10 @@ void Signature::removeWord(int wordId)
|
||||
_words3.erase(wordId);
|
||||
}
|
||||
|
||||
void Signature::setDepth(const std::vector<unsigned char> & depth, float fx, float fy, float cx, float cy)
|
||||
void Signature::setDepthCompressed(const cv::Mat & bytes, float fx, float fy, float cx, float cy)
|
||||
{
|
||||
UASSERT_MSG(depth.empty() || (!depth.empty() && fx > 0.0f && fy > 0.0f && cx >= 0.0f && cy >= 0.0f), uFormat("fx=%f fy=%f cx=%f cy=%f",fx,fy,cx,cy).c_str());
|
||||
_depth = depth;
|
||||
UASSERT_MSG(bytes.empty() || (!bytes.empty() && fx > 0.0f && fy > 0.0f && cx >= 0.0f && cy >= 0.0f), uFormat("fx=%f fy=%f cx=%f cy=%f",fx,fy,cx,cy).c_str());
|
||||
_depthCompressed = bytes;
|
||||
_fx=fx;
|
||||
_fy=fy;
|
||||
_cx=cx;
|
||||
@@ -247,53 +247,53 @@ void Signature::uncompressData()
|
||||
uncompressData(&_imageRaw, &_depthRaw, &_depth2DRaw);
|
||||
}
|
||||
|
||||
void Signature::uncompressData(cv::Mat * image, cv::Mat * depth, cv::Mat * depth2D) const
|
||||
void Signature::uncompressData(cv::Mat * imageRaw, cv::Mat * depthRaw, cv::Mat * depth2DRaw) const
|
||||
{
|
||||
if(image)
|
||||
if(imageRaw)
|
||||
{
|
||||
*image = _imageRaw;
|
||||
*imageRaw = _imageRaw;
|
||||
}
|
||||
if(depth)
|
||||
if(depthRaw)
|
||||
{
|
||||
*depth = _depthRaw;
|
||||
*depthRaw = _depthRaw;
|
||||
}
|
||||
if(depth2D)
|
||||
if(depth2DRaw)
|
||||
{
|
||||
*depth2D = _depth2DRaw;
|
||||
*depth2DRaw = _depth2DRaw;
|
||||
}
|
||||
if( (image && image->empty()) ||
|
||||
(depth && depth->empty()) ||
|
||||
(depth2D && depth2D->empty()))
|
||||
if( (imageRaw && imageRaw->empty()) ||
|
||||
(depthRaw && depthRaw->empty()) ||
|
||||
(depth2DRaw && depth2DRaw->empty()))
|
||||
{
|
||||
util3d::CompressionThread ctImage(&_image, true);
|
||||
util3d::CompressionThread ctDepth(&_depth, true);
|
||||
util3d::CompressionThread ctDepth2D(&_depth2D, false);
|
||||
if(image && image->empty())
|
||||
util3d::CompressionThread ctImage(_imageCompressed, true);
|
||||
util3d::CompressionThread ctDepth(_depthCompressed, true);
|
||||
util3d::CompressionThread ctDepth2D(_depth2DCompressed, false);
|
||||
if(imageRaw && imageRaw->empty())
|
||||
{
|
||||
ctImage.start();
|
||||
}
|
||||
if(depth && depth->empty())
|
||||
if(depthRaw && depthRaw->empty())
|
||||
{
|
||||
ctDepth.start();
|
||||
}
|
||||
if(depth2D && depth2D->empty())
|
||||
if(depth2DRaw && depth2DRaw->empty())
|
||||
{
|
||||
ctDepth2D.start();
|
||||
}
|
||||
ctImage.join();
|
||||
ctDepth.join();
|
||||
ctDepth2D.join();
|
||||
if(image && image->empty())
|
||||
if(imageRaw && imageRaw->empty())
|
||||
{
|
||||
*image = ctImage.getUncompressedData();
|
||||
*imageRaw = ctImage.getUncompressedData();
|
||||
}
|
||||
if(depth && depth->empty())
|
||||
if(depthRaw && depthRaw->empty())
|
||||
{
|
||||
*depth = ctDepth.getUncompressedData();
|
||||
*depthRaw = ctDepth.getUncompressedData();
|
||||
}
|
||||
if(depth2D && depth2D->empty())
|
||||
if(depth2DRaw && depth2DRaw->empty())
|
||||
{
|
||||
*depth2D = ctDepth2D.getUncompressedData();
|
||||
*depth2DRaw = ctDepth2D.getUncompressedData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@ namespace util3d
|
||||
|
||||
// format : ".png" ".jpg" "" (empty is general)
|
||||
CompressionThread::CompressionThread(const cv::Mat & mat, const std::string & format) :
|
||||
constCompressedData_(0),
|
||||
uncompressedData_(mat),
|
||||
format_(format),
|
||||
image_(!format.empty()),
|
||||
@@ -75,8 +74,8 @@ CompressionThread::CompressionThread(const cv::Mat & mat, const std::string & fo
|
||||
UASSERT(format.empty() || format.compare(".png") == 0 || format.compare(".jpg") == 0);
|
||||
}
|
||||
// assume image
|
||||
CompressionThread::CompressionThread(const std::vector<unsigned char> * bytes, bool isImage) :
|
||||
constCompressedData_(bytes),
|
||||
CompressionThread::CompressionThread(const cv::Mat & bytes, bool isImage) :
|
||||
compressedData_(bytes),
|
||||
image_(isImage),
|
||||
compressMode_(false)
|
||||
{}
|
||||
@@ -88,25 +87,25 @@ void CompressionThread::mainLoop()
|
||||
{
|
||||
if(image_)
|
||||
{
|
||||
compressedData_ = compressImage(uncompressedData_, format_);
|
||||
compressedData_ = compressImage2(uncompressedData_, format_);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressedData_ = compressData(uncompressedData_);
|
||||
compressedData_ = compressData2(uncompressedData_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // uncompress
|
||||
{
|
||||
if(constCompressedData_ && constCompressedData_->size())
|
||||
if(!compressedData_.empty())
|
||||
{
|
||||
if(image_)
|
||||
{
|
||||
uncompressedData_ = uncompressImage(*constCompressedData_);
|
||||
uncompressedData_ = uncompressImage(compressedData_);
|
||||
}
|
||||
else
|
||||
{
|
||||
uncompressedData_ = uncompressData(*constCompressedData_);
|
||||
uncompressedData_ = uncompressData(compressedData_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1105,6 +1104,31 @@ std::vector<unsigned char> compressImage(const cv::Mat & image, const std::strin
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// ".png" or ".jpg"
|
||||
cv::Mat compressImage2(const cv::Mat & image, const std::string & format)
|
||||
{
|
||||
std::vector<unsigned char> bytes = compressImage(image, format);
|
||||
if(bytes.size())
|
||||
{
|
||||
return cv::Mat(1, bytes.size(), CV_8UC1, bytes.data()).clone();
|
||||
}
|
||||
return cv::Mat();
|
||||
}
|
||||
|
||||
cv::Mat uncompressImage(const cv::Mat & bytes)
|
||||
{
|
||||
cv::Mat image;
|
||||
if(!bytes.empty())
|
||||
{
|
||||
#if CV_MAJOR_VERSION >=2 && CV_MINOR_VERSION >=4
|
||||
image = cv::imdecode(bytes, cv::IMREAD_UNCHANGED);
|
||||
#else
|
||||
image = cv::imdecode(bytes, -1);
|
||||
#endif
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
cv::Mat uncompressImage(const std::vector<unsigned char> & bytes)
|
||||
{
|
||||
cv::Mat image;
|
||||
@@ -1150,20 +1174,61 @@ std::vector<unsigned char> compressData(const cv::Mat & data)
|
||||
return bytes;
|
||||
}
|
||||
|
||||
cv::Mat compressData2(const cv::Mat & data)
|
||||
{
|
||||
cv::Mat bytes;
|
||||
if(!data.empty())
|
||||
{
|
||||
uLong sourceLen = uLong(data.total())*uLong(data.elemSize());
|
||||
uLong destLen = compressBound(sourceLen);
|
||||
bytes = cv::Mat(1, destLen+3*sizeof(int), CV_8UC1);
|
||||
int errCode = compress(
|
||||
(Bytef *)bytes.data,
|
||||
&destLen,
|
||||
(const Bytef *)data.data,
|
||||
sourceLen);
|
||||
bytes = cv::Mat(bytes, cv::Rect(0,0, destLen+3*sizeof(int), 1));
|
||||
*((int*)&bytes.data[destLen]) = data.rows;
|
||||
*((int*)&bytes.data[destLen+sizeof(int)]) = data.cols;
|
||||
*((int*)&bytes.data[destLen+2*sizeof(int)]) = data.type();
|
||||
|
||||
if(errCode == Z_MEM_ERROR)
|
||||
{
|
||||
UERROR("Z_MEM_ERROR : Insufficient memory.");
|
||||
}
|
||||
else if(errCode == Z_BUF_ERROR)
|
||||
{
|
||||
UERROR("Z_BUF_ERROR : The buffer dest was not large enough to hold the uncompressed data.");
|
||||
}
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
cv::Mat uncompressData(const cv::Mat & bytes)
|
||||
{
|
||||
UASSERT(bytes.empty() || bytes.type() == CV_8UC1);
|
||||
return uncompressData(bytes.data, bytes.cols*bytes.rows);
|
||||
}
|
||||
|
||||
cv::Mat uncompressData(const std::vector<unsigned char> & bytes)
|
||||
{
|
||||
return uncompressData(bytes.data(), bytes.size());
|
||||
}
|
||||
|
||||
cv::Mat uncompressData(const unsigned char * bytes, unsigned long size)
|
||||
{
|
||||
cv::Mat data;
|
||||
if(bytes.size()>=3*sizeof(int))
|
||||
if(bytes && size>=3*sizeof(int))
|
||||
{
|
||||
//last 3 int elements are matrix size and type
|
||||
int height = *((int*)&bytes[bytes.size()-3*sizeof(int)]);
|
||||
int width = *((int*)&bytes[bytes.size()-2*sizeof(int)]);
|
||||
int type = *((int*)&bytes[bytes.size()-1*sizeof(int)]);
|
||||
int height = *((int*)&bytes[size-3*sizeof(int)]);
|
||||
int width = *((int*)&bytes[size-2*sizeof(int)]);
|
||||
int type = *((int*)&bytes[size-1*sizeof(int)]);
|
||||
|
||||
// If the size is higher, it may be a wrong data format.
|
||||
UASSERT_MSG(height>=0 && height<10000 &&
|
||||
width>=0 && width<10000,
|
||||
uFormat("size=%d, height=%d width=%d type=%d", bytes.size(), height, width, type).c_str());
|
||||
uFormat("size=%d, height=%d width=%d type=%d", size, height, width, type).c_str());
|
||||
|
||||
data = cv::Mat(height, width, type);
|
||||
uLongf totalUncompressed = uLongf(data.total())*uLongf(data.elemSize());
|
||||
@@ -1171,8 +1236,8 @@ cv::Mat uncompressData(const std::vector<unsigned char> & bytes)
|
||||
int errCode = uncompress(
|
||||
(Bytef*)data.data,
|
||||
&totalUncompressed,
|
||||
(const Bytef*)bytes.data(),
|
||||
uLong(bytes.size()));
|
||||
(const Bytef*)bytes,
|
||||
uLong(size));
|
||||
|
||||
if(errCode == Z_MEM_ERROR)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user