PCL: Populate Organized PointCloud by Index - c++

I have worked with PCL for a few days now, but cannot get around one Problem:
I got a dense, organized PointCloud<PointT> cloud_1 and want to populate a second, new PointCoud PointCloud<PointT> cloud_2 with processed Points.
So my idea was (in pseudocode, but of course I can provide MWE if it helps):
//cloud_1 is also a Ptr that gets a Cloud loaded from PCD File
PointCloud<PointT>::Ptr cloud_2(new PointCloud<PointT>)
void populateSecondCoud(PointCloud<PointT>& cloud_1, PointCloud<PointT>& cloud_2){
cloud_2.width = cloud_1.width;
cloud_2.height = cloud_1.height;
for (i in cloud_1.height){
for(j in cloud_1.width){
PointT p = cloud_1.at(i,j);
// do processing with the point...
cloud_2.at(i,j) = p
}
}
}
populateSecondCloud(*cloud_1, *cloud_2)
This terminates with :
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)
I guess, because the points-vector of cloud_2 is still completely empty.
Is there any way to iteratively populate an organized PointCloud?
All of that happens for a lot of PointClouds, that is why I try to prevent copying cloud_2 from cloud_1 before processing the points.
Any ideas are greatly appreciated. Of course I can provide a compiling code snippet, but I thought the problem gets clear from above pseudocode.
Edit: Clarified how cloud_2 is initialized.

There are 2 issues in your code:
1. Memory allocation:
You need to allocate cloud_2 with the proper size.
There is a pcl::PointCloud constructor that accepts the width and height and allocates the data accordingly, e.g.:
PointCloud<PointT>::Ptr cloud_2 = PointCloud<PointT>::Ptr cloud(
new PointCloud<PointT>(cloud_1.width, cloud_1.height));
You can also use the pcl::PointCloud::resize method to resize cloud_2 with new width and height inside populateSecondCoud:
cloud_2.resize(cloud_1.width, cloud_1.height);
2. Proper indexing:
As you can see in the pcl::PointCloud::at documentation,
the arguments for at are column, row (in that order).
You actually pass them in the reverse order, because your i in the row index and j the column index.
Therefore change lines containing:
at(i, j)
To:
at(j, i)

Related

C++: What is causing this stack smashing error?

Disclaimer: I have limited knowledge of C++ due to switching from a college where they didn't teach C++ to another where it was the only language that was taught.
I'm trying to implement the box counting method for a randomly generated 2D cluster in a lattice that's 54x54.
One of the requirements is that we use a 1D array to represent the 2D square lattice, so a transformation is required to associate x and y values (columns and lines, respectively) to the actual positions of the array.
The transformation is "i = x + y*N", with N being the length of the side of the square lattice (in this case, it would be 54) and i being the position of the array.
The box-counting method, simply put, involves splitting a grid into large squares that get progressively smaller and counting how many contain the cluster in each instance.
The code works in the way that it should for smaller lattice sizes, at least the ones that I could verify (for obvious reasons, I can't verify even a 10x10 lattice by hand). However, when I run it, the box size goes all the way to 1/37 and gives me a "stack smashing detected" error.
From what I understand, the error may have something to do with array sizes, but I've checked the points where the arrays are accessed and made sure they're within the actual dimensions of the array.
A "for" in the function "boxTransform(int grid[], int NNew, int div)" is responsible for the error in question, but I added other functions that I believe are relevant to it.
The rest of the code is just defining a lattice and isolating the aggregate, which is then passed to boxCounting(int grid[]), and creating a .dat file. Those work fine.
To "fit" the larger array into the smaller one, I divide each coordinate (x, y) by the ratio of squares on the large array to the small array. This is how my teacher explained it, and as mentioned before, works fine for smaller array sizes.
EDIT: Thanks to a comment by VTT, I went back and checked if the array index goes out of bounds with the code itself. It is indeed the case, which is likely the origin of the problem.
EDIT #2: It was indeed the origin of the problem. There was a slight error in the calculations that didn't appear for smaller lattice sizes (or I just missed it).
//grid[] is an array containing the cluster
//that I want to analyze.
void boxCounting(int grid[]) {
//N is a global constant; it's the length of the
//side of the square lattice that's being analyzed.
//NNew is the side of the larger squares. It will
//be increased until it reaches N
for (int NNew = 1; N - NNew > 0; NNew++) {
int div = N/NNew;
boxTransform(grid, NNew, div);
}
}
void boxTransform(int grid[], int NNew, int div) {
int gridNew[NNew*NNew];
//Here the array elements are set to zero, which
//I understand C++ cannot do natively
for (int i = 0; i < NNew*NNew; i++) {
gridNew[i] = 0;
}
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
if (grid[col + row*N] == 1) {
//This is where the error occurs. The idea here is
//that if a square on the initial grid is occupied,
//the corresponding square on the new grid will have
//its value increased by 1, so I can later check
//how many squares on the larger grid are occupied
gridNew[col/div + (row/div)*NNew]++;
}
}
}
int boxes = countBox(gridNew, NNew);
//Creates a .dat file with the relevant values
printResult(boxes, NNew);
}
int countBox(int grid[], int NNew) {
int boxes = 0;
//Any array values that weren't touched remain at zero,
//so I just have to check that it's greater than zero
//to know if the square is occupied or not
for(int i = 0; i < NNew*NNew; i++) {
if(grid[i] > 0) boxes++;
}
return boxes;
}
Unfortunately this is not enough information to find the exact problem for you but I will try to help.
There are like multiple reasons that you should use a dynamic array instead of the fixed size arrays that you are using except if it's required in your exercise.
If you've been learning other languages you might think that fixed array is good enough, but it's far more dangerous in C++ than in most of the languages.
int gridNew[NNew*NNew]; You should know that this is not valid according to C++ standard, only the GCC compiler made it work. In C++ you always have to know the size of the fixed arrays in compile time. Which means you can't use variables to declare an array.
You keep updating global variables to track the size of the array which makes your code super hard to read. You are probably doing this because you know that you are not able to query the size of the array once you pass it to a function.
For both of these problems a dynamic array is the perfect solution. The standard dynamic array implementation in C++ is the std::vector: https://en.cppreference.com/w/cpp/container/vector
When you create a vector you can define it's size and also you can query the length of the vector with the size() member function.
Even better: You can use the at() function instead of the square brackets([]) to get and element with an index which does bounds check for you and throws an exception if you provided an index which is out of bounds which helps a lot to locate these kind of errors. Because in C++ if you just simply provide an index which does not exist in an array it is an undefined behaviour which might be your problem.
I wouldn't like to write any more features of the vector because it's really easy to find examples on how to do these things, I just wanted to help you where to start.
VTT was right in his comment. There was a small issue with the transformation to fit the large array into the smaller one that made the index go out of bounds. I only checked this on pen and paper when I should've put it in the actual code, which is why I didn't notice it. Since he didn't post it as an answer, I'm doing so on his behalf.
The int gridNew[NNew*NNew]; bit was kind of a red herring, but I appreciate the lesson and will take that into account when coding in C++ in the future.

Some vector elements do not change

I am experiencing very strange behaviour, which I cannot explain. I hope someone might shed some light on it.
Code snippet first:
class TContour {
public:
typedef std::pair<int,int> TEdge; // an edge is defined by indices of vertices
typedef std::vector<TEdge> TEdges;
TEdges m_oEdges;
void splitEdge(int iEdgeIndex, int iMiddleVertexIndex) {
TEdge & oEdge = m_oEdges[iEdgeIndex];
m_oEdges.push_back(TEdge(oEdge.first, iMiddleVertexIndex));
oEdge = TEdge(oEdge.second, iMiddleVertexIndex); // !!! THE PROBLEM
};
void splitAllEdges(void) {
size_t iEdgesCnt = m_oEdges.size();
for (int i=0; i<iEdgesCnt; ++i) {
int iSomeVertexIndex = 10000; // some new value, not actually important
splitEdge(i, iSomeVertexIndex);
}
};
};
When I call splitAllEdges(), the original edges are changed and new edges are added (resulting in doubling the container size). Everything as expected, with an exception of 1 original edge, which does not change. Should that be of any interest, its index is 3 and value is [1,242]. All the other original edges change, but this one remains unchanged. Adding debug prints confirms that the edge is written with a different value, but m_oEdges contents does not change.
I have a simple workaround, replacing the problematic line with m_oEdges[iEdgeIndex] = TEdge(oEdge.end, iMiddleVertexIndex); does fix the issue. Though my concern is what is the cause for the unexpected behaviour. Might that be a compiler bug (hence what other issues do I have to expect?), or do I overlook some stupid bug in my code?
/usr/bin/c++ --version
c++ (Debian 4.9.2-10) 4.9.2
Switching from c++98 to c++11 did not change anything.
You're using an invalid reference after your push_back operation.
This:
TEdge & oEdge = m_oEdges[iEdgeIndex];
acquires the reference. Then this:
m_oEdges.push_back(TEdge(oEdge.start, iMiddleVertexIndex));
potentially resizes the vector, and in so doing, invalidates the oEdge reference. At which point this:
oEdge = TEdge(oEdge.end, iMiddleVertexIndex);
is no longer define behavior, as you're using a dangling reference. Reuse the index, not the reference, such as:
m_oEdges[iEdgeIndex] = TEdge(m_oEdges[iEdgeIndex].end, iMiddleVertexIndex);
Others have mentioned the invalidation of the reference, so I won't go into more details on that.
If performance is critical, you could explicitly reserve enough space in the original vector for the new edges before you start looping. This would avoid the problem, but would still be technically incorrect. i.e. it would work, but still be against the rules.
A safer, but slightly slower method would be to iterate through the vector, changing existing edges and generating new edges in a new vector (with sufficient space reserved beforehand for performance), and then at the end, append the new vector to the existing one.
The safest way (including being completely exception safe), would be to create a new vector (reserving double the size of the initial vector), iterate through the initial vector (without modifying any of its edges), pushing two new edges into the new vector for each old edge, and then right at the end vector.swap() the old vector with the new vector.
A big positive side-effect of this last approach is that your code either succeeds completely, or leaves the original edges unchanged. It maintains the integrity of the data even in the face of disaster.
P.S. I notice that you are doing:
TEdge(oEdge.first, iMiddleVertexIndex)
TEdge(oEdge.second, iMiddleVertexIndex)
If the rest of your code is sensitive to ring-orientation you probably want to reverse the parameters for the second edge. i.e.:
TEdge(oEdge.first, iMiddleVertexIndex)
TEdge(iMiddleVertexIndex, oEdge.second )

OpenCV Mat array access, which way is the fastest for and why?

I am wondering about the way of accessing data in Mat in OpenCV. As you know, we can access to get data in many ways. I want to store image (Width x Height x 1-depth) in Mat and looping access each pixel in the image. Using ptr<>(irow) to get row-pixel and then access each column in the row is the best way? or using at<>(irow,jcol) is the best? or using directly calculate the index by using index = irow*Width + jrow is the best? Anyone know the reason.
Thanks in advance
You can find information here in the documentation: the basic image container and how to scan images.
I advice you to practice with at (here) if you are not experienced with OpenCV or with C language types hell. But the fastest way is ptr as Nolwenn answer because you avoid the type checking.
at<T> does a range check at every call, thus making it slower than ptr<T>, but safer.
So, if you're confident that your range calculations are correct and you want the best possible speed, use ptr<T>.
I realize this is an old question, but I think the current answers are somehow misleading.
Calling both at<T>(...) and ptr<T>(...) will check the boundaries in the debug mode. If the _DEBUG macro is not defined, they will basically calculate y * width + x and give you either the pointer to the data or the data itself. So using at<T>(...) in release mode is equivalent to calculating the pointer yourself, but safer because calculating the pointer is not just y * width + x if the matrix is just a sub-view of another matrix. In debug mode, you get the safety checks.
I think the best way is to process the image row-by-row, getting the row pointer using ptr<T>(y) and then using p[x]. This has the benefit that you don't have to count with various data layouts and still plain pointer for the inner loop.
You can use plain pointers all the way, which would be most efficient because you avoid one the multiplication per row, but then you need to use step1(i) to advance the pointer. I think that using ptr<T>(y) is a nice trade-off.
According to the official documentations, they suggest that the most efficient way is to get the pointer to the row first, and then just use the plain C operator []. It also saves a multiplication for each iteration.
// compute sum of positive matrix elements
// (assuming that M isa double-precision matrix)
double sum=0;
for(int i = 0; i < M.rows; i++)
{
const double* Mi = M.ptr<double>(i);
for(int j = 0; j < M.cols; j++)
sum += std::max(Mi[j], 0.);
}

OpenCV extracted descriptors cause valgrind to report invalid read when being copied

I know there is already at least a dozen valgrind reports invalid read questions, but please bear with me cause I really don't know how to help myself so I'm asking for yours.
I am writing a wrapper for OpenCV feature detection and feature description modules (I want to be able to implement my own feat detection / extraction at some point). Because of that, I can not operate directly on OpenCV datatypes.
So, when extracting descriptors from features, I store them as std::vector <std::vector <double> > instead of cv::Mat. I have this piece of code where I first calculate the descriptors and then convert them from one notation to another:
// private
void CVDescriptor::calculateDescriptors(std::vector <cv::KeyPoint> &feats){
this->feats = &feats;
this->descCalc->compute(*(this->image), feats, this->desc);
this->calculated = true;
}
// public
void CVDescriptor::calculateDescriptors
(std::vector< std::vector< double > >& desc,
std::vector< cv::KeyPoint >& feats){
if (!this->calculated)
this->calculateDescriptors(feats);
assert(this->calculated);
const double *temp;
desc.clear();
desc.reserve(this->desc.rows);
for (int i=0, szi = this->desc.rows; i < szi; ++i){
temp = this->desc.ptr<double>(i);
// this line is the problem
desc.push_back(std::vector<double>(temp, temp+(this->desc.cols)));
// .
// /|\
// |
}
assert(desc.size() == this->desc.rows);
assert(desc[0].size() == this->desc.cols);
return;
}
Here are the types of my member variables, and I've checked and written where I initialize them (just to avoid confusion):
std::vector <cv::KeyPoint> *feats
cv::Mat *image;
// it is set just before calling calculateDescriptors(desc, feats)
cv::Mat desc;
bool calculated; // set in the only constructor
Here's the OpenCV documentation for cv::DescriptorExtractor::compute. From what I can see, each calculated descriptor should be one row in cv::Mat, and should have as much components as the matrix has columns.
I'm suspecting memory leaks at some places in my code, so I've run it through Valgrind. The first thing it reports is Invalid read of size 1 on the line marked with a big arrow in my code excerpt. As far as I can see, it is reporting it only twice per call to CVDescriptor::calculateDescriptors(..), not in every iteration of the for loop.
Can anyone see anything obviously wrong with my copying code? Or has any other ideas how this might be happening?
I can provide additional information if needed, but I've tried to put all the relevant code here (as my project is pretty big). Thank you all in advance (and I'm sorry for the lengthy question)...
I added a printout of the starting and ending addresses of the memory block being copied in every iteration, and that revealed the problem. Excerpt from the printout:
copied from 0xc0d5990 -- 0xc0d5d90
copied from 0xc0d5b90 -- 0xc0d5f90
copied from 0xc0d5d90 -- 0xc0d6190
copied from 0xc0d5f90 -- 0xc0d6390
copied from 0xc0d6190 -- 0xc0d6590
In every iteration I was accidentally trying to copy two rows of the cv::Mat at once, because I was accessing it through double pointers, while the data stored was float.
Declaring temp as a const float *temp; and changing the temp assignment in
temp = this->desc.ptr<float>(i);
does the trick.

Addition of multidimensional vectors C++

Having a bit of a headache trying to sum the elements in a 3d Vector.
Its for a k-means algorithm that I'm currently programming; an algorithm that I understand and can do on paper, but syntactically has me a bit tongue tied at the moment. I might mention that this project is the first time that I've really dealt with complex containers in C++. Currently I want calculate the new centroid for my points in a cluster, this is done by averaging the positions of every co-ordinate in the cluster. My 3d vector is set out as a vector of clusters each containing a vector which contain vectors of my co-ordinates in that cluster (I hope that sounds clear, hopefully my code will alleviate any confusion). I'm trying to use iterators at the moment, but am considering going back to ints and indices as I am more comfortable with them, though I feel that I should learn how this syntax works as it seems to be important and powerful.
I'll post just the function that I'm stuck on and the parts of the header that relate to it. If you would like to see any of the other code I'm happy to throw that in too on request, but I feel that this should be enough to show my problem.
.h file parts (public members of class):
vector< vector < vector <float> > > clusters;
vector<vector<float> > avg;
int avgDiv;
.cpp file part with comments to help elaborate my query:
vector<vector<vector<float> > >::iterator threeD;
vector<vector<float> >::iterator row;
vector<float>::iterator col;
for (threeD = clusters.begin(); threeD != clusters.end(); threeD++) {
for (row = threeD->begin(); row != threeD->end(); row++) {
for(col = row->begin(); col != row->end(); col++){
//its this code below that is causing my headache,
//I know that what is written isn't correct,
//it is there to serve as an example of what I've
//been trying to do to sort out my issue.
avg.at(row) ( = or push_back ) ((clusters.at(row).at(col)) + (clusters.at(row+1).at(col)));
}
avgDiv = distance(row->begin(),row->end());
//divide each value in avg vector by the amount of members in row, giving the new centroid for that cluster, loop forward to next cluster. this isn't a problem I should think.
}
}
My problem is that the compiler tells me that call to 'at' is not a member function. Now from what I can see from other questions it is because I'm not passing the right object as an arguement, though, I'm sure that I want to add together every element in the vector which the iterators are at together with the element next in the row.
I've tried and make this as clear as possible, please ask and I will add as much detail as I can to help you answer. I am new to this, and am very happy to take criticism; it will only make me a better programmer. Thank you for your time.
avg.at(index) is used with an integer index, it's just the 'c' array[index] notation with bounds checking - incidentally in real code you want to use [] or disable checking for speed.
But row is an iterator, effectively it's a pointer to the element in avg already so just dereference it to get the value.
*row = value of avg at position of iterator 'row'
A good tutorial on C++ iterators http://www.cprogramming.com/tutorial/stl/iterators.html
ps. With vectors and 'maths' type code, it's often simpler to just use array index notation