Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

order changed after decode? #40

Closed
saedrna opened this issue Jan 20, 2017 · 6 comments
Closed

order changed after decode? #40

saedrna opened this issue Jan 20, 2017 · 6 comments

Comments

@saedrna
Copy link

saedrna commented Jan 20, 2017

Hi,

I am intended to test the accuracy loss of draco encoding and decoding. That is encode a point cloud to buffer and then decode the buffer to point cloud. Then check the difference between the two point clouds (both are saved in col-major Eigen matrix). There should be some accuracy loss, because I have used the qunatization to 14 bits.

However, it seems the result are not correct. Maybe the order has changed after decoding?

Below is my code,
the main function

    MatrixXf points = read_laz_file(ifile);
    unique_ptr<draco::PointCloud> draco_cloud = convert_to_draco(points);

    draco::EncoderBuffer encode_buffer;
    draco::DecoderBuffer decode_buffer;

    draco_encode(draco_cloud, encode_buffer);
    decode_buffer.Init(encode_buffer.data(), encode_buffer.size());

    auto decode_cloud = draco_decode(decode_buffer);
    MatrixXf decode_points = convert_to_eigen(decode_cloud);

    MatrixXf points_error = (points - decode_points).cwiseAbs();

and here is the related functions

unique_ptr<draco::PointCloud> convert_to_draco(const MatrixXf &points) {
    using namespace draco;
    unique_ptr<PointCloud> draco_points = std::make_unique<draco::PointCloud>();

    int num_points = points.cols();
    draco_points->set_num_points(num_points);
    GeometryAttribute va;
    va.Init(GeometryAttribute::POSITION, nullptr, 3, DT_FLOAT32, false, sizeof(float) * 3, 0);
    const int id_att = draco_points->AddAttribute(va, true, num_points);

    for (int i = 0; i < num_points; i++) {
        draco_points->attribute(id_att)->SetAttributeValue(AttributeValueIndex(i), points.col(i).data());
    }

    return draco_points;
}
MatrixXf convert_to_eigen(const unique_ptr<draco::PointCloud> &cloud) {
    using namespace draco;
    int id_pos_att = cloud->GetNamedAttributeId(GeometryAttribute::POSITION);
    int num_points = cloud->num_points();
    MatrixXf vertices(3, num_points);
    const auto *const pos_att = cloud->attribute(id_pos_att);

    for (int i = 0; i < num_points; ++i) {
        auto v = pos_att->GetValue<float, 3>(pos_att->mapped_index(draco::PointIndex(i)));
        vertices(0, i) = v[0];
        vertices(1, i) = v[1];
        vertices(2, i) = v[2];
    }

    return vertices;
}

void draco_encode(const unique_ptr<draco::PointCloud> &cloud, draco::EncoderBuffer &buffer) {
    using namespace draco;
    EncoderOptions options = CreateDefaultEncoderOptions();

    SetNamedAttributeQuantization(&options, *cloud, GeometryAttribute::POSITION, 14);
    SetSpeedOptions(&options, 5, 5);

    draco::EncodePointCloudToBuffer(*cloud, options, &buffer);
}

unique_ptr<draco::PointCloud> draco_decode(draco::DecoderBuffer &buffer) {
    const draco::EncodedGeometryType type = draco::GetEncodedGeometryType(&buffer);
    unique_ptr<draco::PointCloud> cloud;
    if (type == draco::POINT_CLOUD) {
        cloud = draco::DecodePointCloudFromBuffer(&buffer);
    }
    return cloud;
}

@ondys
Copy link
Collaborator

ondys commented Jan 20, 2017

Yes you are right, the order of the points is not preserved for the options that you selected.

Try setting the speed options to: SetSpeedOptions(&options, 10, 10);

anything below 10 currently uses kD-tree compression method which provides better compression but is not order preserving. 10 will use a simple delta + entropy coding on the input points, which is an order preserving approach but the compression ratio is going to be worse.

@saedrna
Copy link
Author

saedrna commented Jan 21, 2017

Thanks. In fact I do not care about the order in practice, so maybe I could try nn search to test the accuracy.

@1f0
Copy link

1f0 commented Mar 15, 2017

It would be really useful if Draco can export vertices order correspondence between uncompressed mesh and origin one. For example, skinning weight data will be useless if the order is lost.

@ondys
Copy link
Collaborator

ondys commented Mar 15, 2017

@mlenta
Skinning weights (or any other vertex attribute) should be encoded as a separate generic attribute inside the mesh. This way, their order is going to match the order of vertices of the decoded mesh.

@themmes
Copy link

themmes commented May 30, 2018

off-topic: @saedrna can you say something about compression rate differences between Draco Pointcloud and LAZ format?

@saedrna
Copy link
Author

saedrna commented May 30, 2018

@themmes Draco wins, but is lossy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants