How to save intensity value in sensor_msgs/Image from PointCloud? - ros

I am using ROS-Kinetic. I have a pointcloud of type PointCloud. I have projected the same pointcloud on a plane. I would like to convert the planar pointcloud to an image of type sensor_msgs/Image.
toROSMsg(cloud, image);
enter code hereis throwing an error as
error: ‘const struct pcl::PointXYZI’ has no member named ‘rgb’
memcpy (pixel, &cloud (x, y).rgb, 3 * sizeof(uint8_t));
Kindly enlighten me in this regard. If possible along with a code snippet.
Thanks in advance

If toROSMsg() is complaining that your input cloud does not have an 'rgb' member, try to input a cloud of type pcl::PointXYZRGB. This is another type of point cloud handled by PCL. You can look at the documentation of PCL point types.
Convert to type pcl::PointXYZRGB with these lines:
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloudrgb (new pcl::PointCloud<pcl::PointXYZRGB>);
pcl::copyPointCloud(*cloud, *cloudrgb);
Then call your function as:
toROSMsg(cloudrgb, image);

What you try to achieve is some 2D voxelization. And I assume that you want to implement some "inverse sensor model" (ISM) as explained by Thrun, right?
This approach is commonly directly implemented into a mapping algorithm to circumvent the exhaustive calculation of the plain ISM.
Therefore, you'll hardly find an out of the box solution.
Anyway, you could do it in multiple ways like this:
Use pointcloud_to_laserscan for 2D projection (but you have it anyway)
Use the ISM alg. explained in the book
or
Transform the PCL to an octree
Downsample to a quadtree and convert it to an imge

Related

How to create an Emgu::CV::Image with a specific type?

In OpenCV we have access to the CV_XX types which allow you to create a matrix with, for example, CV_32SC1. How do I do this in EmguCV?
The reason for asking is:
I am currently using EmguCV and getting an error where I need to create a specific type of Image and am unable to find those values.
Here is my code:
Emgu::CV::Image<Emgu::CV::Structure::Gray, byte>^ mask = gcnew Emgu::CV::Image<Emgu::CV::Structure::Gray, byte>(gray->Size);
try { CvInvoke::cvDistTransform(255-gray, tmp, CvEnum::DIST_TYPE::CV_DIST_L1, 3, nullptr, mask); }
Which gives the error:
OpenCV: the output array of labels must be 32sC1
So I believe I need to change the byte type to 32sC1, how do I do this?
I am using EmguCV 2.0
From the Working with images page, specifically the section on EmguCV 2.0, it provides the following clarification on image depth:
Image Depth Image Depth is specified using the second generic
parameter Depth. The types of depth supported in Emgu CV 1.4.0.0
include
Byte
SByte
Single (float)
Double
UInt16
Int16
Int32 (int)
I believe this means it does not use the CV_XXX types at all and only the above.
For my issue i set the type to Int32 and it seemed to stop erroring.

What should I do for multiple histograms?

I'm working with openCV and I'm a newbie in this field. I'm researching about Camshift. I want to extend this method by using multiple histograms. It means when tracking an object has many than one apperance (ex: rubik cube with six apperance), if we use only one histogram, Camshift will most likely fail.
I know calcHist function in openCV (http://docs.opencv.org/modules/imgproc/doc/histograms.html#calchist) has a parameter is "accumulate", but I don't know how to use and when to use (apply for camshiftdemo.cpp in opencv samples folder). This function can help me solve this problem? Or I have to use difference solution?
I have an idea, that is: create an array histogram for object, for every appearance condition that strongly varies in color, we pre-compute and store all to this array. But when we compute new histogram? It means that the pre-condition to start compute new histogram is what?
And what happend if I have to track multiple object has same color?
Everybody please help me. Thank you so much!

Matrix Concatenation using Actionscript Matrix3D

I want to get the properly rendered projection result from a Stage3D framework that presents something of a 'gray box' interface via its API. It is gray rather than black because I can see this critical snippet of source code:
matrix3D.copyFrom (renderable.getRenderSceneTransform (camera));
matrix3D.append (viewProjection);
The projection rendering technique that perfectly suits my needs comes from a helpful tutorial that works directly with AGAL rather than any particular framework. Its comparable rendering logic snippet looks like this:
cube.mat.copyToMatrix3D (drawMatrix);
drawMatrix.prepend (worldToClip);
So, I believe the correct, general summary of what is going on here is that both pieces of code are setting up the proper combined matrix to be sent to the Vertex Shader where that matrix will be a parameter to the m44 AGAL operation. The general description is that the combined matrix will take us from Object Local Space through Camera View Space to Screen or Clipping Space.
My problem can be summarized as arising from my ignorance of proper matrix operations. I believe my failed attempt to merge the two environments arises precisely because the semantics of prepending one matrix to another is not, and is never intended to be, equivalent to appending that matrix to the other. My request, then, can be summarized in this way. Because I have no control over the calling sequence that the framework will issue, e.g., I must live with an append operation, I can only try to fix things on the side where I prepare the matrix which is to be appended. That code is not black-boxed, but it is too complex for me to know how to change it so that it would meet the interface requirements posed by the framework.
Is there some sequence of inversions, transformations or other manuevers which would let me modify a viewProjection matrix that was designed to be prepended, so that it will turn out right when it is, instead, appended to the Object's World Space coordinates?
I am providing an answer more out of desperation than sure understanding, and still hope I will receive a better answer from those more knowledgeable. From Dunn and Parberry's "3D Math Primer" I learned that "transposing the product of two matrices is the same as taking the product of their transposes in reverse order."
Without being able to understand how to enter text involving superscripts, I am not sure if I can reduce my approach to a helpful mathematical formulation, so I will invent a syntax using functional notation. The equivalency noted by Dunn and Parberry would be something like:
AB = transpose (B) x transpose (A)
That comes close to solving my problem, which problem, to restate, is really just a problem arising out of the fact that I cannot control the behavior of the internal matrix operations in the framework package. I can, however, perform appropriate matrix operations on either side of the workflow from local object coordinates to those required by the GPU Vertex Shader.
I have not completed the test of my solution, which requires the final step to be taken in the AGAL shader, but I have been able to confirm in AS3 that the last 'un-transform' does yield exactly the same combined raw data as the example from the author of the camera with the desired lens properties whose implementation involves prepending rather than appending.
BA = transpose (transpose (A) x transpose (B))
I have also not yet tested to see if these extra calculations are so processing intensive as to reduce my application frame rate beyond what is acceptable, but am pleased at least to be able to confirm that the computations yield the same result.

Unsupported format or combination of formats when using cv::reduce method in OpenCV

I am using OpenCV 2.4.2 and I am trying to take projections of two matrices (tmpl(32x44), subj(32x44)) along row and column. I have initialised a result matrix as rowProjectionSubj(subj.rows,1,CV_8UC1) Then I call cv::reduce(subj,rowProjectionSubj,1,CV_REDUCE_SUM,-1);
Why is this complaining about the type mismatch? I have kept the types same (by keeping dtype=-1 in cv::reduce. I get the tmpl and subj objects by doing cv::imread("image_path",0) i.e. scanning grayscale images in.
I might not be right, but after I saw this:
http://answers.opencv.org/question/3698/cvreduce-gives-unsupported-format-exception/?answer=3701#post-id-3701
and with a little experiment and using an old friend called "register math", I realised that when you add two 8-bit numbers, you need to consider a 8+1+1 bit register to store the sum because it potentially has carry output. so any result of reduce should have bigger space than the source i.e. if the source is 8-bit unsigned, it should be at least 16-bit unsigned or signed; might as well be 32-bit if it is going to be used for some product calculation and stuff...
NOTE: The destination type must be EXPLICITLY stated in the cv::reduce method. Please follow my openCV link for further information.

How to determine the human-readable type of a cv::Mat?

My current problem is that I would like to know the type of the cv::Mat-frames grabbed by cv::VideoCapture from a video file. The documentation doesn't specify that (as is often the case, so even if I have overlooked it in this particular case, it would still be helpful to get an answer for dealing with the problem in general).
Of course, I could open the appropriate OpenCV header file and go through the CV_64FC2, ... macros to find a macro which matches the Mat's type(). But I'm kind of sick of that. There must be an easier way.
Isn't there any function that lets me translate a Mat's type() to a human-readable format ? Like this:
cv::Mat myMatWithUnknownType;
// Some code modifying myMatWithUnknownType.
// ...
std::string readableType = myMatWithUnknownType.typeString();
std::cout << readableType; // Prints "CV_64FC3".
How do you deal with that?
First, the format that come from cameras is only one: CV_8UC3. This is hardcoded in OpenCV, and any video format is converted to this before being sent to user. So
capture >> frame;
Will always return a RGB image, of 8 bits per channel.
Now, for other types you can write your function, keeping in mid that there are not so many types supported in OpenCV: A Mat can be of type char, uchar, short, ushort, int, uint, float, double, of 1 to 512 channels (according to the latest docs.) So writing your own type_to_string() is not difficult.

Resources