Is there any function to extract the indices generated from a cropbox - point-cloud-library

I've tried the pcl::cropbox and filtered a cloud based on the min and max x,y,z values given to the cropbox. I get the new cloud which contains only the point within the cropbox limits. Unfortunately I don't need a separate cloud, but need the indices which lie within the box.
Note : I get the removed indices from the old cloud, but not the indices which lie inside cropbox.
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile ("D:\ism_test.pcd", *cloud);
pcl::PointCloud<pcl::PointXYZ>::Ptr bodyFiltered (new pcl::PointCloud<pcl::PointXYZ>);
pcl::CropBox<pcl::PointXYZ> boxFilter(true);
boxFilter.setMin(Eigen::Vector4f(minX, minY, minZ, 1.0));
boxFilter.setMax(Eigen::Vector4f(maxX, maxY, maxZ, 1.0));
boxFilter.setInputCloud(cloud);
boxFilter.FilterIndices(*bodyFiltered);
pcl::IndicesConstPtr removedIndices = boxFilter.getRemovedIndices();
pcl::IndicesConstPtr actualindices = boxFilter.getIndices();
//blocks until the cloud is actually rendered
pcl::visualization::CloudViewer filteredviewer("Filtered Viewer");
filteredviewer.showCloud(bodyFiltered);

pcl::CropBox inherited filter (std::vector< int > &indices) so you should be able to call it to get the indices which lie within the box see here for reference
pcl::CropBox<pcl::PointXYZ> boxFilter;
...
#
std::vector<int> indices_inside;
boxFilter.filter(indices_inside);
If you need the points out side the box, you can retrieve it with std::set_difference, for example
std::vector<int> all_points(cloud.size());
std::iota(all_points.begin(), all_points.end()) // fill with 0, 1, 2, ..., n
std::vector<int> indices_inside = ...(from previous);
std::vector<int> indices_outside;
// process: indices_outside = all_points - indices_inside
std::set_difference(all_points.begin(), all_points.end(),
indices_inside.begin(), indices_inside.end(),
std::inserter(indices_outside, indices_outside.begin()));

Related

What does the C++ map() function do

I am currently looking at the following code (which can be found here)
void MPU6050::CalibrateAccel(uint8_t Loops,uint8_t OffsetSaveAddress) {
double kP = 0.15;
double kI = 8;
float x;
x = (100 - map(Loops, 1, 5, 20, 0)) * .01;
kP *= x;
kI *= x;
PID( 0x3B, OffsetSaveAddress, kP, kI, Loops);
}
Specifically I am struggling to understand what the line:
x = (100 - map(Loops, 1, 5, 20, 0)) * .01;
is doing?
The best matching function I can find for map() is here but it doesn't appear to match the integer parameters that are being passed into the function.
Obviously ideally I would run this code but unfortunately I am yet unable to get this to compile.
Have I correctly found the function being invoked and what is the behaviour of this function with the given parameters? I assume this is a map() function similar to any other typical map function in other languages/frameworks such as python, jquery etc.
Could anyone guide me in the right direction?
map defined in math, re-maps a number from one range to another. Syntax is map(value, fromLow, fromHigh, toLow, toHigh)
So, map(Loops, 1, 5, 20, 0)) means the value of variable Loops will be initially searched between (1,5) but result will be between 20 to 0 since it is remapped.

Finding the largest blob in a black/white image

I have this picture:
I want to create a mask from this image, to place on top of the original image. The mask I want to obtain is the black part at the top.
I tried to use simpleBlobDetector from OpenCV to try to detect the white part as one big blob. I do not obtain the results I am hoping for and am unsure what to do.
R has been used, but my question is not specifically on how to achieve this in R. The result I have is below the code.
library(Rvision)
x <- simpleBlobDetector(im, min_threshold = 0, max_threshold = 255)
plot(x)
I do not understand why those three black boxes are selected as blobs, while there are a lot more of those black boxes that are not selected.
EDIT: when I add blob_color = 255 so white blobs are searched, nothing is detected.
You can do something like this using OpenCV:
// read input image
Mat inputImg = imread("test1.tif", IMREAD_GRAYSCALE);
// create binary image
Mat binImg;
threshold(inputImg, binImg, 254, 1, THRESH_BINARY_INV);
// compute connected components
Mat labelImg;
connectedComponents(binImg, labelImg, 8, CV_16U);
// compute histogram
Mat histogram;
int histSize = 256;
float range[] = { 0, 256 } ;
const float* histRange = { range };
calcHist(&labelImg, 1, 0, Mat(), histogram, 1, &histSize, &histRange, true, false);
// retrieve maximal population
float maxVal = 0;
int maxIdx;
for (int i=1; i<histSize; ++i) {
if (histogram.at<float>(i) > maxVal) {
maxVal = histogram.at<float>(i);
maxIdx = i;
}
}
// create output mask with bigest population
Mat resImg;
threshold(labelImg, labelImg, maxIdx, 0, THRESH_TOZERO_INV);
threshold(labelImg, resImg, maxIdx-1, 1, THRESH_BINARY);
// write result
imwrite("res.tif", resImg);
And you should obtain something like this:
I think you can convert input to bianry, then extract connected components, compute associated histogram and simply keep (by thresholding) histogram class with highest population
Regards

scilab submatrix incorrectly defined

I am stuck at creating a matrix of a matrix (vector in this case)
What I have so far
index = zeros(size(A)) // This is some matrix but isn't important to the question
indexIndex = 1;
for rows=1:length(R)
for columns=1:length(K)
if(A(rows,columns)==x)
V=[rows columns]; // I create a vector holding the row + column
index(indexIndex) = V(1,2) // I want to store all these vectors
indexIndex = indexIndex + 1
end
end
end
I have tried various ways of getting the information out of V (such as V(1:2)) but nothing seems to work correctly.
In other words, I'm trying to get an array of points.
Thanks in advance
I do not understand your question exactly. What is the size of A? What is x, K and R? But under some assumptions,
Using list
You could use a list
// Create some matrix A
A = zeros(8,8)
//initialize the list
index = list();
// Get the dimensions of A
rows = size(A,1);
cols = size(A,2);
x = 0;
for row=1:rows
for col=1:cols
if(A(row,col)==x)
// Create a vector holding row and col
V=[row col];
// Append it to list using $ (last index) + 1
index($+1) = V
end
end
end
Single indexed matrices
Another approach would be to make use of the fact an multi-dimensional matrix can also be indexed by a single value.
For instance create a random matrix named a:
-->a = rand(3,3)
a =
0.6212882 0.5211472 0.0881335
0.3454984 0.2870401 0.4498763
0.7064868 0.6502795 0.7227253
Access the first value:
-->a(1)
ans =
0.6212882
-->a(1,1)
ans =
0.6212882
Access the second value:
-->a(2)
ans =
0.3454984
-->a(2,1)
ans =
0.3454984
So that proves how the single indexing works. Now to apply it to your problem and knocking out a for-loop.
// Create some matrix A
A = zeros(8,8)
//initialize the array of indices
index = [];
// Get the dimensions of A
rows = size(A,1);
cols = size(A,2);
x = 0;
for i=1:length(A)
if(A(i)==x)
// Append it to list using $ (last index) + 1
index($+1) = i;
end
end
Without for-loop
If you just need the values that adhere to a certain condition you could also do something like this
values = A(A==x);
Be carefull when comparing doubles, these are not always (un)equal when you expect.

Get index of first "true" in vector

How do I efficiently calculate the index of the first "true" value in an OpenCL vector:
float4 f = (float4)(1, 2, 3, 4);
int i = firstTrue(f > 2);
In the example I would like to get i=2 because 3 is the first value greater than 2.
I have looked at all functions in http://www.khronos.org/registry/cl/sdk/1.2/docs/man/xhtml/ but have found nothing.
Is this such an uncommon operation?
How do I calculate this (on my own) without much branching/code duplication?
I'm not aware of a built-in function that does exactly what you want, but I have some ideas on how you could do it. There might be a simpler solution, but I've only had one cup of coffee so far. The idea is to leverage the "count leading zeros" function "clz". You just need to convert the results of your conditional into bit positions in an integer.
Create a boolean vector with true/false state set by the comparison
Do a dot product of that against an integer vector with pre-defined values that correspond to bit positions.
The first bit set will correspond to the index you're asking for. Use clz() or a bithack to find that bit index.
In code, something like this (untested and might need adjusting):
float4 f = (float4)(1, 2, 3, 4);
int4 greater = (f > 2);
int4 bits = (int4)(8, 4, 2, 1);
int sum = dot(greater, bits); // maybe this needs to use float
int index = clz(sum); // might need offset applied
You'll need to offset or invert the result from clz to get 0,1,2,3 but that's just addition or subtraction.
Working Code
int firstTrue(int4 v) {
return 4 - (clz(0) - clz((v.x & 8) | (v.y & 4) | (v.z & 2) | (v.w & 1));
}

Extracting minimum of vector

I'm extracting the min from a vector.
Say vector = [0, inf, inf, inf];
ExtractSmallest(vector) = 0;
and then vector = [0, 1, inf, inf];
but now, we've already seen 0. Thus,
ExtractSmallest(vector) = 1;
I represent this in my code by doing nodes.erase(nodes.begin() + smallestPosition);
But, I now realize that erasing is very bad. Is there a way to achieve this without erasing the vectors? Just skipping over the ones we've already seen?
Node* CGraph::ExtractSmallest(vector<Node*>& nodes)
{
int size = nodes.size();
if (size == 0) return NULL;
int smallestPosition = 0;
Node* smallest = nodes.at(0);
for (int i=1; i<size; ++i)
{
Node* current = nodes.at(i);
if (current->distanceFromStart <
smallest->distanceFromStart)
{
smallest = current;
smallestPosition = i;
}
}
nodes.erase(nodes.begin() + smallestPosition);
return smallest;
}
Option 1 You can have an additional vector<bool> on which you iterate in parallel. When you find the smallest element, mark that position in the bool vector as true. Whenever you iterate, skip the positions in both vectors that are marked as true.
Option 2 If order is not important, keep the number of elements removed so far. When you find the minimum, swap positions with the first non-excluded element. On a new iteration, start from the first non-excluded element.
Option 3 If order is not important, sort the array. (this takes O(n*log(n))). Removal will now take O(1) - you just exclude the first non-excluded element.
Option 4 If there are no duplicates, you can keep a std::set on the side with all excluded elements to this point. When you iterate, check whether the current element was already excluded or not.

Resources