I encounter an error while running this code ..
access violation in reading memory location
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); //fill the cloud.
cloud-> width = 100;
cloud->height = 10;
cloud->is_dense = false;
cloud->points.resize(cloud->width*cloud->height); // generate the data
//double temp_x , temp_y , temp_z;
for (size_t i = 0; i!=cloud->points.size(); i++) {
cloud->points[i].x = 1024*rand()/(RAND_MAX + 1.0f);
cloud->points[i].y = 1024*rand()/(RAND_MAX + 1.0f);
cloud->points[i].z = 1024*rand()/(RAND_MAX + 1.0f);
}
pcl::visualization::PCLVisualizer viewer;
viewer.addPointCloud<pcl::PointXYZ>(cloud);
while(!viewer.wasStopped()){
viewer.spinOnce();
}
system("PAUSE");
return EXIT_SUCCESS;
I think "cloud->height=10" means that it's organised point cloud type.
And you should try to set cloud->height=1.
good luck!
Related
I don't quite understand what pose is returned by pcl::visualization::PCLVisualizer::getViewerPose. Is this pose relative to the viewer? or something else? If yes, how is the initial pose of the viewer defined?
Based on the code, the getViewerPose is just retrieving camera pose.
pcl::visualization::PCLVisualizer::getViewerPose (int viewport)
{
Eigen::Affine3f ret (Eigen::Affine3f::Identity ());
rens_->InitTraversal ();
vtkRenderer* renderer = nullptr;
if (viewport == 0)
viewport = 1;
int viewport_i = 1;
while ((renderer = rens_->GetNextItem ()))
{
if (viewport_i == viewport)
{
vtkCamera& camera = *renderer->GetActiveCamera ();
Eigen::Vector3d pos, x_axis, y_axis, z_axis;
camera.GetPosition (pos[0], pos[1], pos[2]);
camera.GetViewUp (y_axis[0], y_axis[1], y_axis[2]);
camera.GetFocalPoint (z_axis[0], z_axis[1], z_axis[2]);
z_axis = (z_axis - pos).normalized ();
x_axis = y_axis.cross (z_axis).normalized ();
ret.translation () = pos.cast<float> ();
ret.linear ().col (0) << x_axis.cast<float> ();
ret.linear ().col (1) << y_axis.cast<float> ();
ret.linear ().col (2) << z_axis.cast<float> ();
return ret;
}
viewport_i ++;
}
return ret;
}
I wrote a program in Qt, which visualizes a processed pointcloud (3D-points) by using Q3DScatter.
Now I want to add calculated keypoints with a different color.
Is that possible?
Does anyboy have some experiences with that?
Below you can see the part of code, where the point cloud is added to the data array.
QScatterDataArray * dataArray = new QScatterDataArray;
dataArray->resize(vector_seg_x->size());
QScatterDataItem * ptrToDataArray = &dataArray->first();
for(int i = 0; i < vector_seg_x->size();i++){
ptrToDataArray->setPosition(QVector3D(
(double)(iter_seg_x[i]),
(double)(iter_seg_y[i]),
(double)(iter_seg_z[i])));
ptrToDataArray++;
}
m_graph_seg->seriesList().at(0)->dataProxy()->resetArray(dataArray);
You can only set a color/gradient for a whole point list:
Q3DScatter scatter;
scatter.setFlags(scatter.flags() ^ Qt::FramelessWindowHint);
scatter.addSeries(new QScatter3DSeries);
scatter.addSeries(new QScatter3DSeries);
{
QScatterDataArray *data = new QScatterDataArray;
*data << QVector3D(0.5f, 0.5f, 0.5f) << QVector3D(-0.3f, -0.5f, -0.4f) << QVector3D(0.0f, -0.3f, 0.2f);
scatter.seriesList().at(0)->dataProxy()->resetArray(data);
QLinearGradient linearGrad(QPointF(100, 100), QPointF(200, 200));
linearGrad.setColorAt(0, Qt::blue);
linearGrad.setColorAt(1, Qt::red);
scatter.seriesList().at(0)->setBaseGradient(linearGrad);
scatter.seriesList().at(0)->setColorStyle(Q3DTheme::ColorStyle::ColorStyleObjectGradient);
}
{
QScatterDataArray *data = new QScatterDataArray;
*data << QVector3D(0.f, 0.f, 0.f);
scatter.seriesList().at(1)->dataProxy()->resetArray(data);
scatter.seriesList().at(1)->setBaseColor(Qt::green);
}
scatter.show();
I'm doing some processing on an Amazon Linux EC2 AWS server. When something goes wrong I need to send an email with a bar graph. I want to generate a bar graph myself, and I'm doing so by using QPainter and QImage. I'm developing an example application to simply generate the bar graph, right now. So what I do is I develop on my laptop and when I have something that works upload the code to the EC2 server and compile it there. Then run the resulting application in the server.
However, here is the hiccup. When I tried to draw text using QPainter, the program in my laptop crashes. This is because I use a QCoreApplication instead of QApplication in my main.cpp.
So I change to QApplication which fixes the problem. I upload the code to the server and compile it. Then when I try to run it, I get:
qt.qpa.screen: QXcbConnection: Could not connect to display
Could not connect to any X display.
This is, of course, because the server is headless.
My question is: is there something I can install in the server that would allow me to fully use QPainter's capabilities?
Edit:
My main.cpp
#include <QApplication>
#include "../../CommonClasses/DataAnalysis/BarGrapher/bargrapher.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Setup
qreal W = 1024;
qreal H = 768;
// A fictional data set;
QList<qreal> ds1;
ds1 << 50 << 500 << 368 << 198;
QStringList descs;
descs << "Item 1";
descs << "A somewhat long and complex description";
descs << "Item 2";
descs << "Item Another";
// The actual bar graph
BarGrapher bg;
bg.configureGraphText(W,H,descs,"Some sort of label","The title of this damn thing");
BarGrapher::DataSet ds;
ds << ds1;
QImage result = bg.generateGraph(ds);
qWarning() << "ERROR" << bg.getError();
result.save("mytest.png");
qWarning() << "DONE";
return a.exec();
}
My bargrapher.cpp
#include "bargrapher.h"
const qreal BarGrapher::PROYECTION_FACTOR = 0.707106;
const qreal BarGrapher::LEFT_MARGIN = 0.1;
const qreal BarGrapher::RIGHT_MARGIN = 0.04;
const qreal BarGrapher::TOP_MARGIN = 0.08;
BarGrapher::BarGrapher()
{
}
void BarGrapher::configureGraphText(qreal width, qreal height, const QStringList &xItems, const QString &ylabel, const QString &title){
graphTitle = title;
W = width;
H = height;
itemDescriptions = xItems;
yAxisText = ylabel;
}
QImage BarGrapher::generateGraph(const DataSet &dataSet){
QImage graph(W,H,QImage::Format_RGB888);
error = "";
// Making sure that the data is coherent.
if (dataSet.isEmpty()){
error = "No data was presented";
return graph;
}
if (dataSet.size() > 2){
error = "Cannot have more than two data sets, passed " + QString::number(dataSet.size());
return graph;
}
qint32 numItems = dataSet.first().size();
for (qint32 i = 0; i < dataSet.size(); i++){
if (numItems != dataSet.at(i).size()){
error = "All data sets must be the same size: " + QString::number(numItems) + " however data set " + QString::number(i) + " has " + QString::number(dataSet.at(i).size());
return graph;
}
}
if (!itemDescriptions.isEmpty()){
if (numItems != itemDescriptions.size()){
error = "The number of item descriptios (" + QString::number(itemDescriptions.size()) + ") must coincide with the numer of points in the data set (" + QString::number(numItems) + ")";
return graph;
}
}
else{
for (qint32 i = 0; i < numItems; i++){
itemDescriptions << QString::number(i);
}
}
// The font to be used
QFont textFont("Mono");
textFont.setPixelSize(10);
//QFont titleFont("Mono",16,QFont::Bold);
// Calculating margins to get the effective graph area.
qreal XAxisLength = (1.0 - LEFT_MARGIN - RIGHT_MARGIN)*W;
qreal DW = XAxisLength/(qreal)(numItems);
// Calculating the effective graph area due to the text items.
qreal Th = 0.1*H;
qreal GH = (1.0-TOP_MARGIN)*H - Th;
qreal xOffset = LEFT_MARGIN*W;
qreal yOffset = TOP_MARGIN*H;
// --------------- Commence drawing -----------------------
QPainter painter(&graph);
// The background
painter.setBrush(QBrush(QColor(226,226,226)));
painter.drawRect(0,0,W,H);
// Drawing the axis;
QPen pen;
pen.setColor(QColor(0,0,0));
pen.setWidth(2);
painter.setPen(pen);
painter.setBrush(QBrush(Qt::black));
painter.drawLine(xOffset,yOffset+GH,xOffset + XAxisLength,yOffset+GH);
painter.drawLine(xOffset,yOffset,xOffset,yOffset+GH);
// Drawing the X Axis text
painter.setFont(textFont);
for (qint32 i = 0; i < numItems; i++){
QRectF rectF(xOffset + i*DW,yOffset+GH,DW,Th);
painter.drawText(rectF,itemDescriptions.at(i));
}
return graph;
}
I got "Error Reading characters of string error" in runtime. And it is not handling with try catch,
void process(const BYTE* pBodyIndexBuffer){
m_pCoordinateMapper->MapCameraPointToDepthSpace(m_pJoints[JointType_ShoulderLeft].Position, &p);
dx = static_cast<int>(p.X + 0.5);
dy = static_cast<int>(p.Y + 0.5);
try
{
if (p.X < 500 && p.X >= 0 && p.Y <= 410 && p.Y >= 0)
{
pPoint = pBodyIndexBuffer[dx + (dy*cDepthWidth)];
while (1) {
if (pPoint == 0xff) break;
pPoint = pBodyIndexBuffer[dx + (dy * cDepthWidth)];
dx -= 1;
dy -= 1;
p.X -= 1;
p.Y -= 1;
OutputDebugString(L"Moved \n");
}
}
m_pBodyEdgeswidth[ShoulderLeft] = getDistance(m_pJoints[JointType_ShoulderLeft].Position, p, distance);
}
catch (const std::exception&)
{
OutputDebugString(L"Error Occured");
}
}
I provided the part of code.
Here is the issue I am facing,
Please explain how to resolve this issue.
But sometimes it starts running without error.
how I am passing is,
BYTE *bodyIndex = NULL;
cm->getBodyIndexStream(&bodyIndex);
if(bodyIndex) process(bodyIndex);
Thanks in advance .
You will need to pass a valid non-null buffer to getBodyIndexStream. You are passing null buffer, which satisfies compiler and will definitely fail at runtime. It is like:
int* ptr = NULL;
// Set value
*ptr = 120; // crash
I have a point cloud data, where by clicking a point, I want to extract points surrounding the clicked point within a radius. I want to also push the extracted points into a new cloud. Using Pointpickingevent, I am able to click one point and push it into the cloud. How do I extract a set of points, say points surrounding 0.02cm radius from the clicked point and push them into a new cloud?
Given a point cloud:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud
A Kdtree is then generated to perform an efficient range search:
pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;
kdtree.setInputCloud (cloud);
Then, given a point and a radius:
pcl::PointXYZ searchPoint(1,2,3);
float radius = 4;
You can get all the points that are at a distance radius from the point searchPoint:
std::vector<int> pointIdxRadiusSearch; //to store index of surrounding points
std::vector<float> pointRadiusSquaredDistance; // to store distance to surrounding points
if ( kdtree.radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0 )
{
for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
std::cout << " " << cloud->points[ pointIdxRadiusSearch[i] ].x
<< " " << cloud->points[ pointIdxRadiusSearch[i] ].y
<< " " << cloud->points[ pointIdxRadiusSearch[i] ].z
<< " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
}
You can print all the surrounding points and their distance to the searchPoint to check the code functional correctness.
Finally, create a cloud with the obtained points:
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZ>);
for (size_t i = 0; i < pointIdxRadiusSearch.size (); ++i)
cloud_cluster->points.push_back(cloud->points[ pointIdxRadiusSearch[i] ]);
cloud_cluster->width = cloud_cluster->points.size ();
cloud_cluster->height = 1;
cloud_cluster->is_dense = true;
In order to be able to pick a point you can use PointPickingEvent similarly to this answer.
The Class declaration in your .h,
class PCLViewer : public QMainWindow
{
Q_OBJECT
public:
explicit PCLViewer (QWidget *parent = 0);
~PCLViewer ();
void pointPickCallback (const pcl::visualization::PointPickingEvent& event, void*);
public slots:
protected:
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud;
pcl::PointXYZ src_point_;
bool src_point_selected_;
private:
Ui::PCLViewer *ui;
};
In your .cpp,
PCLViewer::PCLViewer (QWidget *parent) :
QMainWindow (parent),
ui (new Ui::PCLViewer)
{
ui->setupUi (this);
[...]
viewer.reset (new pcl::visualization::PCLVisualizer ("viewer", false));
viewer->registerPointPickingCallback (&PCLViewer::pointPickCallback, *this);
[...]
}
and the additional function,
void
PCLViewer::pointPickCallback (const pcl::visualization::PointPickingEvent& event, void*)
{
// Check to see if we got a valid point. Early exit.
int idx = event.getPointIndex ();
if (idx == -1)
return;
// Get the point that was picked
event.getPoint (src_point_.x, src_point_.y, src_point_.z);
PCL_INFO ("Src Window: Clicked point %d with X:%f Y:%f Z:%f\n", idx, src_point_.x, src_point_.y, src_point_.z);
src_point_selected_ = true;
}
There is a more detailed example of the utilisation of it in the manual registration app:
pcl/apps/src/manual_registration/manual_registration.cpp
pcl/apps/include/pcl/apps/manual_registration.h