Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

so, opencv's loadPLYSimple() won't work for your data. you could try to adapt the code from here to fit your specific needs, like:

#include <opencv2/opencv.hpp>
using namespace cv;

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

static std::vector<std::string> split(const std::string &text, char sep) {
  std::vector<std::string> tokens;
  std::size_t start = 0, end = 0;
  while ((end = text.find(sep, start)) != std::string::npos) {
    tokens.push_back(text.substr(start, end - start));
    start = end + 1;
  }
  tokens.push_back(text.substr(start));
  return tokens;
}



bool loadPLY(const char* fileName, std::vector<Point3f> &points, std::vector<Vec3b> &colors)
{
    int numVertices = 0;

    std::ifstream ifs(fileName);

    if (!ifs.is_open())
        CV_Error(Error::StsError, String("Error opening input file: ") + String(fileName) + "\n");

    std::string str;
    while (str.substr(0, 10) != "end_header")
    {
        std::vector<std::string> tokens = split(str,' ');
        if (tokens.size() == 3)
        {
            if (tokens[0] == "element" && tokens[1] == "vertex")
            {
                numVertices = atoi(tokens[2].c_str());
            }
        }
        else if (tokens.size() > 1 && tokens[0] == "format" && tokens[1] != "ascii")
            CV_Error(Error::StsBadArg, String("Cannot read file, only ascii ply format is currently supported..."));
        std::getline(ifs, str);
    }
    for (int i = 0; i < numVertices; i++)
    {
        float x,y,z,nx,ny,nz,curvature; // read *all* in, but only keep points & colors
        int r,g,b;
        ifs >> x >> y >> z >> r >> g >> b >> nx >> ny >> nz >> curvature;
        points.push_back(Point3f(x,y,z));
        colors.push_back(Vec3b(b,g,r));
    }
    return true;
}

int main() {

    std::vector<Point3f> points;
    std::vector<Vec3b> colors;

    loadPLY("cloud.ply", points, colors);
    cout << points[0] << points[1] << endl; // go check, if this is correct !
    cout << colors[0] << colors[1] << endl;
    return 0;
}

then, you could try to render an image from it:

int W = draw_img.cols;
int H = draw_img.rows;
float focal = 5; // e.g from the ply !

Point p(focal * points[i].x / points[i].z, focal * points[i].y / points[i].z); // project to 2d
p.x = p.x * W/2 + W/2; // scale/offset to img coords
p.y = p.y * H/2 + H/2;

cv::circle(draw_img, p, 3, colors[i], -1); // filled circle of some size

so, opencv's loadPLYSimple() won't work for your data. you could try to adapt the code from here to fit your specific needs, like:

#include <opencv2/opencv.hpp>
using namespace cv;

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

static std::vector<std::string> split(const std::string &text, char sep) {
  std::vector<std::string> tokens;
  std::size_t start = 0, end = 0;
  while ((end = text.find(sep, start)) != std::string::npos) {
    tokens.push_back(text.substr(start, end - start));
    start = end + 1;
  }
  tokens.push_back(text.substr(start));
  return tokens;
}



bool loadPLY(const char* fileName, std::vector<Point3f> &points, std::vector<Vec3b> &colors)
{
    int numVertices = 0;

    std::ifstream ifs(fileName);

    if (!ifs.is_open())
        CV_Error(Error::StsError, String("Error opening input file: ") + String(fileName) + "\n");

    std::string str;
    while (str.substr(0, 10) != "end_header")
    {
        std::vector<std::string> tokens = split(str,' ');
        if (tokens.size() == 3)
        {
            if (tokens[0] == "element" && tokens[1] == "vertex")
            {
                numVertices = atoi(tokens[2].c_str());
            }
        }
        else if (tokens.size() > 1 && tokens[0] == "format" && tokens[1] != "ascii")
            CV_Error(Error::StsBadArg, String("Cannot read file, only ascii ply format is currently supported..."));
        std::getline(ifs, str);
    }
    for (int i = 0; i < numVertices; i++)
    {
        float x,y,z,nx,ny,nz,curvature; // read *all* in, but only keep points & colors
        int r,g,b;
        ifs >> x >> y >> z >> r >> g >> b >> nx >> ny >> nz >> curvature;
        points.push_back(Point3f(x,y,z));
        colors.push_back(Vec3b(b,g,r));
    }
    return true;
}

int main() {

    std::vector<Point3f> points;
    std::vector<Vec3b> colors;

    loadPLY("cloud.ply", points, colors);
    cout << points[0] << points[1] << endl; // go check, if this is correct !
    cout << colors[0] << colors[1] << endl;
    return 0;
}

then, you could try to render an image from it:

int W = draw_img.cols;
int H = draw_img.rows;
float focal = 5; // e.g from the ply !

Point p(focal * points[i].x / points[i].z, focal * points[i].y / points[i].z); // project to 2d
p.x = p.x * W/2 + W/2; // scale/offset to img coords
p.y = p.y * H/2 + H/2;

cv::circle(draw_img, p, 3, colors[i], -1); // filled circle of some size

so, opencv's loadPLYSimple() won't work for your data. you could try to adapt the code from here to fit your specific needs, like:

#include <opencv2/opencv.hpp>
using namespace cv;

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;

static std::vector<std::string> split(const std::string &text, char sep) {
  std::vector<std::string> tokens;
  std::size_t start = 0, end = 0;
  while ((end = text.find(sep, start)) != std::string::npos) {
    tokens.push_back(text.substr(start, end - start));
    start = end + 1;
  }
  tokens.push_back(text.substr(start));
  return tokens;
}



bool loadPLY(const char* fileName, std::vector<Point3f> &points, std::vector<Vec3b> &colors)
{
    int numVertices = 0;

    std::ifstream ifs(fileName);

    if (!ifs.is_open())
        CV_Error(Error::StsError, String("Error opening input file: ") + String(fileName) + "\n");

    std::string str;
    while (str.substr(0, 10) != "end_header")
    {
        std::vector<std::string> tokens = split(str,' ');
        if (tokens.size() == 3)
        {
            if (tokens[0] == "element" && tokens[1] == "vertex")
            {
                numVertices = atoi(tokens[2].c_str());
            }
        }
        else if (tokens.size() > 1 && tokens[0] == "format" && tokens[1] != "ascii")
            CV_Error(Error::StsBadArg, String("Cannot read file, only ascii ply format is currently supported..."));
        std::getline(ifs, str);
    }
    for (int i = 0; i < numVertices; i++)
    {
        float x,y,z,nx,ny,nz,curvature; // read *all* in, but only keep points & colors
        int r,g,b;
        ifs >> x >> y >> z >> r >> g >> b >> nx >> ny >> nz >> curvature;
        points.push_back(Point3f(x,y,z));
        colors.push_back(Vec3b(b,g,r));
    }
    return true;
}

int main() {

    std::vector<Point3f> points;
    std::vector<Vec3b> colors;

    loadPLY("cloud.ply", points, colors);
    cout << points[0] << points[1] << endl; // go check, if this is correct !
    cout << colors[0] << colors[1] << endl;
    return 0;
}

then, you could try to render an image from it:

int W = draw_img.cols;
int H = draw_img.rows;
float focal = 5; // e.g from the ply !

// project to 2d
Point p(focal * points[i].x / points[i].z, focal * points[i].y / points[i].z);  // project scale/offset to 2d
img coords
p.x = p.x * W/2 + W/2; // scale/offset to img coords
 p.y = p.y * H/2 + H/2;

cv::circle(draw_img, p, 3, colors[i], -1); // filled circle of some size
cv::circle(draw_img, p, 3, colors[i], -1);