/**
* @brief Sets mv_3d_pointcloud_cb() callback.
* @details Use this function to set mv_3d_pointcloud_cb() callback.
+ * pointcloud is only valid whithin the callback, so user need to copy the pointcloud if necessary.
*
* @since_tizen 7.0
*
+++ /dev/null
-/*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __TIZEN_MEDIAVISION_3D_PRIVATE_H__
-#define __TIZEN_MEDIAVISION_3D_PRIVATE_H__
-
-#include <cstdio>
-#include "mv_3d_type.h"
-
-#ifdef MV_3D_POINTCLOUD_IS_AVAILABLE
-#include <open3d/Open3D.h>
-
-using PointCloudPtr = std::shared_ptr<open3d::geometry::PointCloud>;
-
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/**
- * @file mv_3d_private.h
- * @brief This file contains the internal structure for depth or pointcloud.
- * @since_tizen 7.0
- */
-
-/**
- * @brief structure of pointcloud.
- *
- * @since_tizen 7.0
- *
- */
-typedef struct {
- mv_3d_pointcloud_type_e type { MV_3D_POINTCLOUD_TYPE_PCD_BIN };
-#ifdef MV_3D_POINTCLOUD_IS_AVAILABLE
- PointCloudPtr pointcloud;
-#endif
-} mv_3d_pointcloud_s;
-
-/**
- * @}
- */
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* __TIZEN_MEDIAVISION_3D_PRIVATE_H__ */
MV_3D_POINTCLOUD_TYPE_PLY_BIN /**< Polygon format as binary */
} mv_3d_pointcloud_type_e;
+/**
+ * @brief A point cloud consists of point coordinates and colors and normals.
+ * @details Points are required. colors and normals are optional,
+ * but if present, they always have the same number as num_points.
+ * @since_tizen 8.0
+ *
+ */
+typedef struct {
+ size_t num_points; /**< The number of points */
+ bool has_colors; /**< indicate whether the struct has color */
+ bool has_normals; /**< indicate whether the struct has normal */
+ mv_vec3d_s *points; /**< arrays of 3-dimensional vectors for points */
+ mv_vec3d_s *colors; /**< arrays of 3-dimensional vectors for colors */
+ mv_vec3d_s *normals; /**< arrays of 3-dimensional vectors for normals */
+} mv_3d_pointcloud_s;
+
/**
* @brief The mv3d handle.
* @since_tizen 7.0
MEDIA_VISION_COLORSPACE_RGBA, /**< The colorspace type is RGBA */
} mv_colorspace_e;
+/**
+ * @brief 3×1 vector of type double.
+ * @since_tizen 8.0
+ */
+typedef struct mv_vec3d {
+ double x; /**< The x-component of the vector */
+ double y; /**< The y-component of the vector */
+ double z; /**< The z-component of the vector */
+} mv_vec3d_s;
+
/**
* @brief The handle to the Media Vision API engine algorithms configuration.
* @details Configuration is a dictionary consists of key and value pairs to
PATTERN "mv_3d.h"
PATTERN "mv_3d_type.h"
PATTERN "mv_3d_internal.h"
- PATTERN "mv_3d_private.h"
- )
\ No newline at end of file
+ )
#include "dfs_adaptation_impl.h"
#include "mv_3d.h"
#include "mv_3d_type.h"
-#include "mv_3d_private.h"
/**
* @file Depth.h
static gpointer DfsThreadLoop(gpointer data);
#ifdef MV_3D_POINTCLOUD_IS_AVAILABLE
- PointCloudPtr GetPointcloudFromSource(DfsInputData &intput, DfsOutputData &depthData);
+ mv_3d_pointcloud_s *GetPointcloudFromSource(DfsInputData &intput, DfsOutputData &depthData);
#endif
public:
Mv3d();
}
#ifdef MV_3D_POINTCLOUD_IS_AVAILABLE
-PointCloudPtr Mv3d::GetPointcloudFromSource(DfsInputData &input, DfsOutputData &depthData)
+mv_3d_pointcloud_s *Mv3d::GetPointcloudFromSource(DfsInputData &input, DfsOutputData &depthData)
{
camera::PinholeCameraIntrinsic intrinsic;
io::ReadIJsonConvertible(mIntrinsicPath, intrinsic);
std::tie(pcd, pt_map) = pcd->RemoveRadiusOutliers(mOutlierRemovalPoints, mOutlierRemovalRadius, true);
}
- return pcd;
+ mv_3d_pointcloud_s *_pcd = new mv_3d_pointcloud_s;
+ _pcd->num_points = pcd->points_.size();
+
+ if (pcd->HasPoints()) {
+ _pcd->points = new mv_vec3d_s[_pcd->num_points];
+ memcpy(_pcd->points, pcd->points_.data(), sizeof(double) * 3 * _pcd->num_points);
+ }
+
+ if (pcd->HasColors()) {
+ _pcd->colors = new mv_vec3d_s[_pcd->num_points];
+ _pcd->has_colors = true;
+ memcpy(_pcd->colors, pcd->colors_.data(), sizeof(double) * 3 * _pcd->num_points);
+ } else {
+ _pcd->has_colors = false;
+ }
+
+ if (pcd->HasNormals()) {
+ _pcd->normals = new mv_vec3d_s[_pcd->num_points];
+ _pcd->has_normals = true;
+ memcpy(_pcd->normals, pcd->normals_.data(), sizeof(double) * 3 * _pcd->num_points);
+ } else {
+ _pcd->has_normals = false;
+ }
+
+ return _pcd;
}
#endif
}
#ifdef MV_3D_POINTCLOUD_IS_AVAILABLE
if (mPointcloudCallback) {
- mv_3d_pointcloud_s p { .type = MV_3D_POINTCLOUD_TYPE_PCD_BIN,
- .pointcloud = GetPointcloudFromSource(input, depthData) };
+ mv_3d_pointcloud_s *pcd = GetPointcloudFromSource(input, depthData);
- mPointcloudCallback(baseSource, static_cast<mv_3d_pointcloud_h>(&p), mPointcloudUserData);
+ mPointcloudCallback(baseSource, static_cast<mv_3d_pointcloud_h>(pcd), mPointcloudUserData);
+
+ if (pcd->num_points > 0)
+ delete[] pcd->points;
+ if (pcd->has_colors)
+ delete[] pcd->colors;
+ if (pcd->has_normals)
+ delete[] pcd->normals;
+ delete pcd;
}
#endif
delete[] static_cast<unsigned char *>(input.data);
handle->mDepthUserData);
#ifdef MV_3D_POINTCLOUD_IS_AVAILABLE
if (handle->mPointcloudCallback) {
- mv_3d_pointcloud_s p { .type = MV_3D_POINTCLOUD_TYPE_PCD_BIN,
- .pointcloud = handle->GetPointcloudFromSource(*pInput, depthData) };
+ mv_3d_pointcloud_s *pcd = handle->GetPointcloudFromSource(*pInput, depthData);
- handle->mPointcloudCallback(handle->mInternalSource, static_cast<mv_3d_pointcloud_h>(&p),
+ handle->mPointcloudCallback(handle->mInternalSource, static_cast<mv_3d_pointcloud_h>(pcd),
handle->mPointcloudUserData);
+
+ if (pcd->num_points > 0)
+ delete[] pcd->points;
+ if (pcd->has_colors)
+ delete[] pcd->colors;
+ if (pcd->has_normals)
+ delete[] pcd->normals;
+ delete pcd;
}
#endif
delete[] static_cast<unsigned char *>(pInput->data);
{
#ifdef MV_3D_POINTCLOUD_IS_AVAILABLE
auto s = static_cast<mv_3d_pointcloud_s *>(pointcloud);
- if (!s) {
+ if (!s)
+ return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+
+ if (!s->num_points) {
LOGE("Pointcloud data is NULL");
return MEDIA_VISION_ERROR_INVALID_PARAMETER;
}
+ auto _pcd = std::make_shared<geometry::PointCloud>();
+ _pcd->points_.clear();
+ _pcd->colors_.clear();
+ _pcd->normals_.clear();
+
+ if (s->num_points > 0) {
+ _pcd->points_.resize(s->num_points);
+ memcpy(_pcd->points_.data(), s->points, sizeof(double) * 3 * s->num_points);
+ }
+ utility::LogInfo("pcd points = {}", _pcd->points_.size());
+
+ if (s->has_colors) {
+ _pcd->colors_.resize(s->num_points);
+ memcpy(_pcd->colors_.data(), s->colors, sizeof(double) * 3 * s->num_points);
+ }
+ utility::LogInfo("pcd colors = {}", _pcd->colors_.size());
+
+ if (s->has_normals) {
+ _pcd->normals_.resize(s->num_points);
+ memcpy(_pcd->normals_.data(), s->normals, sizeof(double) * 3 * s->num_points);
+ }
+ utility::LogInfo("OUT >> pcd normals = {}", _pcd->normals_.size());
+
if (access(mPointcloudOutputPath.c_str(), W_OK) != 0) {
if (errno == EACCES || errno == EPERM) {
utility::LogInfo("Fail to access path[%s]: Permission Denied", mPointcloudOutputPath.c_str());
std::string fullPath = mPointcloudOutputPath + std::string("/") + std::string(fileName);
- if (!io::WritePointCloud(fullPath.c_str(), *(s->pointcloud), { bText, false, false, {} })) {
+ if (!io::WritePointCloud(fullPath.c_str(), *_pcd, { bText, false, false, {} })) {
utility::LogError("Failed to write {}", fullPath.c_str());
return MEDIA_VISION_ERROR_INTERNAL;
}
utility::LogInfo("Successfully wrote {}", fullPath.c_str());
+ _pcd->points_.clear();
+ _pcd->colors_.clear();
+ _pcd->normals_.clear();
+
return MEDIA_VISION_ERROR_NONE;
#else
return MEDIA_VISION_ERROR_NOT_SUPPORTED;
#include "mv_3d_internal.h"
#include "mv_private.h"
-#include "mv_3d_private.h"
#include "Mv3d.h"
#define DISTANCE_THRESHOLD 0.01
using namespace mediavision::mv3d;
#endif
+#ifdef MV_3D_POINTCLOUD_IS_AVAILABLE
+static int _convert_to_open3d(mv_3d_pointcloud_s *src, geometry::PointCloud &dst)
+{
+ if (!src)
+ return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+
+ dst.points_.clear();
+ dst.colors_.clear();
+ dst.normals_.clear();
+
+ if (src->num_points > 0) {
+ dst.points_.resize(src->num_points);
+ memcpy(dst.points_.data(), src->points, sizeof(double) * 3 * src->num_points);
+ }
+
+ if (src->has_colors) {
+ dst.colors_.resize(src->num_points);
+ memcpy(dst.colors_.data(), src->colors, sizeof(double) * 3 * src->num_points);
+ }
+
+ if (src->has_normals) {
+ dst.normals_.resize(src->num_points);
+ memcpy(dst.normals_.data(), src->normals, sizeof(double) * 3 * src->num_points);
+ }
+
+ return MEDIA_VISION_ERROR_NONE;
+}
+
+static int _convert_to_mv3d(std::shared_ptr<geometry::PointCloud> src, mv_3d_pointcloud_s *dst)
+{
+ if (!dst)
+ return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+
+ dst->num_points = src->points_.size();
+
+ if (src->HasPoints()) {
+ dst->points = new mv_vec3d_s[dst->num_points];
+ memcpy(dst->points, src->points_.data(), sizeof(double) * 3 * dst->num_points);
+ }
+
+ if (src->HasColors()) {
+ dst->colors = new mv_vec3d_s[dst->num_points];
+ dst->has_colors = true;
+ memcpy(dst->colors, src->colors_.data(), sizeof(double) * 3 * dst->num_points);
+ } else {
+ dst->has_colors = false;
+ }
+
+ if (src->HasNormals()) {
+ dst->normals = new mv_vec3d_s[dst->num_points];
+ dst->has_normals = true;
+ memcpy(dst->normals, src->normals_.data(), sizeof(double) * 3 * dst->num_points);
+ } else {
+ dst->has_normals = false;
+ }
+
+ return MEDIA_VISION_ERROR_NONE;
+}
+#endif
+
#ifdef MV_3D_POINTCLOUD_IS_AVAILABLE
int mv_3d_pointcloud_plane_model_create(mv_3d_pointcloud_plane_model_h *handle)
{
auto s = static_cast<mv_3d_pointcloud_s *>(pointcloud);
+ if (!s->num_points) {
+ LOGE("Pointcloud data is NULL");
+ return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+ }
+
Eigen::Vector4d *best_plane_model = new Eigen::Vector4d;
std::vector<size_t> *plane_inlier = new std::vector<size_t>;
- std::tie(*best_plane_model, *plane_inlier) =
- s->pointcloud->SegmentPlane(DISTANCE_THRESHOLD, RANSAC_NUMBER, NUM_ITERATIONS);
+ auto _pcd = std::make_shared<geometry::PointCloud>();
+ int ret = _convert_to_open3d(s, *_pcd);
+ if (ret != MEDIA_VISION_ERROR_NONE)
+ return ret;
+
+ std::tie(*best_plane_model, *plane_inlier) = _pcd->SegmentPlane(DISTANCE_THRESHOLD, RANSAC_NUMBER, NUM_ITERATIONS);
*model = (mv_3d_pointcloud_plane_model_h) best_plane_model;
*inlier = (mv_3d_pointcloud_plane_inlier_h) plane_inlier;
MEDIA_VISION_NULL_ARG_CHECK(inlier);
MEDIA_VISION_FUNCTION_ENTER();
- auto plane_inlier = static_cast<std::vector<size_t> *>(inlier);
auto s = static_cast<mv_3d_pointcloud_s *>(pointcloud);
- mv_3d_pointcloud_s _pcd { .type = MV_3D_POINTCLOUD_TYPE_PCD_BIN,
- .pointcloud = s->pointcloud->SelectByIndex(*plane_inlier) };
+ if (!s->num_points) {
+ LOGE("Pointcloud data is NULL");
+ return MEDIA_VISION_ERROR_INVALID_PARAMETER;
+ }
+
+ auto _pcd = std::make_shared<geometry::PointCloud>();
+ int ret = _convert_to_open3d(s, *_pcd);
+ if (ret != MEDIA_VISION_ERROR_NONE)
+ return ret;
+
+ auto plane_inlier = static_cast<std::vector<size_t> *>(inlier);
+ auto _pcd_inlier = _pcd->SelectByIndex(*plane_inlier);
+
+ mv_3d_pointcloud_s *pcd_inlier = new mv_3d_pointcloud_s;
+ ret = _convert_to_mv3d(_pcd_inlier, pcd_inlier);
+ if (ret != MEDIA_VISION_ERROR_NONE)
+ return ret;
auto pMv3d = static_cast<Mv3d *>(mv3d);
- int ret = pMv3d->WritePointcloudFile(static_cast<mv_3d_pointcloud_h>(&_pcd), type, filename);
+ ret = pMv3d->WritePointcloudFile(static_cast<mv_3d_pointcloud_h>(pcd_inlier), type, filename);
+
+ if (pcd_inlier->num_points > 0)
+ delete[] pcd_inlier->points;
+ if (pcd_inlier->has_colors)
+ delete[] pcd_inlier->colors;
+ if (pcd_inlier->has_normals)
+ delete[] pcd_inlier->normals;
+ delete pcd_inlier;
+
if (ret != MEDIA_VISION_ERROR_NONE) {
LOGE("Failed to write pointcloud plane file");
ret = MEDIA_VISION_ERROR_INTERNAL;
%{_includedir}/media/mv_3d.h
%{_includedir}/media/mv_3d_type.h
%{_includedir}/media/mv_3d_internal.h
-%{_includedir}/media/mv_3d_private.h
%{_libdir}/pkgconfig/*3d.pc
%endif