Visualize PCD containing custom double point structure - double

I have created a custom double point-type for storing the point position in the PCD file. I required the double data type since my points are in global coordinates and have very large values (of order 10^6 to 10^7) and require good precision. Since the values are large and the default FLOAT32 precision is limited, there is considerable data approximation which is also visible during visualization.
I created this PCD by transforming the raw pointcloud with the initial global reference coordinate from GPS in the data bag that I have. I am using a 15 point precision.
I created a separate script for visualizing this custom point-type PCD. But by visually comparing, I cannot see any considerable difference between the FLOAT32 and double data-type PCD's.
Raw_float_pcd_visualization
Transformed_float_pcd_visualization
Transformed_double_pcd_visualization
You can see that the transformed_double and transformed_float PCD's are quite similar and approximated. While the raw_float PCD is quite good as compared to these two.
I am attaching the PCD files for reference:
raw_float
transformed_float
transformed_double
I think that I am skipping some things while loading the pointcloud and there are some more changes that need to be done in order to visualize the points with double point precision.
I used "pcl_viewer" from pcl_tools for visualizing FLOAT type PCD's.
Code for visualizaing custom DOUBLE point-structure PCD:
#define PCL_NO_PRECOMPILE
#include <iostream>
// #include "double_viz/pcl_double.h"
#include <pcl-1.7/pcl/common/common.h>
#include <pcl-1.7/pcl/io/pcd_io.h>
#include <pcl-1.7/pcl/visualization/pcl_visualizer.h>
#include <pcl-1.7/pcl/console/parse.h>
#include <pcl-1.7/pcl/point_cloud.h>
#include <pcl-1.7/pcl/point_types.h>
namespace pcl
{
#define PCL_ADD_UNION_POINT4D_DOUBLE \
union EIGEN_ALIGN16 { \
double data[4]; \
struct { \
double x; \
double y; \
double z; \
}; \
};
struct _PointXYZDouble
{
PCL_ADD_UNION_POINT4D_DOUBLE; // This adds the members x,y,z which can also be accessed using the point (which is float[4])
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
struct EIGEN_ALIGN16 PointXYZDouble : public _PointXYZDouble
{
inline PointXYZDouble (const _PointXYZDouble &p)
{
x = p.x; y = p.y; z = p.z; data[3] = 1.0;
}
inline PointXYZDouble ()
{
x = y = z = 0.0;
data[3] = 1.0;
}
inline PointXYZDouble (double _x, double _y, double _z)
{
x = _x; y = _y; z = _z;
data[3] = 1.0;
}
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
}
POINT_CLOUD_REGISTER_POINT_STRUCT (pcl::_PointXYZDouble,
(double, x, x)
(double, y, y)
(double, z, z)
)
POINT_CLOUD_REGISTER_POINT_WRAPPER(pcl::PointXYZDouble, pcl::_PointXYZDouble)
// This function displays the help
void
showHelp(char * program_name)
{
std::cout << std::endl;
std::cout << "Usage: " << program_name << " cloud_filename.[pcd]" << std::endl;
std::cout << "-h: Show this help." << std::endl;
}
// This is the main function
int
main (int argc, char** argv)
{
// Show help
if (pcl::console::find_switch (argc, argv, "-h") || pcl::console::find_switch (argc, argv, "--help"))
{
showHelp (argv[0]);
return 0;
}
// Fetch point cloud filename in arguments | Works with PCD
std::vector<int> filenames;
if (filenames.size () != 1)
{
filenames = pcl::console::parse_file_extension_argument (argc, argv, ".pcd");
if (filenames.size () != 1)
{
showHelp (argv[0]);
return -1;
}
}
// Load file | Works with PCD and PLY files
pcl::PointCloud<pcl::PointXYZDouble>::Ptr source_cloud (new pcl::PointCloud<pcl::PointXYZDouble> ());
if (pcl::io::loadPCDFile (argv[filenames[0]], *source_cloud) < 0)
{
std::cout << "Error loading point cloud " << argv[filenames[0]] << std::endl << std::endl;
showHelp (argv[0]);
return -1;
}
// Visualization
// printf( "\nPoint cloud colors : white = original point cloud\n"
// " red = transformed point cloud\n");
pcl::visualization::PCLVisualizer viewer ("Visualize double PCL");
// Define R,G,B colors for the point cloud
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZDouble> source_cloud_color_handler (source_cloud, 100, 100, 100);
// We add the point cloud to the viewer and pass the color handler
viewer.addPointCloud (source_cloud, source_cloud_color_handler, "original_cloud");
viewer.addCoordinateSystem (1.0, "cloud", 0);
viewer.setBackgroundColor(0.05, 0.05, 0.05, 0); // Setting background to a dark grey
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_OPACITY, 1, "original_cloud");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "original_cloud");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 1, "original_cloud");
//viewer.setPosition(800, 400); // Setting visualiser window position
while (!viewer.wasStopped ()) // Display the visualiser until 'q' key is pressed
{
viewer.spinOnce ();
}
return 0;
}

In the raw_float file, the size field has been defined as 4 bytes each: SIZE 4 4 4 4,
to be read as double it should be SIZE 8 8 8 8.
With your current implementation each field is being read as Float32

Related

My vscode is part English part Chinese, how to change it to complete English?

As mentioned in the title, I have part of my vscode Chinese, which is troublesome since looking up error codes in English will be easier. How can I turn it into complete English? I've tried How to set Visual Studio Code Terminal output to English and it didn't work for me.
Since someone asked for the code to be post in text, this is the code (I'm using a tutorial code for camera calibration from opencv, so the error code appearing also confused me):
#include <iostream>
#include <opencv2/calib3d.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
int main(int argc, char **argv) {
(void)argc;
(void)argv;
std::vector<cv::String> fileNames;
cv::glob("../calibration/Image*.png", fileNames, false);
cv::Size patternSize(25 - 1, 18 - 1);
std::vector<std::vector<cv::Point2f>> q(fileNames.size());
std::vector<std::vector<cv::Point3f>> Q;
// 1. Generate checkerboard (world) coordinates Q. The board has 25 x 18
// fields with a size of 15x15mm
int checkerBoard[2] = {25,18};
// Defining the world coordinates for 3D points
std::vector<cv::Point3f> objp;
for(int i = 1; i<checkerBoard[1]; i++){
for(int j = 1; j<checkerBoard[0]; j++){
objp.push_back(cv::Point3f(j,i,0));
}
}
std::vector<cv::Point2f> imgPoint;
// Detect feature points
std::size_t i = 0;
for (auto const &f : fileNames) {
std::cout << std::string(f) << std::endl;
// 2. Read in the image an call cv::findChessboardCorners()
cv::Mat img = cv::imread(fileNames[i]);
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_RGB2GRAY);
bool patternFound = cv::findChessboardCorners(gray, patternSize, q[i], cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE + cv::CALIB_CB_FAST_CHECK);
// 2. Use cv::cornerSubPix() to refine the found corner detections
if(patternFound){
cv::cornerSubPix(gray, q[i],cv::Size(11,11), cv::Size(-1,-1), cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::MAX_ITER, 30, 0.1));
Q.push_back(objp);
}
// Display
cv::drawChessboardCorners(img, patternSize, q[i], patternFound);
cv::imshow("chessboard detection", img);
cv::waitKey(0);
i++;
}
cv::Matx33f K(cv::Matx33f::eye()); // intrinsic camera matrix
cv::Vec<float, 5> k(0, 0, 0, 0, 0); // distortion coefficients
std::vector<cv::Mat> rvecs, tvecs;
std::vector<double> stdIntrinsics, stdExtrinsics, perViewErrors;
int flags = cv::CALIB_FIX_ASPECT_RATIO + cv::CALIB_FIX_K3 +
cv::CALIB_ZERO_TANGENT_DIST + cv::CALIB_FIX_PRINCIPAL_POINT;
cv::Size frameSize(1440, 1080);
std::cout << "Calibrating..." << std::endl;
// 4. Call "float error = cv::calibrateCamera()" with the input coordinates
// and output parameters as declared above...
float error = cv::calibrateCamera(Q, q, frameSize, K, k, rvecs, tvecs, flags);
std::cout << "Reprojection error = " << error << "\nK =\n"
<< K << "\nk=\n"
<< k << std::endl;
// Precompute lens correction interpolation
cv::Mat mapX, mapY;
cv::initUndistortRectifyMap(K, k, cv::Matx33f::eye(), K, frameSize, CV_32FC1,
mapX, mapY);
// Show lens corrected images
for (auto const &f : fileNames) {
std::cout << std::string(f) << std::endl;
cv::Mat img = cv::imread(f, cv::IMREAD_COLOR);
cv::Mat imgUndistorted;
// 5. Remap the image using the precomputed interpolation maps.
cv::remap(img, imgUndistorted, mapX, mapY, cv::INTER_LINEAR);
// Display
cv::imshow("undistorted image", imgUndistorted);
cv::waitKey(0);
}
return 0;
}

How to emulate *really simple* variable bit shifts with SSE?

I have two variable bit-shifting code fragments that I want to SSE-vectorize by some means:
1) a = 1 << b (where b = 0..7 exactly), i.e. 0/1/2/3/4/5/6/7 -> 1/2/4/8/16/32/64/128/256
2) a = 1 << (8 * b) (where b = 0..7 exactly), i.e. 0/1/2/3/4/5/6/7 -> 1/0x100/0x10000/etc
OK, I know that AMD's XOP VPSHLQ would do this, as would AVX2's VPSHLQ. But my challenge here is whether this can be achieved on 'normal' (i.e. up to SSE4.2) SSE.
So, is there some funky SSE-family opcode sequence that will achieve the effect of either of these code fragments? These only need yield the listed output values for the specific input values (0-7).
Update: here's my attempt at 1), based on Peter Cordes' suggestion of using the floating point exponent to do simple variable bitshifting:
#include <stdint.h>
typedef union
{
int32_t i;
float f;
} uSpec;
void do_pow2(uint64_t *in_array, uint64_t *out_array, int num_loops)
{
uSpec u;
for (int i=0; i<num_loops; i++)
{
int32_t x = *(int32_t *)&in_array[i];
u.i = (127 + x) << 23;
int32_t r = (int32_t) u.f;
out_array[i] = r;
}
}

Postgis + boost::geometry + C++

I have the following wtk:
POLYGON((0 0, 10 0, 10 11, 11 10, 0 10))
In boost::geometry we can get this polygon representation using
boost::geometry::dsv(polygon," "," "," ");
How I can apply postgis st_makevalid function to a boost::geometry polygon?
I suppose it something like:
#include "libpq/libpq-fs.h"
#include "../libpq-fe.h"
.
.
.
std::string geom = "POLYGON" + boost::geometry::dsv(multipoly," "," "," ");
res = PQexecParams(conn, "SELECT st_makevalid(geom) FROM ....
I do not want to connect to a data base, I just want to repair a polygon or multipolygon with the postgis function st_makevalid.
I doubt you need PostGIS for this operation.
I also doubt there is a way to "make it valid". Because the polygon has a clear self intersection:
Here's how you do the validation and correction in Boost Geometry itself:
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <boost/geometry/io/io.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <iostream>
namespace bg = boost::geometry;
namespace bgm = boost::geometry::model;
template<typename G>
bool check(G const& g) {
std::string reason;
bool valid = bg::is_valid(g, reason);
if (valid) std::cout << "Valid (dsv): " << bg::dsv(g) << "\n";
else std::cout << "Invalid: " << reason << "\n";
return valid;
}
int main() {
using pt = bgm::d2::point_xy<double>;
using poly = bgm::polygon<pt>;
poly p;
bg::read_wkt("POLYGON((0 0, 10 0, 10 11, 11 10, 0 10))", p);
while (!check(p)) {
auto same = p;
bg::correct(p);
if (bg::equals(p, same)) {
std::cout << "Out of ideas\n";
break;
}
}
}
And note the output:
Invalid: Geometry is defined as closed but is open
Invalid: Geometry has invalid self-intersections. A self-intersection point was found at (10, 10); method: i; operations: u/i; segment IDs {source, multi, ring, segment}: {0, -1, -1, 1}/{0, -1, -1, 3}
Out of ideas
If your source actually contains self-intersections like that, it's hard to tell what you'd like. Perhaps you want to look at
Split Self intersecting Polygon into non self intersecting polygon
Area of self-intersecting polygon

How to center-justify a string in text file using fprintf in MATLAB? [duplicate]

By default, printf() seems to align strings to the right.
printf("%10s %20s %20s\n", "col1", "col2", "col3");
/* col1 col2 col3 */
I can also align text to the left like this:
printf("%-10s %-20s %-20s", "col1", "col2", "col3");
Is there a quick way to center text? Or do I have to write a function that turns a string like test into (space)(space)test(space)(space) if the text width for that column is 8?
printf by itself can't do the trick, but you could play with the "indirect" width, which specifies the width by reading it from an argument. Lets' try this (ok, not perfect)
void f(char *s)
{
printf("---%*s%*s---\n",10+strlen(s)/2,s,10-strlen(s)/2,"");
}
int main(int argc, char **argv)
{
f("uno");
f("quattro");
return 0;
}
#GiuseppeGuerrini's was helpful, by suggesting how to use print format specifiers and dividing the whitespace. Unfortunately, it can truncate text.
The following solves the problem of truncation (assuming the field specified is actually large enough to hold the text).
void centerText(char *text, int fieldWidth) {
int padlen = (fieldWidth - strlen(text)) / 2;
printf("%*s%s%*s\n", padLen, "", text, padlen, "");
}
There is no printf() format specifier to centre text.
You will need to write your own function or locate a library which provides the functionality that you're looking for.
You may try write own function for this problem.
/**
* Returns a sting "str" centered in string of a length width "new_length".
* Padding is done using the specified fill character "placeholder".
*/
char *
str_center(char str[], unsigned int new_length, char placeholder)
{
size_t str_length = strlen(str);
// if a new length is less or equal length of the original string, returns the original string
if (new_length <= str_length)
return str;
char *buffer;
unsigned int i, total_rest_length;
buffer = malloc(sizeof(char) * new_length);
// length of a wrapper of the original string
total_rest_length = new_length - str_length;
// write a prefix to buffer
i = 0;
while (i < (total_rest_length / 2)) {
buffer[i] = placeholder;
++i;
}
buffer[i + 1] = '\0';
// write the original string
strcat(buffer, str);
// write a postfix to the buffer
i += str_length;
while (i < new_length) {
buffer[i] = placeholder;
++i;
}
buffer[i + 1] = '\0';
return buffer;
}
Results:
puts(str_center("A", 0, '-')); // A
puts(str_center("A", 1, '-')); // A
puts(str_center("A", 10, '-')); // ----A-----
puts(str_center("text", 10, '*')); // ***text***
puts(str_center("The C programming language", 26, '!')); // The C programming language
puts(str_center("The C programming language", 27, '!')); // The C programming language!
puts(str_center("The C programming language", 28, '!')); // !The C programming language!
puts(str_center("The C programming language", 29, '!')); // !The C programming language!!
puts(str_center("The C programming language", 30, '!')); // !!The C programming language!!
puts(str_center("The C programming language", 31, '!')); // !!The C programming language!!!
Ill drop my 2 cents after dealing with similar issue of trying to center a table headers in a row with printf.
The following macros will need to be printed before/after the text and will align regardless of the length of the text itself.
Notice that if we have odd length strings, we will not align as should(because the normal devision will result in missing space).
Therefor a round up is needed, and I think this is the elegant way to solve that issue:
#define CALC_CENTER_POSITION_PREV(WIDTH, STR) (((WIDTH + ((int)strlen(STR))) % 2) \
? ((WIDTH + ((int)strlen(STR)) + 1)/2) : ((WIDTH + ((int)strlen(STR)))/2))
#define CALC_CENTER_POSITION_POST(WIDTH, STR) (((WIDTH - ((int)strlen(STR))) % 2) \
? ((WIDTH - ((int)strlen(STR)) - 1)/2) : ((WIDTH - ((int)strlen(STR)))/2))
Usage example:
printf("%*s%*s" , CALC_CENTER_POSITION_PREV(MY_COLUMN_WIDTH, "Header")
, "Header"
, CALC_CENTER_POSITION_POST(MY_COLUMN_WIDTH, "Header"), "");
There are two solutions, the first is similar to the above, by placing macros in printf, and the second is a custom macro, which calculates the length of the formatted string in advance through snprintf, and then calls the printf function to output.
#include <stdio.h>
#include <string.h>
#define LEFT(str, w) \
({int m = w + strlen(str); m % 2 ? (m + 1) / 2 : m / 2;})
#define RIGHT(str, w) \
({ int m = w - strlen(str); m % 2 ? (m - 1) / 2 : m / 2; })
#define STR_CENTER(str, width) \
LEFT(str, width), str, RIGHT(str, width), ""
#define PRINTF_CENTER(width, start, fmt, end, ...) ({ \
int n = snprintf(NULL, 0, fmt, __VA_ARGS__); \
int m = width - n; \
int left = m % 2 ? (m + 1) / 2 : m / 2; \
int right = m % 2 ? (m - 1) / 2 : m / 2; \
printf(start "%*s" fmt "%*s" end, left, "", \
__VA_ARGS__, right, ""); \
})
#define MYFORMAT_CENTER(width, fmt, ...) \
PRINTF_CENTER(40, "[", fmt , "]\n", __VA_ARGS__)
int main(int argc, char const *argv[])
{
printf("%*s%*s\n\n", STR_CENTER("--- Hello World ---", 40));
printf("[%*s%*s]\n", STR_CENTER("I am okay today", 40));
MYFORMAT_CENTER(40, "%d, e is %f", 1, 2.71828);
MYFORMAT_CENTER(40, "%d, pi is %f", 2, 3.1415926);
MYFORMAT_CENTER(40, "%s %d.", "This is such a long string that it exceeds the given size:", 40);
return 0;
}
Output:
--- Hello World ---
[ I am okay today ]
[ 1, e is 2.718280 ]
[ 2, pi is 3.141593 ]
[ This is such a long string that it exceeds the given size: 40. ]
Yes, you will either have to write your own function that returns " test " etc, e.g.
printf("%s %s %s", center("col1", 10), center("col2", 20), center("col3", 20));
Or you have a center_print function, something like the following:
void center_print(const char *s, int width)
{
int length = strlen(s);
int i;
for (i=0; i<=(width-length)/2; i++) {
fputs(" ", stdout);
}
fputs(s, stdout);
i += length;
for (; i<=width; i++) {
fputs(" ", stdout);
}
}
A more compact version of PADYMKO's function above (which still leaks memory):
char *str_center(char str[], unsigned int new_length, char placeholder)
{
size_t str_length = strlen(str);
char *buffer;
/*------------------------------------------------------------------
* If a new length is less or equal length of the original string,
* returns the original string
*------------------------------------------------------------------*/
if (new_length <= str_length)
{
return(str);
}
buffer = malloc(sizeof(char) * (new_length + 1));
memset(buffer, placeholder, new_length);
buffer[new_length] = '\0';
bcopy(str, buffer + (( new_length - str_length) / 2), str_length);
return(buffer);
}
This sets the whole of newly allocated buffer to the padding character, null terminates that, and then drops the string to be centred into the middle of the buffer - no loops, or keeping track of where to copy to..
If you want to be able to use a printf() format string for that and you accept to be limited to the GNU clib, you can extend printf() with your own conversion specifier for centering a string with. Add the conversion specifier with register_printf_function().
See here for the documentation: https://www.gnu.org/software/libc/manual/html_node/Customizing-Printf.html
The other answers already provide you with a solution on how to manually print a string in the center, which you still need when using your own conversion specifier.
You can use either of the following two options:
char name[] = "Name1";
//Option One
printf("%*s", 40+strlen(name)/2, name, 40-strlen(name)/2, "");
puts("");//skip one line
//Option two
printf("%*s", 40+strlen("Name2")/2, "Name2", 40-strlen("Name2")/2, "");
The output is:
Name1(center)
Name2(center)

Cairo: Draw an array of pixels

I'm just starting to explore Cairo, but right now I really want to use it for something very simple.
I have a very low-tech bitmap, i.e., a 3*X*Y array of numbers. I'd like to use Cairo to make this into a bitmap and write to a file. I'm looking through tutorials and I'm not seeing a way to use it for comparatively low-level functions like this.
I don't think I need guidance on how to use the tool once I know what the tool is.
I didn't actually test this, but the following should give you lots of useful hints:
#include <cairo.h>
#include <stdint.h>
#define WIDTH 42
#define HEIGHT 42
uint8_t data[WIDTH][HEIGHT][3];
cairo_surface_t* convert()
{
cairo_surface_t *result;
unsigned char *current_row;
int stride;
result = cairo_image_surface_create(CAIRO_FORMAT_RGB24, WIDTH, HEIGHT);
if (cairo_surface_status(result) != CAIRO_STATUS_SUCCESS)
return result;
cairo_surface_flush(result);
current_row = cairo_image_surface_get_data(result);
stride = cairo_image_surface_get_stride(result);
for (int y = 0; y < HEIGHT; y++) {
uint32_t *row = (void *) current_row;
for (int x = 0; x < WIDTH; x++) {
uint32_t r = data[x][y][0];
uint32_t g = data[x][y][1];
uint32_t b = data[x][y][2];
row[x] = (r << 16) | (g << 8) | b;
}
current_row += stride;
}
cairo_surface_mark_dirty(result);
return result;
}