MeVisLab Toolbox Reference
mlPCLMLTools.h
Go to the documentation of this file.
1// Copyright (c) Fraunhofer MEVIS, Germany. All rights reserved.
2// **InsertLicense** code author="Wolf Spindler"
3//----------------------------------------------------------------------------------
5
12//----------------------------------------------------------------------------------
13#pragma once
14
16#include <mlPCLTypes.h>
17#include <mlPCLSupportTools.h>
18#include <mlModuleIncludes.h>
20
21#include <mlPointList.h>
22#include <mlVectorList.h>
23#include <mlXMarkerList.h>
24
26
27class SubImage;
28class PagedImage;
29
31namespace PCLMLTools {
32
33
34//----------------------------------------------------------------------------------
37//----------------------------------------------------------------------------------
39 const MLTypeData* voxVal);
40
41//----------------------------------------------------------------------------------
45// Adapt this if a new PCL point type is integrated in the MeVisLab binding.
46//----------------------------------------------------------------------------------
48inline void setVectorReplacement(pcl::PointXYZ & /*p*/, const Vector3f & /*vf*/)
49{
50 // There is no member which could be used for the vector, do not assign anything.
51}
52
53// Handle all other point types generically.
54template <typename PCL_POINT_TYPE>
56{
57 p.normal_x = vf[0];
58 p.normal_y = vf[1];
59 p.normal_z = vf[2];
60}
62
63//----------------------------------------------------------------------------------
65//----------------------------------------------------------------------------------
67{
70 thresholdMin(0.), thresholdMax(0.),
71 lowerValue(0.), upperValue(0.),
72 skipVoxelsBelowMin(false),
73 skipVoxelsAboveMax(false),
74 normalizeInClampedRange(false),
75 useVectorLengthAsIntensity(false),
76 transformToWorld(false){};
77
81
85
87 double lowerValue;
88
90 double upperValue;
91
94
97
102
107
112};
113
114
115//----------------------------------------------------------------------------------
121//----------------------------------------------------------------------------------
122template <typename POINT_CLOUD_TYPE>
124 const Matrix4 &voxelToWorldMatrix,
125 bool toWorld)
126{
127 typedef typename POINT_CLOUD_TYPE::PointType PointType;
129 mapProps.setVoxelToWorldMatrix(voxelToWorldMatrix);
130 const size_t numPoints = pointCloud.points.size();
131 Vector3 pnt;
132 for (size_t c=0; c < numPoints; ++c){
133 PointType &pclPoint = pointCloud.points[c];
135 if (toWorld){
136 pnt = mapProps.mapVoxelToWorld(pnt);
137 }
138 else{
139 pnt = mapProps.mapWorldToVoxel(pnt);
140 }
141 pclPoint.x = static_cast<float>(pnt[0]);
142 pclPoint.y = static_cast<float>(pnt[1]);
143 pclPoint.z = static_cast<float>(pnt[2]);
144 }
145}
146
147//----------------------------------------------------------------------------------
156//----------------------------------------------------------------------------------
157template <typename POINT_CLOUD_PTR_TYPE>
161{
162 bool allAddedRet = true;
163 const MLTypeInfos* dataTypeInfos = subImg.getDataTypeInfos();
164 if (dataTypeInfos && subImg.getData() && retPointCloudPtr){
165
166 const MLDataType dt = subImg.getDataType();
167 const bool isVectorType = MLIsScalarType(dt) ? false : true;
168 double scale=0;
169 if (convParams.normalizeInClampedRange){
170 const double range = convParams.thresholdMax - convParams.thresholdMin;
171 if (range < 10e-10){
172 scale = 1.;
173 }
174 else{
175 scale = 1. / range;
176 }
177 }
178 typedef typename POINT_CLOUD_PTR_TYPE::element_type::PointType PointType;
179 typedef typename POINT_CLOUD_PTR_TYPE::element_type::VectorType PointVectorType;
181 tmpAddedPoints.reserve(20000);
182 const SubImageBox subImgBox = subImg.getBox();
183 ImageVector p = subImgBox.v1;
186 //for (p.u = subImgBox.v1.u; p.u <= subImgBox.v2.u; ++p.u){
187 //for (p.t = subImgBox.v1.t; p.t <= subImgBox.v2.t; ++p.t){
188 //for (p.c = subImgBox.v1.c; p.c <= subImgBox.v2.c; ++p.c){
189 for (p.z = subImgBox.v1.z; p.z <= subImgBox.v2.z; ++p.z){
190 for (p.y = subImgBox.v1.y; p.y <= subImgBox.v2.y; ++p.y){
191 for (p.x = subImgBox.v1.x; p.x <= subImgBox.v2.x; ++p.x){
192
193 // Get value from the image as generic voxel MLTypeData and determine
194 // whether the value interpreted as double shall be taken or
195 // alternatively the length of a vector if we have one.
196 const MLTypeData* voxVal = reinterpret_cast<MLTypeData*>(subImg.getImagePointer(p));
197 double dblVal = 0;
198 if (isVectorType){
200 }
201 dblVal = isVectorType && convParams.useVectorLengthAsIntensity ?
202 vec3fVal.length() :
203 dataTypeInfos->castToDouble(voxVal);
204
205 // Do clamping and scaling.
206 bool add = true;
207 if (dblVal < convParams.thresholdMin){
208 if (convParams.skipVoxelsBelowMin){
209 add = false;
210 }
211 else{
212 dblVal = convParams.lowerValue;
213 }
214 }
215 if (dblVal > convParams.thresholdMax){
216 if (convParams.skipVoxelsAboveMax){
217 add = false;
218 }
219 else{
220 dblVal = convParams.upperValue;
221 }
222 }
223
224 // Append point with coordinates and intensity.
225 if (!add){
226 allAddedRet = false;
227 }
228 else{
229 valToAppend.x = static_cast<float>(p.x);
230 valToAppend.y = static_cast<float>(p.y);
231 valToAppend.z = static_cast<float>(p.z);
232 if (convParams.normalizeInClampedRange){
233 if (dblVal < convParams.thresholdMin){ dblVal = convParams.thresholdMin; }
234 if (dblVal > convParams.thresholdMax){ dblVal = convParams.thresholdMax; }
235 dblVal = (dblVal-convParams.thresholdMin)*scale;
236 }
237 valToAppend.data[3] = 1.0f;
238 PCLSupportTools::setIntensityReplacement(valToAppend, static_cast<float>(dblVal));
239 if (isVectorType){
241 }
242 tmpAddedPoints.push_back(valToAppend);
243 }
244 }
245 }
246 }
247 //}
248 //}
249 //}
250 if (tmpAddedPoints.size() > 0){
251 const MLuint64 newSize = static_cast<MLuint64>(retPointCloudPtr->width) + tmpAddedPoints.size();
252 if (newSize < PCLSupportTools::getUnsigned32BitMaximumLimit()){
254 retPointCloudPtr->height = 1;
255 retPointCloudPtr->points.insert(retPointCloudPtr->points.end(), tmpAddedPoints.begin(), tmpAddedPoints.end());
256 }
257 else{
258 ML_PRINT_ERROR("mlPCLMLTools.cpp: appendSubImageVoxelsToPointCloud",
260 "Could not add points to point cloud since this would exceed "
261 "the maximum number UINT32_MAX points in a point cloud.");
262 }
263 }
264 }
265 return allAddedRet;
266}
267
268//----------------------------------------------------------------------------------
274//----------------------------------------------------------------------------------
275template <typename POINT_CLOUD_PTR_TYPE>
279{
280 typedef typename POINT_CLOUD_PTR_TYPE::element_type POINT_CLOUD_TYPE;
283 SubImage subImage(inImg.getBoxFromImageExtent(), inImg.getDataType(), nullptr);
284 subImage.allocateAsMemoryBlockHandle(ML_RETURN_NULL);
285 bool isOrganized = false;
286 if (subImage.getData()){
287 retErr = inImg.getTile(subImage);
288 if (ML_RESULT_OK == retErr){
290
291 // If all voxels have been added then we can set the height of the point cloud to mark it as organized.
293 (subImage.getNumVoxels() <= static_cast<MLint>(PCLSupportTools::getUnsigned32BitMaximumLimit()))){
294 retPointCloudPtr->width = mlrange_cast<MLuint32>(subImage.getExtent().x);
295 retPointCloudPtr->height = mlrange_cast<MLuint32>(subImage.getExtent().y * subImage.getExtent().z);
296 }
297 }
298 }
299 if (convParams.transformToWorld){
300 transformTo(*retPointCloudPtr, inImg.getVoxelToWorldMatrix(), true);
301 }
302 return retErr;
303}
304
306// Adapt this if a new PCL point type is integrated in the MeVisLab binding.
307//----------------------------------------------------------------------------------
310//----------------------------------------------------------------------------------
311template <typename POINT_TYPE>
313{
314 point.data[0] = static_cast<float>(xMarker.pos[0]);
315 point.data[1] = static_cast<float>(xMarker.pos[1]);
316 point.data[2] = static_cast<float>(xMarker.pos[2]);
317 point.data[3] = 1.0f;
318}
319
320//----------------------------------------------------------------------------------
326//----------------------------------------------------------------------------------
327inline void assignPointDataFromXMarker(const XMarker &xMarker, pcl::PointXYZLNormal &point)
328{
329 point.data[0] = static_cast<float>(xMarker.pos[0]);
330 point.data[1] = static_cast<float>(xMarker.pos[1]);
331 point.data[2] = static_cast<float>(xMarker.pos[2]);
332 point.data[3] = 1.0f;
333 point.data_n[0] = static_cast<float>(xMarker.vec[0]);
334 point.data_n[1] = static_cast<float>(xMarker.vec[1]);
335 point.data_n[2] = static_cast<float>(xMarker.vec[2]);
336 point.data_n[3] = 0.0f;
337 point.label = static_cast<unsigned int>(xMarker.type);
338}
339
340//----------------------------------------------------------------------------------
346//----------------------------------------------------------------------------------
347inline void assignPointDataFromXMarker(const XMarker &xMarker, pcl::PointXYZRGBNormal &point)
348{
349 point.data[0] = static_cast<float>(xMarker.pos[0]);
350 point.data[1] = static_cast<float>(xMarker.pos[1]);
351 point.data[2] = static_cast<float>(xMarker.pos[2]);
352 point.data[3] = 1.0f;
353 point.data_n[0] = static_cast<float>(xMarker.vec[0]);
354 point.data_n[1] = static_cast<float>(xMarker.vec[1]);
355 point.data_n[2] = static_cast<float>(xMarker.vec[2]);
356 point.data_n[3] = 0.0f;
357 point.rgba = static_cast<unsigned int>(xMarker.type);
358}
359
360//----------------------------------------------------------------------------------
366//----------------------------------------------------------------------------------
367inline void assignPointDataFromXMarker(const XMarker &xMarker, pcl::PointXYZINormal &point)
368{
369 point.data[0] = static_cast<float>(xMarker.pos[0]);
370 point.data[1] = static_cast<float>(xMarker.pos[1]);
371 point.data[2] = static_cast<float>(xMarker.pos[2]);
372 point.data[3] = 1.0f;
373 point.data_n[0] = static_cast<float>(xMarker.vec[0]);
374 point.data_n[1] = static_cast<float>(xMarker.vec[1]);
375 point.data_n[2] = static_cast<float>(xMarker.vec[2]);
376 point.data_n[3] = 0.0f;
377 point.intensity = static_cast<float>(xMarker.type);
378}
380
381//----------------------------------------------------------------------------------
389//----------------------------------------------------------------------------------
390template <typename POINT_CLOUD_PTR_TYPE>
393{
394 if (!inBaseList){
395 retPointCloudPtr.reset();
396 }
397 else{
398 // Check for list-like base types.
403
404 if (pl || vl || xml || xmlc){
405 // Create a new point cloud if we have an input object, even if it is empty.
406 typedef typename POINT_CLOUD_PTR_TYPE::element_type POINT_CLOUD_TYPE;
408
409 // Get number of points from list.
410 const MLssize_t numVals = (pl ? pl->getNum() :
411 (vl ? vl->getNum() :
412 (xml ? mlrange_cast<MLssize_t>(xml->size()) :
413 (xmlc ? mlrange_cast<MLssize_t>(const_cast<XMarkerListContainer*>(xmlc)->getList()->size()) : 0))));
414 if (static_cast<MLint>(numVals) > static_cast<MLint>(PCLSupportTools::getUnsigned32BitMaximumLimit())){
415 ML_PRINT_ERROR("mlPCLToMLTools.h: createPointCloudFromBaseList",
417 "Input point cloud has more than ML_UINT32_MAX entries; the "
418 "PointCloud.width parameter cannot be set to this value any more; "
419 "using ML_UINT32_MAX instead.");
420 retPointCloudPtr->width = static_cast<MLuint32>(PCLSupportTools::getUnsigned32BitMaximumLimit());
421 }
422 else{
423 retPointCloudPtr->width = static_cast<MLuint32>(numVals);
424 }
425 retPointCloudPtr->height = 1;
426 retPointCloudPtr->is_dense = true;
428
429
430 if (numVals > 0){
431 for (MLssize_t cs=0; cs < numVals; ++cs){
432 typename POINT_CLOUD_TYPE::PointType &point = retPointCloudPtr->points[static_cast<size_t>(cs)];
433
434 if (pl){
435 pl->getValue(cs, point.data[0], point.data[1], point.data[2]);
436 }
437 else if (vl){
438 int vecType=0;
439 vl->getPoint(cs, vecType, point.data[0], point.data[1], point.data[2]);
440 }
441 else if (xml || xmlc){
442 const XMarker &xMarker = xml ? (*static_cast<const XMarker*>(xml->getConstItemAt(cs))) :
443 (*static_cast<const XMarker*>(const_cast<XMarkerListContainer*>(xmlc)->getList()->getConstItemAt(cs)));
445 }
446 }
447 }
448 }
449 }
450}
451
452
453
455// Adapt this if a new PCL point type is integrated in the MeVisLab binding.
456//----------------------------------------------------------------------------------
459//----------------------------------------------------------------------------------
460template <typename POINT_TYPE>
462{
463 xMarker.pos[0] = point.data[0];
464 xMarker.pos[1] = point.data[1];
465 xMarker.pos[2] = point.data[2];
466}
467
468//----------------------------------------------------------------------------------
473//----------------------------------------------------------------------------------
474inline void assignXMarkerFromPointData(const pcl::PointXYZLNormal &point, XMarker &xMarker)
475{
476 xMarker.pos[0] = point.data[0];
477 xMarker.pos[1] = point.data[1];
478 xMarker.pos[2] = point.data[2];
479 xMarker.vec[0] = point.data_n[0];
480 xMarker.vec[1] = point.data_n[1];
481 xMarker.vec[2] = point.data_n[2];
482 xMarker.type = static_cast<int>(point.label);
483}
484
485//----------------------------------------------------------------------------------
490//----------------------------------------------------------------------------------
491inline void assignXMarkerFromPointData(const pcl::PointXYZRGBNormal &point, XMarker &xMarker)
492{
493 xMarker.pos[0] = point.data[0];
494 xMarker.pos[1] = point.data[1];
495 xMarker.pos[2] = point.data[2];
496 xMarker.vec[0] = point.data_n[0];
497 xMarker.vec[1] = point.data_n[1];
498 xMarker.vec[2] = point.data_n[2];
499 xMarker.type = static_cast<int>(point.rgba);
500}
501
502//----------------------------------------------------------------------------------
507//----------------------------------------------------------------------------------
508inline void assignXMarkerFromPointData(const pcl::PointXYZINormal &point, XMarker &xMarker)
509{
510 xMarker.pos[0] = point.data[0];
511 xMarker.pos[1] = point.data[1];
512 xMarker.pos[2] = point.data[2];
513 xMarker.vec[0] = point.data_n[0];
514 xMarker.vec[1] = point.data_n[1];
515 xMarker.vec[2] = point.data_n[2];
516 xMarker.type = static_cast<int>(point.intensity);
517}
519
520//----------------------------------------------------------------------------------
525//----------------------------------------------------------------------------------
526template <typename POINT_CLOUD_TYPE>
529{
530 outputList.clear();
531 const size_t numInputPoints = inputPointCloud.points.size();
533 for (size_t c=0; c < numInputPoints; ++c){
534 XMarker *xMarker = static_cast<XMarker*>(outputList.getItemAt(static_cast<MLssize_t>(c)));
536 }
537}
538
539};
540
542
Project global and OS specific declarations.
#define MLPCL_MLAdapters_EXPORT
If included by external modules, exported symbols are declared as import symbols.
Class representing general ML objects that support import/export via strings (setPersistentState() an...
Definition mlBase.h:59
This class encapsulates basic medical image properties:
void setVoxelToWorldMatrix(const Matrix4 &matrix)
Sets the matrix which transforms voxel to world coordinates to matrix.
Class which represents an image, which manages properties of an image and image data which is located...
Base object class PointList managing a list of points.
Definition mlPointList.h:29
This class manages/represents a rectangular 6d image region which is organized linearly in memory.
Definition mlSubImage.h:75
Forward declarations to resolve header file dependencies.
Definition mlVector3.h:66
void assign(const DT px, const DT py, const DT pz)
Sets all components to the passed values.
Definition mlVector3.h:172
Base object representing a list of vectors given as Vector4's.
Base object class XMarkerListContainer (derived from ListContainerTemplate) for XMarkerList objects.
Base object class XMarkerList (derived from BaseListTemplate) specialized for XMarker items.
Base object class XMarker (derived form baseItem) with 6D pos, 3D vec and type int.
MLint32 MLDataType
MLDataType.
Definition mlTypeDefs.h:596
MLEXPORT MLint32 MLIsScalarType(MLDataType dataType)
Alternative name for MLIsStandardType.
#define ML_BAD_PARAMETER
A bad/invalid parameter (or even an inappropriate image) has been passed to a module or an algorithm;...
Definition mlTypeDefs.h:823
MLint32 MLErrorCode
Type of an ML Error code.
Definition mlTypeDefs.h:716
#define ML_NO_MEMORY
The system does not have enough memory to perform the desired operation; try to reduce application da...
Definition mlTypeDefs.h:735
#define ML_RESULT_OK
No error. Everything seems to be okay.
Definition mlTypeDefs.h:724
#define ML_PRINT_ERROR(FUNC_NAME, REASON, HANDLING)
Like ML_PRINT_ERROR_DUMP(FUNC_NAME, REASON, HANDLING, RT_OBJ) without a runtime object to be dumped.
A collection of tool functions used in MLPCLSupport.
Basic types used in the MeVislab binding of the Point Cloud Library(PCL).
Target mlrange_cast(Source arg)
Generic version of checked ML casts.
Tool class for some string operations.
UINT64 MLuint64
Introduce platform independent 64 bit unsigned integer type.
Definition mlTypeDefs.h:425
@ ML_RETURN_NULL
On allocation failure NULL is returned without error handling.
Definition mlTypeDefs.h:676
unsigned int MLuint32
Definition mlTypeDefs.h:185
unsigned char MLTypeData
This is the pointer type used to point to the data of MLType data instances.
MLint64 MLint
A signed ML integer type with at least 64 bits used for index calculations on very large images even ...
Definition mlTypeDefs.h:490
SSIZE_T MLssize_t
The signed ML size type which is a signed 32 bit size_t on 32 bit platforms and 64 bit one on 64 bit ...
Definition mlTypeDefs.h:566
void assignXMarkerFromPointData(const POINT_TYPE &point, XMarker &xMarker)
Generically assigns a point cloud point to an XMarker; only data[0] - data[2] are assigned from point...
MLErrorCode createPointCloudFromPagedImage(PagedImage &inImg, const ImageToPointCloudConversionParameters &convParams, POINT_CLOUD_PTR_TYPE &retPointCloudPtr)
Creates a point cloud from an ML image.
void convertPointCloudToXMarkerList(POINT_CLOUD_TYPE &inputPointCloud, XMarkerList &outputList)
Creates a point cloud from any of the following Base lists: PointList, VectorList,...
void assignPointDataFromXMarker(const XMarker &xMarker, POINT_TYPE &point)
Generically assigns an XMarker to a any at least 3D point cloud point; only data[0] - data[2] are ass...
void setVectorReplacement(pcl::PointXYZ &, const Vector3f &)
If the point type has any normal-like members then any vector components of an ML vector-like voxel t...
void transformTo(POINT_CLOUD_TYPE &pointCloud, const Matrix4 &voxelToWorldMatrix, bool toWorld)
Performs a voxelToWorld transformation of all point coordinates of pointCloud.
void createPointCloudFromBaseList(const Base *inBaseList, POINT_CLOUD_PTR_TYPE &retPointCloudPtr)
Creates a point cloud from any of the following Base lists: PointList, VectorList,...
MLPCL_MLAdapters_EXPORT Vector3f getVector3fFromVoxVal(MLDataType dt, const MLTypeData *voxVal)
Tries to get any sensible Vector3f from the given voxVal if it is of any ML vector type; otherwise a ...
bool appendSubImageVoxelsToPointCloud(const SubImage &subImg, const ImageToPointCloudConversionParameters &convParams, POINT_CLOUD_PTR_TYPE retPointCloudPtr)
Creates a point cloud from an ML SubImage.
Structure containing all data type features and pointers to all functions needed to implement operati...
A container with parameters for the conversion from ML images to point clouds.
double upperValue
Possibly used on voxels larger than thresholdMax; see thresholdMax for details.
bool useVectorLengthAsIntensity
If enabled then the length of a possibly existing normal vector is used instead of the incoming voxel...
ImageToPointCloudConversionParameters()
Default constructor fixing the defaults.
bool normalizeInClampedRange
If enabled then all voxel values are scaled from [lowerValue, upperValue] to [0,1]; values outside wi...
double thresholdMax
If any value is larger than thresholdMax and skipVoxelsAboveMax is false then the voxel is set to upp...
bool skipVoxelsAboveMax
Used when voxels are larger than thresholdMax; see thresholdMax for details.
bool skipVoxelsBelowMin
Used when voxels are smaller than thresholdMin; see thresholdMin for details.
bool transformToWorld
If enabled then all coordinates retrieved from voxel coordinates are translated world coordinates usi...
double lowerValue
Possibly used on voxels smaller than thresholdMin; see thresholdMin for details.
double thresholdMin
If any value is smaller than thresholdMin and skipVoxelsBelowMin is true then the voxel is not added ...