mirror of https://github.com/opencv/opencv.git
Merge pull request #2173 from Nerei:viz
commit
9710b25c7d
45 changed files with 5209 additions and 4090 deletions
@ -1,773 +0,0 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Ozan Tonkal, ozantonkal@gmail.com
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
// OpenCV Viz module is complete rewrite of
|
||||
// PCL visualization module (www.pointclouds.org)
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace viz |
||||
{ |
||||
template<typename _Tp> Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer<vtkPoints>& points); |
||||
} |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Point Cloud Widget implementation
|
||||
|
||||
struct cv::viz::WCloud::CreateCloudWidget |
||||
{ |
||||
static inline vtkSmartPointer<vtkPolyData> create(const Mat &cloud, vtkIdType &nr_points) |
||||
{ |
||||
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New(); |
||||
vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New(); |
||||
|
||||
polydata->SetVerts(vertices); |
||||
|
||||
vtkSmartPointer<vtkPoints> points = polydata->GetPoints(); |
||||
vtkSmartPointer<vtkIdTypeArray> initcells; |
||||
nr_points = cloud.total(); |
||||
|
||||
if (!points) |
||||
{ |
||||
points = vtkSmartPointer<vtkPoints>::New(); |
||||
if (cloud.depth() == CV_32F) |
||||
points->SetDataTypeToFloat(); |
||||
else if (cloud.depth() == CV_64F) |
||||
points->SetDataTypeToDouble(); |
||||
polydata->SetPoints(points); |
||||
} |
||||
points->SetNumberOfPoints(nr_points); |
||||
|
||||
if (cloud.depth() == CV_32F) |
||||
{ |
||||
// Get a pointer to the beginning of the data array
|
||||
Vec3f *data_beg = vtkpoints_data<float>(points); |
||||
Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); |
||||
nr_points = data_end - data_beg; |
||||
} |
||||
else if (cloud.depth() == CV_64F) |
||||
{ |
||||
// Get a pointer to the beginning of the data array
|
||||
Vec3d *data_beg = vtkpoints_data<double>(points); |
||||
Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); |
||||
nr_points = data_end - data_beg; |
||||
} |
||||
points->SetNumberOfPoints(nr_points); |
||||
|
||||
// Update cells
|
||||
vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData(); |
||||
// If no init cells and cells has not been initialized...
|
||||
if (!cells) |
||||
cells = vtkSmartPointer<vtkIdTypeArray>::New(); |
||||
|
||||
// If we have less values then we need to recreate the array
|
||||
if (cells->GetNumberOfTuples() < nr_points) |
||||
{ |
||||
cells = vtkSmartPointer<vtkIdTypeArray>::New(); |
||||
|
||||
// If init cells is given, and there's enough data in it, use it
|
||||
if (initcells && initcells->GetNumberOfTuples() >= nr_points) |
||||
{ |
||||
cells->DeepCopy(initcells); |
||||
cells->SetNumberOfComponents(2); |
||||
cells->SetNumberOfTuples(nr_points); |
||||
} |
||||
else |
||||
{ |
||||
// If the number of tuples is still too small, we need to recreate the array
|
||||
cells->SetNumberOfComponents(2); |
||||
cells->SetNumberOfTuples(nr_points); |
||||
vtkIdType *cell = cells->GetPointer(0); |
||||
// Fill it with 1s
|
||||
std::fill_n(cell, nr_points * 2, 1); |
||||
cell++; |
||||
for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) |
||||
*cell = i; |
||||
// Save the results in initcells
|
||||
initcells = vtkSmartPointer<vtkIdTypeArray>::New(); |
||||
initcells->DeepCopy(cells); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
// The assumption here is that the current set of cells has more data than needed
|
||||
cells->SetNumberOfComponents(2); |
||||
cells->SetNumberOfTuples(nr_points); |
||||
} |
||||
|
||||
// Set the cells and the vertices
|
||||
vertices->SetCells(nr_points, cells); |
||||
return polydata; |
||||
} |
||||
}; |
||||
|
||||
cv::viz::WCloud::WCloud(InputArray _cloud, InputArray _colors) |
||||
{ |
||||
Mat cloud = _cloud.getMat(); |
||||
Mat colors = _colors.getMat(); |
||||
CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); |
||||
CV_Assert(colors.type() == CV_8UC3 && cloud.size() == colors.size()); |
||||
|
||||
if (cloud.isContinuous() && colors.isContinuous()) |
||||
{ |
||||
cloud.reshape(cloud.channels(), 1); |
||||
colors.reshape(colors.channels(), 1); |
||||
} |
||||
|
||||
vtkIdType nr_points; |
||||
vtkSmartPointer<vtkPolyData> polydata = CreateCloudWidget::create(cloud, nr_points); |
||||
|
||||
// Filter colors
|
||||
Vec3b* colors_data = new Vec3b[nr_points]; |
||||
NanFilter::copyColor(colors, colors_data, cloud); |
||||
|
||||
vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New(); |
||||
scalars->SetNumberOfComponents(3); |
||||
scalars->SetNumberOfTuples(nr_points); |
||||
scalars->SetArray(colors_data->val, 3 * nr_points, 0); |
||||
|
||||
// Assign the colors
|
||||
polydata->GetPointData()->SetScalars(scalars); |
||||
|
||||
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New(); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
mapper->SetInput(polydata); |
||||
#else |
||||
mapper->SetInputData(polydata); |
||||
#endif |
||||
|
||||
Vec3d minmax(scalars->GetRange()); |
||||
mapper->SetScalarRange(minmax.val); |
||||
mapper->SetScalarModeToUsePointData(); |
||||
|
||||
bool interpolation = (polydata && polydata->GetNumberOfCells() != polydata->GetNumberOfVerts()); |
||||
|
||||
mapper->SetInterpolateScalarsBeforeMapping(interpolation); |
||||
mapper->ScalarVisibilityOn(); |
||||
|
||||
mapper->ImmediateModeRenderingOff(); |
||||
|
||||
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New(); |
||||
actor->SetNumberOfCloudPoints(int(std::max<vtkIdType>(1, polydata->GetNumberOfPoints() / 10))); |
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->BackfaceCullingOn(); |
||||
actor->SetMapper(mapper); |
||||
|
||||
WidgetAccessor::setProp(*this, actor); |
||||
} |
||||
|
||||
cv::viz::WCloud::WCloud(InputArray _cloud, const Color &color) |
||||
{ |
||||
Mat cloud = _cloud.getMat(); |
||||
CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); |
||||
|
||||
vtkIdType nr_points; |
||||
vtkSmartPointer<vtkPolyData> polydata = CreateCloudWidget::create(cloud, nr_points); |
||||
|
||||
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New(); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
mapper->SetInput(polydata); |
||||
#else |
||||
mapper->SetInputData(polydata); |
||||
#endif |
||||
|
||||
bool interpolation = (polydata && polydata->GetNumberOfCells() != polydata->GetNumberOfVerts()); |
||||
|
||||
mapper->SetInterpolateScalarsBeforeMapping(interpolation); |
||||
mapper->ScalarVisibilityOff(); |
||||
|
||||
mapper->ImmediateModeRenderingOff(); |
||||
|
||||
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New(); |
||||
actor->SetNumberOfCloudPoints(int(std::max<vtkIdType>(1, polydata->GetNumberOfPoints() / 10))); |
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->BackfaceCullingOn(); |
||||
actor->SetMapper(mapper); |
||||
|
||||
WidgetAccessor::setProp(*this, actor); |
||||
setColor(color); |
||||
} |
||||
|
||||
template<> cv::viz::WCloud cv::viz::Widget::cast<cv::viz::WCloud>() |
||||
{ |
||||
Widget3D widget = this->cast<Widget3D>(); |
||||
return static_cast<WCloud&>(widget); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Cloud Collection Widget implementation
|
||||
|
||||
struct cv::viz::WCloudCollection::CreateCloudWidget |
||||
{ |
||||
static inline vtkSmartPointer<vtkPolyData> create(const Mat &cloud, vtkIdType &nr_points) |
||||
{ |
||||
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New(); |
||||
vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New(); |
||||
|
||||
polydata->SetVerts(vertices); |
||||
|
||||
vtkSmartPointer<vtkPoints> points = polydata->GetPoints(); |
||||
vtkSmartPointer<vtkIdTypeArray> initcells; |
||||
nr_points = cloud.total(); |
||||
|
||||
if (!points) |
||||
{ |
||||
points = vtkSmartPointer<vtkPoints>::New(); |
||||
if (cloud.depth() == CV_32F) |
||||
points->SetDataTypeToFloat(); |
||||
else if (cloud.depth() == CV_64F) |
||||
points->SetDataTypeToDouble(); |
||||
polydata->SetPoints(points); |
||||
} |
||||
points->SetNumberOfPoints(nr_points); |
||||
|
||||
if (cloud.depth() == CV_32F) |
||||
{ |
||||
// Get a pointer to the beginning of the data array
|
||||
Vec3f *data_beg = vtkpoints_data<float>(points); |
||||
Vec3f *data_end = NanFilter::copy(cloud, data_beg, cloud); |
||||
nr_points = data_end - data_beg; |
||||
} |
||||
else if (cloud.depth() == CV_64F) |
||||
{ |
||||
// Get a pointer to the beginning of the data array
|
||||
Vec3d *data_beg = vtkpoints_data<double>(points); |
||||
Vec3d *data_end = NanFilter::copy(cloud, data_beg, cloud); |
||||
nr_points = data_end - data_beg; |
||||
} |
||||
points->SetNumberOfPoints(nr_points); |
||||
|
||||
// Update cells
|
||||
vtkSmartPointer<vtkIdTypeArray> cells = vertices->GetData(); |
||||
// If no init cells and cells has not been initialized...
|
||||
if (!cells) |
||||
cells = vtkSmartPointer<vtkIdTypeArray>::New(); |
||||
|
||||
// If we have less values then we need to recreate the array
|
||||
if (cells->GetNumberOfTuples() < nr_points) |
||||
{ |
||||
cells = vtkSmartPointer<vtkIdTypeArray>::New(); |
||||
|
||||
// If init cells is given, and there's enough data in it, use it
|
||||
if (initcells && initcells->GetNumberOfTuples() >= nr_points) |
||||
{ |
||||
cells->DeepCopy(initcells); |
||||
cells->SetNumberOfComponents(2); |
||||
cells->SetNumberOfTuples(nr_points); |
||||
} |
||||
else |
||||
{ |
||||
// If the number of tuples is still too small, we need to recreate the array
|
||||
cells->SetNumberOfComponents(2); |
||||
cells->SetNumberOfTuples(nr_points); |
||||
vtkIdType *cell = cells->GetPointer(0); |
||||
// Fill it with 1s
|
||||
std::fill_n(cell, nr_points * 2, 1); |
||||
cell++; |
||||
for (vtkIdType i = 0; i < nr_points; ++i, cell += 2) |
||||
*cell = i; |
||||
// Save the results in initcells
|
||||
initcells = vtkSmartPointer<vtkIdTypeArray>::New(); |
||||
initcells->DeepCopy(cells); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
// The assumption here is that the current set of cells has more data than needed
|
||||
cells->SetNumberOfComponents(2); |
||||
cells->SetNumberOfTuples(nr_points); |
||||
} |
||||
|
||||
// Set the cells and the vertices
|
||||
vertices->SetCells(nr_points, cells); |
||||
return polydata; |
||||
} |
||||
|
||||
static void createMapper(vtkSmartPointer<vtkLODActor> actor, vtkSmartPointer<vtkPolyData> poly_data, Vec3d& minmax) |
||||
{ |
||||
vtkDataSetMapper *mapper = vtkDataSetMapper::SafeDownCast(actor->GetMapper()); |
||||
if (!mapper) |
||||
{ |
||||
// This is the first cloud
|
||||
vtkSmartPointer<vtkDataSetMapper> mapper_new = vtkSmartPointer<vtkDataSetMapper>::New(); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
mapper_new->SetInputConnection(poly_data->GetProducerPort()); |
||||
#else |
||||
mapper_new->SetInputData(poly_data); |
||||
#endif |
||||
|
||||
mapper_new->SetScalarRange(minmax.val); |
||||
mapper_new->SetScalarModeToUsePointData(); |
||||
|
||||
bool interpolation = (poly_data && poly_data->GetNumberOfCells() != poly_data->GetNumberOfVerts()); |
||||
|
||||
mapper_new->SetInterpolateScalarsBeforeMapping(interpolation); |
||||
mapper_new->ScalarVisibilityOn(); |
||||
mapper_new->ImmediateModeRenderingOff(); |
||||
|
||||
actor->SetNumberOfCloudPoints(int(std::max<vtkIdType>(1, poly_data->GetNumberOfPoints() / 10))); |
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->BackfaceCullingOn(); |
||||
actor->SetMapper(mapper_new); |
||||
return ; |
||||
} |
||||
|
||||
vtkPolyData *data = vtkPolyData::SafeDownCast(mapper->GetInput()); |
||||
CV_Assert("Cloud Widget without data" && data); |
||||
|
||||
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New(); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
appendFilter->AddInputConnection(mapper->GetInput()->GetProducerPort()); |
||||
appendFilter->AddInputConnection(poly_data->GetProducerPort()); |
||||
#else |
||||
appendFilter->AddInputData(data); |
||||
appendFilter->AddInputData(poly_data); |
||||
#endif |
||||
mapper->SetInputConnection(appendFilter->GetOutputPort()); |
||||
|
||||
// Update the number of cloud points
|
||||
vtkIdType old_cloud_points = actor->GetNumberOfCloudPoints(); |
||||
actor->SetNumberOfCloudPoints(int(std::max<vtkIdType>(1, old_cloud_points+poly_data->GetNumberOfPoints() / 10))); |
||||
} |
||||
}; |
||||
|
||||
cv::viz::WCloudCollection::WCloudCollection() |
||||
{ |
||||
// Just create the actor
|
||||
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New(); |
||||
WidgetAccessor::setProp(*this, actor); |
||||
} |
||||
|
||||
void cv::viz::WCloudCollection::addCloud(InputArray _cloud, InputArray _colors, const Affine3f &pose) |
||||
{ |
||||
Mat cloud = _cloud.getMat(); |
||||
Mat colors = _colors.getMat(); |
||||
CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); |
||||
CV_Assert(colors.type() == CV_8UC3 && cloud.size() == colors.size()); |
||||
|
||||
if (cloud.isContinuous() && colors.isContinuous()) |
||||
{ |
||||
cloud.reshape(cloud.channels(), 1); |
||||
colors.reshape(colors.channels(), 1); |
||||
} |
||||
|
||||
vtkIdType nr_points; |
||||
vtkSmartPointer<vtkPolyData> polydata = CreateCloudWidget::create(cloud, nr_points); |
||||
|
||||
// Filter colors
|
||||
Vec3b* colors_data = new Vec3b[nr_points]; |
||||
NanFilter::copyColor(colors, colors_data, cloud); |
||||
|
||||
vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New(); |
||||
scalars->SetNumberOfComponents(3); |
||||
scalars->SetNumberOfTuples(nr_points); |
||||
scalars->SetArray(colors_data->val, 3 * nr_points, 0); |
||||
|
||||
// Assign the colors
|
||||
polydata->GetPointData()->SetScalars(scalars); |
||||
|
||||
// Transform the poly data based on the pose
|
||||
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); |
||||
transform->PreMultiply(); |
||||
transform->SetMatrix(convertToVtkMatrix(pose.matrix)); |
||||
|
||||
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); |
||||
transform_filter->SetTransform(transform); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
transform_filter->SetInputConnection(polydata->GetProducerPort()); |
||||
#else |
||||
transform_filter->SetInputData(polydata); |
||||
#endif |
||||
transform_filter->Update(); |
||||
|
||||
vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); |
||||
CV_Assert("Incompatible widget type." && actor); |
||||
|
||||
Vec3d minmax(scalars->GetRange()); |
||||
CreateCloudWidget::createMapper(actor, transform_filter->GetOutput(), minmax); |
||||
} |
||||
|
||||
void cv::viz::WCloudCollection::addCloud(InputArray _cloud, const Color &color, const Affine3f &pose) |
||||
{ |
||||
Mat cloud = _cloud.getMat(); |
||||
CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); |
||||
|
||||
vtkIdType nr_points; |
||||
vtkSmartPointer<vtkPolyData> polydata = CreateCloudWidget::create(cloud, nr_points); |
||||
|
||||
vtkSmartPointer<vtkUnsignedCharArray> scalars = vtkSmartPointer<vtkUnsignedCharArray>::New(); |
||||
scalars->SetNumberOfComponents(3); |
||||
scalars->SetNumberOfTuples(nr_points); |
||||
scalars->FillComponent(0, color[2]); |
||||
scalars->FillComponent(1, color[1]); |
||||
scalars->FillComponent(2, color[0]); |
||||
|
||||
// Assign the colors
|
||||
polydata->GetPointData()->SetScalars(scalars); |
||||
|
||||
// Transform the poly data based on the pose
|
||||
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); |
||||
transform->PreMultiply(); |
||||
transform->SetMatrix(convertToVtkMatrix(pose.matrix)); |
||||
|
||||
vtkSmartPointer<vtkTransformPolyDataFilter> transform_filter = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); |
||||
transform_filter->SetTransform(transform); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
transform_filter->SetInputConnection(polydata->GetProducerPort()); |
||||
#else |
||||
transform_filter->SetInputData(polydata); |
||||
#endif |
||||
transform_filter->Update(); |
||||
|
||||
vtkLODActor *actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); |
||||
CV_Assert("Incompatible widget type." && actor); |
||||
|
||||
Vec3d minmax(scalars->GetRange()); |
||||
CreateCloudWidget::createMapper(actor, transform_filter->GetOutput(), minmax); |
||||
} |
||||
|
||||
template<> cv::viz::WCloudCollection cv::viz::Widget::cast<cv::viz::WCloudCollection>() |
||||
{ |
||||
Widget3D widget = this->cast<Widget3D>(); |
||||
return static_cast<WCloudCollection&>(widget); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Cloud Normals Widget implementation
|
||||
|
||||
struct cv::viz::WCloudNormals::ApplyCloudNormals |
||||
{ |
||||
template<typename _Tp> |
||||
struct Impl |
||||
{ |
||||
static vtkSmartPointer<vtkCellArray> applyOrganized(const Mat &cloud, const Mat& normals, double level, float scale, _Tp *&pts, vtkIdType &nr_normals) |
||||
{ |
||||
vtkIdType point_step = static_cast<vtkIdType>(std::sqrt(level)); |
||||
nr_normals = (static_cast<vtkIdType>((cloud.cols - 1) / point_step) + 1) * |
||||
(static_cast<vtkIdType>((cloud.rows - 1) / point_step) + 1); |
||||
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); |
||||
|
||||
pts = new _Tp[2 * nr_normals * 3]; |
||||
|
||||
int cch = cloud.channels(); |
||||
vtkIdType cell_count = 0; |
||||
for (vtkIdType y = 0; y < cloud.rows; y += point_step) |
||||
{ |
||||
const _Tp *prow = cloud.ptr<_Tp>(y); |
||||
const _Tp *nrow = normals.ptr<_Tp>(y); |
||||
for (vtkIdType x = 0; x < cloud.cols; x += point_step * cch) |
||||
{ |
||||
pts[2 * cell_count * 3 + 0] = prow[x]; |
||||
pts[2 * cell_count * 3 + 1] = prow[x+1]; |
||||
pts[2 * cell_count * 3 + 2] = prow[x+2]; |
||||
pts[2 * cell_count * 3 + 3] = prow[x] + nrow[x] * scale; |
||||
pts[2 * cell_count * 3 + 4] = prow[x+1] + nrow[x+1] * scale; |
||||
pts[2 * cell_count * 3 + 5] = prow[x+2] + nrow[x+2] * scale; |
||||
|
||||
lines->InsertNextCell(2); |
||||
lines->InsertCellPoint(2 * cell_count); |
||||
lines->InsertCellPoint(2 * cell_count + 1); |
||||
cell_count++; |
||||
} |
||||
} |
||||
return lines; |
||||
} |
||||
|
||||
static vtkSmartPointer<vtkCellArray> applyUnorganized(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) |
||||
{ |
||||
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); |
||||
nr_normals = (cloud.size().area() - 1) / level + 1 ; |
||||
pts = new _Tp[2 * nr_normals * 3]; |
||||
|
||||
int cch = cloud.channels(); |
||||
const _Tp *p = cloud.ptr<_Tp>(); |
||||
const _Tp *n = normals.ptr<_Tp>(); |
||||
for (vtkIdType i = 0, j = 0; j < nr_normals; j++, i = j * level * cch) |
||||
{ |
||||
|
||||
pts[2 * j * 3 + 0] = p[i]; |
||||
pts[2 * j * 3 + 1] = p[i+1]; |
||||
pts[2 * j * 3 + 2] = p[i+2]; |
||||
pts[2 * j * 3 + 3] = p[i] + n[i] * scale; |
||||
pts[2 * j * 3 + 4] = p[i+1] + n[i+1] * scale; |
||||
pts[2 * j * 3 + 5] = p[i+2] + n[i+2] * scale; |
||||
|
||||
lines->InsertNextCell(2); |
||||
lines->InsertCellPoint(2 * j); |
||||
lines->InsertCellPoint(2 * j + 1); |
||||
} |
||||
return lines; |
||||
} |
||||
}; |
||||
|
||||
template<typename _Tp> |
||||
static inline vtkSmartPointer<vtkCellArray> apply(const Mat &cloud, const Mat& normals, int level, float scale, _Tp *&pts, vtkIdType &nr_normals) |
||||
{ |
||||
if (cloud.cols > 1 && cloud.rows > 1) |
||||
return ApplyCloudNormals::Impl<_Tp>::applyOrganized(cloud, normals, level, scale, pts, nr_normals); |
||||
else |
||||
return ApplyCloudNormals::Impl<_Tp>::applyUnorganized(cloud, normals, level, scale, pts, nr_normals); |
||||
} |
||||
}; |
||||
|
||||
cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, int level, float scale, const Color &color) |
||||
{ |
||||
Mat cloud = _cloud.getMat(); |
||||
Mat normals = _normals.getMat(); |
||||
CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); |
||||
CV_Assert(cloud.size() == normals.size() && cloud.type() == normals.type()); |
||||
|
||||
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); |
||||
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); |
||||
vtkIdType nr_normals = 0; |
||||
|
||||
if (cloud.depth() == CV_32F) |
||||
{ |
||||
points->SetDataTypeToFloat(); |
||||
|
||||
vtkSmartPointer<vtkFloatArray> data = vtkSmartPointer<vtkFloatArray>::New(); |
||||
data->SetNumberOfComponents(3); |
||||
|
||||
float* pts = 0; |
||||
lines = ApplyCloudNormals::apply(cloud, normals, level, scale, pts, nr_normals); |
||||
data->SetArray(&pts[0], 2 * nr_normals * 3, 0); |
||||
points->SetData(data); |
||||
} |
||||
else |
||||
{ |
||||
points->SetDataTypeToDouble(); |
||||
|
||||
vtkSmartPointer<vtkDoubleArray> data = vtkSmartPointer<vtkDoubleArray>::New(); |
||||
data->SetNumberOfComponents(3); |
||||
|
||||
double* pts = 0; |
||||
lines = ApplyCloudNormals::apply(cloud, normals, level, scale, pts, nr_normals); |
||||
data->SetArray(&pts[0], 2 * nr_normals * 3, 0); |
||||
points->SetData(data); |
||||
} |
||||
|
||||
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New(); |
||||
polyData->SetPoints(points); |
||||
polyData->SetLines(lines); |
||||
|
||||
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New(); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
mapper->SetInput(polyData); |
||||
#else |
||||
mapper->SetInputData(polyData); |
||||
#endif |
||||
mapper->SetColorModeToMapScalars(); |
||||
mapper->SetScalarModeToUsePointData(); |
||||
|
||||
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New(); |
||||
actor->SetMapper(mapper); |
||||
WidgetAccessor::setProp(*this, actor); |
||||
setColor(color); |
||||
} |
||||
|
||||
template<> cv::viz::WCloudNormals cv::viz::Widget::cast<cv::viz::WCloudNormals>() |
||||
{ |
||||
Widget3D widget = this->cast<Widget3D>(); |
||||
return static_cast<WCloudNormals&>(widget); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Mesh Widget implementation
|
||||
|
||||
struct cv::viz::WMesh::CopyImpl |
||||
{ |
||||
template<typename _Tp> |
||||
static Vec<_Tp, 3> * copy(const Mat &source, Vec<_Tp, 3> *output, int *look_up, const Mat &nan_mask) |
||||
{ |
||||
CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); |
||||
CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); |
||||
CV_DbgAssert(DataDepth<_Tp>::value == nan_mask.depth()); |
||||
|
||||
int s_chs = source.channels(); |
||||
int m_chs = nan_mask.channels(); |
||||
|
||||
int index = 0; |
||||
const _Tp* srow = source.ptr<_Tp>(0); |
||||
const _Tp* mrow = nan_mask.ptr<_Tp>(0); |
||||
|
||||
for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) |
||||
{ |
||||
if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) |
||||
{ |
||||
look_up[x] = index; |
||||
*output++ = Vec<_Tp, 3>(srow); |
||||
++index; |
||||
} |
||||
} |
||||
return output; |
||||
} |
||||
}; |
||||
|
||||
cv::viz::WMesh::WMesh(const Mesh3d &mesh) |
||||
{ |
||||
CV_Assert(mesh.cloud.rows == 1 && (mesh.cloud.type() == CV_32FC3 || mesh.cloud.type() == CV_64FC3 || mesh.cloud.type() == CV_32FC4 || mesh.cloud.type() == CV_64FC4)); |
||||
CV_Assert(mesh.colors.empty() || (mesh.colors.type() == CV_8UC3 && mesh.cloud.size() == mesh.colors.size())); |
||||
CV_Assert(!mesh.polygons.empty() && mesh.polygons.type() == CV_32SC1); |
||||
|
||||
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); |
||||
vtkIdType nr_points = mesh.cloud.total(); |
||||
Mat look_up_mat(1, nr_points, CV_32SC1); |
||||
int * look_up = look_up_mat.ptr<int>(); |
||||
points->SetNumberOfPoints(nr_points); |
||||
|
||||
// Copy data from cloud to vtkPoints
|
||||
if (mesh.cloud.depth() == CV_32F) |
||||
{ |
||||
points->SetDataTypeToFloat(); |
||||
Vec3f *data_beg = vtkpoints_data<float>(points); |
||||
Vec3f *data_end = CopyImpl::copy(mesh.cloud, data_beg, look_up, mesh.cloud); |
||||
nr_points = data_end - data_beg; |
||||
} |
||||
else |
||||
{ |
||||
points->SetDataTypeToDouble(); |
||||
Vec3d *data_beg = vtkpoints_data<double>(points); |
||||
Vec3d *data_end = CopyImpl::copy(mesh.cloud, data_beg, look_up, mesh.cloud); |
||||
nr_points = data_end - data_beg; |
||||
} |
||||
|
||||
vtkSmartPointer<vtkUnsignedCharArray> scalars; |
||||
|
||||
if (!mesh.colors.empty()) |
||||
{ |
||||
Vec3b * colors_data = 0; |
||||
colors_data = new Vec3b[nr_points]; |
||||
NanFilter::copyColor(mesh.colors, colors_data, mesh.cloud); |
||||
|
||||
scalars = vtkSmartPointer<vtkUnsignedCharArray>::New(); |
||||
scalars->SetNumberOfComponents(3); |
||||
scalars->SetNumberOfTuples(nr_points); |
||||
scalars->SetArray(colors_data->val, 3 * nr_points, 0); |
||||
} |
||||
|
||||
points->SetNumberOfPoints(nr_points); |
||||
|
||||
vtkSmartPointer<vtkPointSet> data; |
||||
|
||||
if (mesh.polygons.size().area() > 1) |
||||
{ |
||||
vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New(); |
||||
const int * polygons = mesh.polygons.ptr<int>(); |
||||
|
||||
int idx = 0; |
||||
int poly_size = mesh.polygons.total(); |
||||
for (int i = 0; i < poly_size; ++idx) |
||||
{ |
||||
int n_points = polygons[i++]; |
||||
|
||||
cell_array->InsertNextCell(n_points); |
||||
for (int j = 0; j < n_points; ++j, ++idx) |
||||
cell_array->InsertCellPoint(look_up[polygons[i++]]); |
||||
} |
||||
vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New(); |
||||
cell_array->GetData()->SetNumberOfValues(idx); |
||||
cell_array->Squeeze(); |
||||
polydata->SetStrips(cell_array); |
||||
polydata->SetPoints(points); |
||||
|
||||
if (scalars) |
||||
polydata->GetPointData()->SetScalars(scalars); |
||||
|
||||
data = polydata; |
||||
} |
||||
else |
||||
{ |
||||
// Only one polygon
|
||||
vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New(); |
||||
const int * polygons = mesh.polygons.ptr<int>(); |
||||
int n_points = polygons[0]; |
||||
|
||||
polygon->GetPointIds()->SetNumberOfIds(n_points); |
||||
|
||||
for (int j = 1; j < n_points+1; ++j) |
||||
polygon->GetPointIds()->SetId(j, look_up[polygons[j]]); |
||||
|
||||
vtkSmartPointer<vtkUnstructuredGrid> poly_grid = vtkSmartPointer<vtkUnstructuredGrid>::New(); |
||||
poly_grid->Allocate(1, 1); |
||||
poly_grid->InsertNextCell(polygon->GetCellType(), polygon->GetPointIds()); |
||||
poly_grid->SetPoints(points); |
||||
|
||||
if (scalars) |
||||
poly_grid->GetPointData()->SetScalars(scalars); |
||||
|
||||
data = poly_grid; |
||||
} |
||||
|
||||
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New(); |
||||
|
||||
actor->GetProperty()->SetRepresentationToSurface(); |
||||
actor->GetProperty()->BackfaceCullingOff(); // Backface culling is off for higher efficiency
|
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->EdgeVisibilityOff(); |
||||
actor->GetProperty()->ShadingOff(); |
||||
|
||||
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New(); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
mapper->SetInput(data); |
||||
#else |
||||
mapper->SetInputData(data); |
||||
#endif |
||||
mapper->ImmediateModeRenderingOff(); |
||||
|
||||
vtkIdType numberOfCloudPoints = nr_points * 0.1; |
||||
actor->SetNumberOfCloudPoints(int(numberOfCloudPoints > 1 ? numberOfCloudPoints : 1)); |
||||
actor->SetMapper(mapper); |
||||
|
||||
WidgetAccessor::setProp(*this, actor); |
||||
} |
||||
|
||||
template<> CV_EXPORTS cv::viz::WMesh cv::viz::Widget::cast<cv::viz::WMesh>() |
||||
{ |
||||
Widget3D widget = this->cast<Widget3D>(); |
||||
return static_cast<WMesh&>(widget); |
||||
} |
@ -0,0 +1,441 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Ozan Tonkal, ozantonkal@gmail.com
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Point Cloud Widget implementation
|
||||
|
||||
cv::viz::WCloud::WCloud(InputArray cloud, InputArray colors) |
||||
{ |
||||
CV_Assert(!cloud.empty() && !colors.empty()); |
||||
|
||||
vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New(); |
||||
cloud_source->SetColorCloud(cloud, colors); |
||||
cloud_source->Update(); |
||||
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); |
||||
VtkUtils::SetInputData(mapper, cloud_source->GetOutput()); |
||||
mapper->SetScalarModeToUsePointData(); |
||||
mapper->ImmediateModeRenderingOff(); |
||||
mapper->SetScalarRange(0, 255); |
||||
mapper->ScalarVisibilityOn(); |
||||
|
||||
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); |
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->BackfaceCullingOn(); |
||||
actor->SetMapper(mapper); |
||||
|
||||
WidgetAccessor::setProp(*this, actor); |
||||
} |
||||
|
||||
cv::viz::WCloud::WCloud(InputArray cloud, const Color &color) |
||||
{ |
||||
WCloud cloud_widget(cloud, Mat(cloud.size(), CV_8UC3, color)); |
||||
*this = cloud_widget; |
||||
} |
||||
|
||||
|
||||
template<> cv::viz::WCloud cv::viz::Widget::cast<cv::viz::WCloud>() |
||||
{ |
||||
Widget3D widget = this->cast<Widget3D>(); |
||||
return static_cast<WCloud&>(widget); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Painted Cloud Widget implementation
|
||||
|
||||
cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud) |
||||
{ |
||||
vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New(); |
||||
cloud_source->SetCloud(cloud); |
||||
cloud_source->Update(); |
||||
|
||||
Vec6d bounds(cloud_source->GetOutput()->GetPoints()->GetBounds()); |
||||
|
||||
vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::New(); |
||||
elevation->SetInputConnection(cloud_source->GetOutputPort()); |
||||
elevation->SetLowPoint(bounds[0], bounds[2], bounds[4]); |
||||
elevation->SetHighPoint(bounds[1], bounds[3], bounds[5]); |
||||
elevation->SetScalarRange(0.0, 1.0); |
||||
elevation->Update(); |
||||
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); |
||||
VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); |
||||
mapper->ImmediateModeRenderingOff(); |
||||
mapper->ScalarVisibilityOn(); |
||||
mapper->SetColorModeToMapScalars(); |
||||
|
||||
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); |
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->BackfaceCullingOn(); |
||||
actor->SetMapper(mapper); |
||||
|
||||
WidgetAccessor::setProp(*this, actor); |
||||
} |
||||
|
||||
cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2) |
||||
{ |
||||
vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New(); |
||||
cloud_source->SetCloud(cloud); |
||||
|
||||
vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::New(); |
||||
elevation->SetInputConnection(cloud_source->GetOutputPort()); |
||||
elevation->SetLowPoint(p1.x, p1.y, p1.z); |
||||
elevation->SetHighPoint(p2.x, p2.y, p2.z); |
||||
elevation->SetScalarRange(0.0, 1.0); |
||||
elevation->Update(); |
||||
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); |
||||
VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); |
||||
mapper->ImmediateModeRenderingOff(); |
||||
mapper->ScalarVisibilityOn(); |
||||
mapper->SetColorModeToMapScalars(); |
||||
|
||||
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); |
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->BackfaceCullingOn(); |
||||
actor->SetMapper(mapper); |
||||
|
||||
WidgetAccessor::setProp(*this, actor); |
||||
} |
||||
|
||||
cv::viz::WPaintedCloud::WPaintedCloud(InputArray cloud, const Point3d& p1, const Point3d& p2, const Color& c1, const Color c2) |
||||
{ |
||||
vtkSmartPointer<vtkCloudMatSource> cloud_source = vtkSmartPointer<vtkCloudMatSource>::New(); |
||||
cloud_source->SetCloud(cloud); |
||||
|
||||
vtkSmartPointer<vtkElevationFilter> elevation = vtkSmartPointer<vtkElevationFilter>::New(); |
||||
elevation->SetInputConnection(cloud_source->GetOutputPort()); |
||||
elevation->SetLowPoint(p1.x, p1.y, p1.z); |
||||
elevation->SetHighPoint(p2.x, p2.y, p2.z); |
||||
elevation->SetScalarRange(0.0, 1.0); |
||||
elevation->Update(); |
||||
|
||||
Color vc1 = vtkcolor(c1), vc2 = vtkcolor(c2); |
||||
vtkSmartPointer<vtkColorTransferFunction> color_transfer = vtkSmartPointer<vtkColorTransferFunction>::New(); |
||||
color_transfer->SetColorSpaceToRGB(); |
||||
color_transfer->AddRGBPoint(0.0, vc1[0], vc1[1], vc1[2]); |
||||
color_transfer->AddRGBPoint(1.0, vc2[0], vc2[1], vc2[2]); |
||||
color_transfer->SetScaleToLinear(); |
||||
color_transfer->Build(); |
||||
|
||||
//if in future some need to replace color table with real scalars, then this can be done usine next calls:
|
||||
//vtkDataArray *float_scalars = vtkPolyData::SafeDownCast(elevation->GetOutput())->GetPointData()->GetArray("Elevation");
|
||||
//vtkSmartPointer<vtkPolyData> polydata = cloud_source->GetOutput();
|
||||
//polydata->GetPointData()->SetScalars(color_transfer->MapScalars(float_scalars, VTK_COLOR_MODE_DEFAULT, 0));
|
||||
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); |
||||
VtkUtils::SetInputData(mapper, vtkPolyData::SafeDownCast(elevation->GetOutput())); |
||||
mapper->ImmediateModeRenderingOff(); |
||||
mapper->ScalarVisibilityOn(); |
||||
mapper->SetColorModeToMapScalars(); |
||||
mapper->SetLookupTable(color_transfer); |
||||
|
||||
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); |
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->BackfaceCullingOn(); |
||||
actor->SetMapper(mapper); |
||||
|
||||
WidgetAccessor::setProp(*this, actor); |
||||
} |
||||
|
||||
template<> cv::viz::WPaintedCloud cv::viz::Widget::cast<cv::viz::WPaintedCloud>() |
||||
{ |
||||
Widget3D widget = this->cast<Widget3D>(); |
||||
return static_cast<WPaintedCloud&>(widget); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Cloud Collection Widget implementation
|
||||
|
||||
cv::viz::WCloudCollection::WCloudCollection() |
||||
{ |
||||
// Just create the actor
|
||||
vtkSmartPointer<vtkLODActor> actor = vtkSmartPointer<vtkLODActor>::New(); |
||||
WidgetAccessor::setProp(*this, actor); |
||||
} |
||||
|
||||
void cv::viz::WCloudCollection::addCloud(InputArray cloud, InputArray colors, const Affine3d &pose) |
||||
{ |
||||
vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New(); |
||||
source->SetColorCloud(cloud, colors); |
||||
|
||||
vtkSmartPointer<vtkPolyData> polydata = VtkUtils::TransformPolydata(source->GetOutputPort(), pose); |
||||
|
||||
vtkSmartPointer<vtkLODActor> actor = vtkLODActor::SafeDownCast(WidgetAccessor::getProp(*this)); |
||||
CV_Assert("Incompatible widget type." && actor); |
||||
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkPolyDataMapper::SafeDownCast(actor->GetMapper()); |
||||
if (!mapper) |
||||
{ |
||||
// This is the first cloud
|
||||
mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); |
||||
mapper->SetScalarRange(0, 255); |
||||
mapper->SetScalarModeToUsePointData(); |
||||
mapper->ScalarVisibilityOn(); |
||||
mapper->ImmediateModeRenderingOff(); |
||||
VtkUtils::SetInputData(mapper, polydata); |
||||
|
||||
actor->SetNumberOfCloudPoints(std::max<vtkIdType>(1, polydata->GetNumberOfPoints()/10)); |
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->BackfaceCullingOn(); |
||||
actor->SetMapper(mapper); |
||||
return; |
||||
} |
||||
|
||||
vtkPolyData *currdata = vtkPolyData::SafeDownCast(mapper->GetInput()); |
||||
CV_Assert("Cloud Widget without data" && currdata); |
||||
|
||||
vtkSmartPointer<vtkAppendPolyData> append_filter = vtkSmartPointer<vtkAppendPolyData>::New(); |
||||
VtkUtils::AddInputData(append_filter, currdata); |
||||
VtkUtils::AddInputData(append_filter, polydata); |
||||
append_filter->Update(); |
||||
|
||||
VtkUtils::SetInputData(mapper, append_filter->GetOutput()); |
||||
|
||||
actor->SetNumberOfCloudPoints(std::max<vtkIdType>(1, actor->GetNumberOfCloudPoints() + polydata->GetNumberOfPoints()/10)); |
||||
} |
||||
|
||||
void cv::viz::WCloudCollection::addCloud(InputArray cloud, const Color &color, const Affine3d &pose) |
||||
{ |
||||
addCloud(cloud, Mat(cloud.size(), CV_8UC3, color), pose); |
||||
} |
||||
|
||||
template<> cv::viz::WCloudCollection cv::viz::Widget::cast<cv::viz::WCloudCollection>() |
||||
{ |
||||
Widget3D widget = this->cast<Widget3D>(); |
||||
return static_cast<WCloudCollection&>(widget); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Cloud Normals Widget implementation
|
||||
|
||||
cv::viz::WCloudNormals::WCloudNormals(InputArray _cloud, InputArray _normals, int level, double scale, const Color &color) |
||||
{ |
||||
Mat cloud = _cloud.getMat(); |
||||
Mat normals = _normals.getMat(); |
||||
|
||||
CV_Assert(cloud.type() == CV_32FC3 || cloud.type() == CV_64FC3 || cloud.type() == CV_32FC4 || cloud.type() == CV_64FC4); |
||||
CV_Assert(cloud.size() == normals.size() && cloud.type() == normals.type()); |
||||
|
||||
int sqlevel = (int)std::sqrt((double)level); |
||||
int ystep = (cloud.cols > 1 && cloud.rows > 1) ? sqlevel : 1; |
||||
int xstep = (cloud.cols > 1 && cloud.rows > 1) ? sqlevel : level; |
||||
|
||||
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New(); |
||||
points->SetDataType(cloud.depth() == CV_32F ? VTK_FLOAT : VTK_DOUBLE); |
||||
|
||||
vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New(); |
||||
|
||||
int s_chs = cloud.channels(); |
||||
int n_chs = normals.channels(); |
||||
int total = 0; |
||||
|
||||
for(int y = 0; y < cloud.rows; y += ystep) |
||||
{ |
||||
if (cloud.depth() == CV_32F) |
||||
{ |
||||
const float *srow = cloud.ptr<float>(y); |
||||
const float *send = srow + cloud.cols * s_chs; |
||||
const float *nrow = normals.ptr<float>(y); |
||||
|
||||
for (; srow < send; srow += xstep * s_chs, nrow += xstep * n_chs) |
||||
if (!isNan(srow) && !isNan(nrow)) |
||||
{ |
||||
Vec3f endp = Vec3f(srow) + Vec3f(nrow) * (float)scale; |
||||
|
||||
points->InsertNextPoint(srow); |
||||
points->InsertNextPoint(endp.val); |
||||
|
||||
lines->InsertNextCell(2); |
||||
lines->InsertCellPoint(total++); |
||||
lines->InsertCellPoint(total++); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
const double *srow = cloud.ptr<double>(y); |
||||
const double *send = srow + cloud.cols * s_chs; |
||||
const double *nrow = normals.ptr<double>(y); |
||||
|
||||
for (; srow < send; srow += xstep * s_chs, nrow += xstep * n_chs) |
||||
if (!isNan(srow) && !isNan(nrow)) |
||||
{ |
||||
Vec3d endp = Vec3d(srow) + Vec3d(nrow) * (double)scale; |
||||
|
||||
points->InsertNextPoint(srow); |
||||
points->InsertNextPoint(endp.val); |
||||
|
||||
lines->InsertNextCell(2); |
||||
lines->InsertCellPoint(total++); |
||||
lines->InsertCellPoint(total++); |
||||
} |
||||
} |
||||
} |
||||
|
||||
vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New(); |
||||
polyData->SetPoints(points); |
||||
polyData->SetLines(lines); |
||||
|
||||
vtkSmartPointer<vtkDataSetMapper> mapper = vtkSmartPointer<vtkDataSetMapper>::New(); |
||||
mapper->SetColorModeToMapScalars(); |
||||
mapper->SetScalarModeToUsePointData(); |
||||
VtkUtils::SetInputData(mapper, polyData); |
||||
|
||||
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); |
||||
actor->SetMapper(mapper); |
||||
|
||||
WidgetAccessor::setProp(*this, actor); |
||||
setColor(color); |
||||
} |
||||
|
||||
template<> cv::viz::WCloudNormals cv::viz::Widget::cast<cv::viz::WCloudNormals>() |
||||
{ |
||||
Widget3D widget = this->cast<Widget3D>(); |
||||
return static_cast<WCloudNormals&>(widget); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Mesh Widget implementation
|
||||
|
||||
cv::viz::WMesh::WMesh(const Mesh &mesh) |
||||
{ |
||||
CV_Assert(mesh.cloud.rows == 1 && mesh.polygons.type() == CV_32SC1); |
||||
|
||||
vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New(); |
||||
source->SetColorCloudNormalsTCoords(mesh.cloud, mesh.colors, mesh.normals, mesh.tcoords); |
||||
source->Update(); |
||||
|
||||
Mat lookup_buffer(1, mesh.cloud.total(), CV_32SC1); |
||||
int *lookup = lookup_buffer.ptr<int>(); |
||||
for(int y = 0, index = 0; y < mesh.cloud.rows; ++y) |
||||
{ |
||||
int s_chs = mesh.cloud.channels(); |
||||
|
||||
if (mesh.cloud.depth() == CV_32F) |
||||
{ |
||||
const float* srow = mesh.cloud.ptr<float>(y); |
||||
const float* send = srow + mesh.cloud.cols * s_chs; |
||||
|
||||
for (; srow != send; srow += s_chs, ++lookup) |
||||
if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) |
||||
*lookup = index++; |
||||
} |
||||
|
||||
if (mesh.cloud.depth() == CV_64F) |
||||
{ |
||||
const double* srow = mesh.cloud.ptr<double>(y); |
||||
const double* send = srow + mesh.cloud.cols * s_chs; |
||||
|
||||
for (; srow != send; srow += s_chs, ++lookup) |
||||
if (!isNan(srow[0]) && !isNan(srow[1]) && !isNan(srow[2])) |
||||
*lookup = index++; |
||||
} |
||||
} |
||||
lookup = lookup_buffer.ptr<int>(); |
||||
|
||||
vtkSmartPointer<vtkPolyData> polydata = source->GetOutput(); |
||||
polydata->SetVerts(0); |
||||
|
||||
const int * polygons = mesh.polygons.ptr<int>(); |
||||
vtkSmartPointer<vtkCellArray> cell_array = vtkSmartPointer<vtkCellArray>::New(); |
||||
|
||||
int idx = 0; |
||||
size_t polygons_size = mesh.polygons.total(); |
||||
for (size_t i = 0; i < polygons_size; ++idx) |
||||
{ |
||||
int n_points = polygons[i++]; |
||||
|
||||
cell_array->InsertNextCell(n_points); |
||||
for (int j = 0; j < n_points; ++j, ++idx) |
||||
cell_array->InsertCellPoint(lookup[polygons[i++]]); |
||||
} |
||||
cell_array->GetData()->SetNumberOfValues(idx); |
||||
cell_array->Squeeze(); |
||||
polydata->SetStrips(cell_array); |
||||
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); |
||||
mapper->SetScalarModeToUsePointData(); |
||||
mapper->ImmediateModeRenderingOff(); |
||||
VtkUtils::SetInputData(mapper, polydata); |
||||
|
||||
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); |
||||
//actor->SetNumberOfCloudPoints(std::max(1, polydata->GetNumberOfPoints() / 10));
|
||||
actor->GetProperty()->SetRepresentationToSurface(); |
||||
actor->GetProperty()->BackfaceCullingOff(); // Backface culling is off for higher efficiency
|
||||
actor->GetProperty()->SetInterpolationToFlat(); |
||||
actor->GetProperty()->EdgeVisibilityOff(); |
||||
actor->GetProperty()->ShadingOff(); |
||||
actor->SetMapper(mapper); |
||||
|
||||
if (!mesh.texture.empty()) |
||||
{ |
||||
vtkSmartPointer<vtkImageMatSource> image_source = vtkSmartPointer<vtkImageMatSource>::New(); |
||||
image_source->SetImage(mesh.texture); |
||||
|
||||
vtkSmartPointer<vtkTexture> texture = vtkSmartPointer<vtkTexture>::New(); |
||||
texture->SetInputConnection(image_source->GetOutputPort()); |
||||
actor->SetTexture(texture); |
||||
} |
||||
|
||||
WidgetAccessor::setProp(*this, actor); |
||||
} |
||||
|
||||
cv::viz::WMesh::WMesh(InputArray cloud, InputArray polygons, InputArray colors, InputArray normals) |
||||
{ |
||||
Mesh mesh; |
||||
mesh.cloud = cloud.getMat(); |
||||
mesh.colors = colors.getMat(); |
||||
mesh.normals = normals.getMat(); |
||||
mesh.polygons = polygons.getMat(); |
||||
*this = WMesh(mesh); |
||||
} |
||||
|
||||
template<> CV_EXPORTS cv::viz::WMesh cv::viz::Widget::cast<cv::viz::WMesh>() |
||||
{ |
||||
Widget3D widget = this->cast<Widget3D>(); |
||||
return static_cast<WMesh&>(widget); |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,165 +0,0 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Ozan Tonkal, ozantonkal@gmail.com
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
// OpenCV Viz module is complete rewrite of
|
||||
// PCL visualization module (www.pointclouds.org)
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
cv::Affine3f cv::viz::makeTransformToGlobal(const Vec3f& axis_x, const Vec3f& axis_y, const Vec3f& axis_z, const Vec3f& origin) |
||||
{ |
||||
Affine3f::Mat3 R(axis_x[0], axis_y[0], axis_z[0], |
||||
axis_x[1], axis_y[1], axis_z[1], |
||||
axis_x[2], axis_y[2], axis_z[2]); |
||||
|
||||
return Affine3f(R, origin); |
||||
} |
||||
|
||||
cv::Affine3f cv::viz::makeCameraPose(const Vec3f& position, const Vec3f& focal_point, const Vec3f& y_dir) |
||||
{ |
||||
// Compute the transformation matrix for drawing the camera frame in a scene
|
||||
Vec3f n = normalize(focal_point - position); |
||||
Vec3f u = normalize(y_dir.cross(n)); |
||||
Vec3f v = n.cross(u); |
||||
|
||||
return makeTransformToGlobal(u, v, n, position); |
||||
} |
||||
|
||||
vtkSmartPointer<vtkMatrix4x4> cv::viz::convertToVtkMatrix(const cv::Matx44f &m) |
||||
{ |
||||
vtkSmartPointer<vtkMatrix4x4> vtk_matrix = vtkSmartPointer<vtkMatrix4x4>::New(); |
||||
for (int i = 0; i < 4; i++) |
||||
for (int k = 0; k < 4; k++) |
||||
vtk_matrix->SetElement(i, k, m(i, k)); |
||||
return vtk_matrix; |
||||
} |
||||
|
||||
cv::Matx44f cv::viz::convertToMatx(const vtkSmartPointer<vtkMatrix4x4>& vtk_matrix) |
||||
{ |
||||
cv::Matx44f m; |
||||
for (int i = 0; i < 4; i++) |
||||
for (int k = 0; k < 4; k++) |
||||
m(i, k) = vtk_matrix->GetElement(i, k); |
||||
return m; |
||||
} |
||||
|
||||
namespace cv { namespace viz |
||||
{ |
||||
template<typename _Tp> Vec<_Tp, 3>* vtkpoints_data(vtkSmartPointer<vtkPoints>& points); |
||||
|
||||
template<> Vec3f* vtkpoints_data<float>(vtkSmartPointer<vtkPoints>& points) |
||||
{ |
||||
CV_Assert(points->GetDataType() == VTK_FLOAT); |
||||
vtkDataArray *data = points->GetData(); |
||||
float *pointer = static_cast<vtkFloatArray*>(data)->GetPointer(0); |
||||
return reinterpret_cast<Vec3f*>(pointer); |
||||
} |
||||
|
||||
template<> Vec3d* vtkpoints_data<double>(vtkSmartPointer<vtkPoints>& points) |
||||
{ |
||||
CV_Assert(points->GetDataType() == VTK_DOUBLE); |
||||
vtkDataArray *data = points->GetData(); |
||||
double *pointer = static_cast<vtkDoubleArray*>(data)->GetPointer(0); |
||||
return reinterpret_cast<Vec3d*>(pointer); |
||||
} |
||||
}} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// VizStorage implementation
|
||||
|
||||
cv::viz::VizMap cv::viz::VizStorage::storage; |
||||
void cv::viz::VizStorage::unregisterAll() { storage.clear(); } |
||||
|
||||
cv::viz::Viz3d& cv::viz::VizStorage::get(const String &window_name) |
||||
{ |
||||
String name = generateWindowName(window_name); |
||||
VizMap::iterator vm_itr = storage.find(name); |
||||
CV_Assert(vm_itr != storage.end()); |
||||
return vm_itr->second; |
||||
} |
||||
|
||||
void cv::viz::VizStorage::add(const Viz3d& window) |
||||
{ |
||||
String window_name = window.getWindowName(); |
||||
VizMap::iterator vm_itr = storage.find(window_name); |
||||
CV_Assert(vm_itr == storage.end()); |
||||
storage.insert(std::make_pair(window_name, window)); |
||||
} |
||||
|
||||
bool cv::viz::VizStorage::windowExists(const String &window_name) |
||||
{ |
||||
String name = generateWindowName(window_name); |
||||
return storage.find(name) != storage.end(); |
||||
} |
||||
|
||||
void cv::viz::VizStorage::removeUnreferenced() |
||||
{ |
||||
for(VizMap::iterator pos = storage.begin(); pos != storage.end();) |
||||
if(pos->second.impl_->ref_counter == 1) |
||||
storage.erase(pos++); |
||||
else |
||||
++pos; |
||||
} |
||||
|
||||
cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) |
||||
{ |
||||
String output = "Viz"; |
||||
// Already is Viz
|
||||
if (window_name == output) |
||||
return output; |
||||
|
||||
String prefixed = output + " - "; |
||||
if (window_name.substr(0, prefixed.length()) == prefixed) |
||||
output = window_name; // Already has "Viz - "
|
||||
else if (window_name.substr(0, output.length()) == output) |
||||
output = prefixed + window_name; // Doesn't have prefix
|
||||
else |
||||
output = (window_name == "" ? output : prefixed + window_name); |
||||
|
||||
return output; |
||||
} |
||||
|
||||
cv::viz::Viz3d cv::viz::get(const String &window_name) { return Viz3d (window_name); } |
||||
void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } |
@ -1,368 +0,0 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Ozan Tonkal, ozantonkal@gmail.com
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
// OpenCV Viz module is complete rewrite of
|
||||
// PCL visualization module (www.pointclouds.org)
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_VIZ_VIZ3D_IMPL_HPP__ |
||||
#define __OPENCV_VIZ_VIZ3D_IMPL_HPP__ |
||||
|
||||
struct cv::viz::Viz3d::VizImpl |
||||
{ |
||||
public: |
||||
typedef Viz3d::KeyboardCallback KeyboardCallback; |
||||
typedef Viz3d::MouseCallback MouseCallback; |
||||
|
||||
int ref_counter; |
||||
|
||||
VizImpl(const String &name); |
||||
virtual ~VizImpl(); |
||||
|
||||
void showWidget(const String &id, const Widget &widget, const Affine3f &pose = Affine3f::Identity()); |
||||
void removeWidget(const String &id); |
||||
Widget getWidget(const String &id) const; |
||||
void removeAllWidgets(); |
||||
|
||||
void setWidgetPose(const String &id, const Affine3f &pose); |
||||
void updateWidgetPose(const String &id, const Affine3f &pose); |
||||
Affine3f getWidgetPose(const String &id) const; |
||||
|
||||
void setDesiredUpdateRate(double rate); |
||||
double getDesiredUpdateRate(); |
||||
|
||||
/** \brief Returns true when the user tried to close the window */ |
||||
bool wasStopped() const { if (interactor_ != NULL) return (stopped_); else return true; } |
||||
|
||||
/** \brief Set the stopped flag back to false */ |
||||
void resetStoppedFlag() { if (interactor_ != NULL) stopped_ = false; } |
||||
|
||||
/** \brief Stop the interaction and close the visualizaton window. */ |
||||
void close() |
||||
{ |
||||
stopped_ = true; |
||||
if (interactor_) |
||||
{ |
||||
interactor_->GetRenderWindow()->Finalize(); |
||||
interactor_->TerminateApp(); // This tends to close the window...
|
||||
} |
||||
} |
||||
|
||||
void setRepresentation(int representation); |
||||
|
||||
void setCamera(const Camera &camera); |
||||
Camera getCamera() const; |
||||
|
||||
/** \brief Reset the camera to a given widget */ |
||||
void resetCameraViewpoint(const String& id); |
||||
void resetCamera(); |
||||
|
||||
void setViewerPose(const Affine3f &pose); |
||||
Affine3f getViewerPose(); |
||||
|
||||
void convertToWindowCoordinates(const Point3d &pt, Point3d &window_coord); |
||||
void converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction); |
||||
|
||||
void saveScreenshot(const String &file); |
||||
void setWindowPosition(int x, int y); |
||||
Size getWindowSize() const; |
||||
void setWindowSize(int xw, int yw); |
||||
void setFullScreen(bool mode); |
||||
String getWindowName() const; |
||||
void setBackgroundColor(const Color& color); |
||||
|
||||
void spin(); |
||||
void spinOnce(int time = 1, bool force_redraw = false); |
||||
|
||||
void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0); |
||||
void registerMouseCallback(MouseCallback callback, void* cookie = 0); |
||||
|
||||
private: |
||||
vtkSmartPointer<vtkRenderWindowInteractor> interactor_; |
||||
|
||||
struct ExitMainLoopTimerCallback : public vtkCommand |
||||
{ |
||||
static ExitMainLoopTimerCallback* New() { return new ExitMainLoopTimerCallback; } |
||||
virtual void Execute(vtkObject* vtkNotUsed(caller), unsigned long event_id, void* call_data) |
||||
{ |
||||
if (event_id != vtkCommand::TimerEvent) |
||||
return; |
||||
|
||||
int timer_id = *reinterpret_cast<int*>(call_data); |
||||
if (timer_id != right_timer_id) |
||||
return; |
||||
|
||||
// Stop vtk loop and send notification to app to wake it up
|
||||
viz_->interactor_->TerminateApp(); |
||||
} |
||||
int right_timer_id; |
||||
VizImpl* viz_; |
||||
}; |
||||
|
||||
struct ExitCallback : public vtkCommand |
||||
{ |
||||
static ExitCallback* New() { return new ExitCallback; } |
||||
virtual void Execute(vtkObject*, unsigned long event_id, void*) |
||||
{ |
||||
if (event_id == vtkCommand::ExitEvent) |
||||
{ |
||||
viz_->stopped_ = true; |
||||
viz_->interactor_->GetRenderWindow()->Finalize(); |
||||
viz_->interactor_->TerminateApp(); |
||||
} |
||||
} |
||||
VizImpl* viz_; |
||||
}; |
||||
|
||||
/** \brief Set to false if the interaction loop is running. */ |
||||
bool stopped_; |
||||
|
||||
double s_lastDone_; |
||||
|
||||
/** \brief Global timer ID. Used in destructor only. */ |
||||
int timer_id_; |
||||
|
||||
/** \brief Callback object enabling us to leave the main loop, when a timer fires. */ |
||||
vtkSmartPointer<ExitMainLoopTimerCallback> exit_main_loop_timer_callback_; |
||||
vtkSmartPointer<ExitCallback> exit_callback_; |
||||
|
||||
vtkSmartPointer<vtkRenderer> renderer_; |
||||
vtkSmartPointer<vtkRenderWindow> window_; |
||||
|
||||
/** \brief The render window interactor style. */ |
||||
vtkSmartPointer<InteractorStyle> style_; |
||||
|
||||
/** \brief Internal list with actor pointers and name IDs for all widget actors */ |
||||
cv::Ptr<WidgetActorMap> widget_actor_map_; |
||||
|
||||
/** \brief Boolean that holds whether or not the camera parameters were manually initialized*/ |
||||
bool camera_set_; |
||||
|
||||
bool removeActorFromRenderer(const vtkSmartPointer<vtkProp> &actor); |
||||
}; |
||||
|
||||
|
||||
|
||||
namespace cv |
||||
{ |
||||
namespace viz |
||||
{ |
||||
vtkSmartPointer<vtkMatrix4x4> convertToVtkMatrix(const cv::Matx44f &m); |
||||
cv::Matx44f convertToMatx(const vtkSmartPointer<vtkMatrix4x4>& vtk_matrix); |
||||
|
||||
struct NanFilter |
||||
{ |
||||
template<typename _Tp, typename _Msk> |
||||
struct Impl |
||||
{ |
||||
typedef Vec<_Tp, 3> _Out; |
||||
|
||||
static _Out* copy(const Mat& source, _Out* output, const Mat& nan_mask) |
||||
{ |
||||
CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); |
||||
CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); |
||||
CV_DbgAssert(DataDepth<_Msk>::value == nan_mask.depth()); |
||||
|
||||
int s_chs = source.channels(); |
||||
int m_chs = nan_mask.channels(); |
||||
|
||||
for (int y = 0; y < source.rows; ++y) |
||||
{ |
||||
const _Tp* srow = source.ptr<_Tp>(y); |
||||
const _Msk* mrow = nan_mask.ptr<_Msk>(y); |
||||
|
||||
for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) |
||||
if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) |
||||
*output++ = _Out(srow); |
||||
} |
||||
return output; |
||||
} |
||||
|
||||
static _Out* copyColor(const Mat& source, _Out* output, const Mat& nan_mask) |
||||
{ |
||||
CV_Assert(DataDepth<_Tp>::value == source.depth() && source.size() == nan_mask.size()); |
||||
CV_Assert(nan_mask.channels() == 3 || nan_mask.channels() == 4); |
||||
CV_DbgAssert(DataDepth<_Msk>::value == nan_mask.depth()); |
||||
|
||||
int s_chs = source.channels(); |
||||
int m_chs = nan_mask.channels(); |
||||
|
||||
for (int y = 0; y < source.rows; ++y) |
||||
{ |
||||
const _Tp* srow = source.ptr<_Tp>(y); |
||||
const _Msk* mrow = nan_mask.ptr<_Msk>(y); |
||||
|
||||
for (int x = 0; x < source.cols; ++x, srow += s_chs, mrow += m_chs) |
||||
if (!isNan(mrow[0]) && !isNan(mrow[1]) && !isNan(mrow[2])) |
||||
{ |
||||
*output = _Out(srow); |
||||
std::swap((*output)[0], (*output)[2]); // BGR -> RGB
|
||||
++output; |
||||
} |
||||
} |
||||
return output; |
||||
} |
||||
}; |
||||
|
||||
template<typename _Tp> |
||||
static inline Vec<_Tp, 3>* copy(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) |
||||
{ |
||||
CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); |
||||
|
||||
typedef Vec<_Tp, 3>* (*copy_func)(const Mat&, Vec<_Tp, 3>*, const Mat&); |
||||
const static copy_func table[2] = { &NanFilter::Impl<_Tp, float>::copy, &NanFilter::Impl<_Tp, double>::copy }; |
||||
|
||||
return table[nan_mask.depth() - 5](source, output, nan_mask); |
||||
} |
||||
|
||||
template<typename _Tp> |
||||
static inline Vec<_Tp, 3>* copyColor(const Mat& source, Vec<_Tp, 3>* output, const Mat& nan_mask) |
||||
{ |
||||
CV_Assert(nan_mask.depth() == CV_32F || nan_mask.depth() == CV_64F); |
||||
|
||||
typedef Vec<_Tp, 3>* (*copy_func)(const Mat&, Vec<_Tp, 3>*, const Mat&); |
||||
const static copy_func table[2] = { &NanFilter::Impl<_Tp, float>::copyColor, &NanFilter::Impl<_Tp, double>::copyColor }; |
||||
|
||||
return table[nan_mask.depth() - 5](source, output, nan_mask); |
||||
} |
||||
}; |
||||
|
||||
struct ApplyAffine |
||||
{ |
||||
const Affine3f& affine_; |
||||
ApplyAffine(const Affine3f& affine) : affine_(affine) {} |
||||
|
||||
template<typename _Tp> Point3_<_Tp> operator()(const Point3_<_Tp>& p) const { return affine_ * p; } |
||||
|
||||
template<typename _Tp> Vec<_Tp, 3> operator()(const Vec<_Tp, 3>& v) const |
||||
{ |
||||
const float* m = affine_.matrix.val; |
||||
|
||||
Vec<_Tp, 3> result; |
||||
result[0] = (_Tp)(m[0] * v[0] + m[1] * v[1] + m[ 2] * v[2] + m[ 3]); |
||||
result[1] = (_Tp)(m[4] * v[0] + m[5] * v[1] + m[ 6] * v[2] + m[ 7]); |
||||
result[2] = (_Tp)(m[8] * v[0] + m[9] * v[1] + m[10] * v[2] + m[11]); |
||||
return result; |
||||
} |
||||
|
||||
private: |
||||
ApplyAffine(const ApplyAffine&); |
||||
ApplyAffine& operator=(const ApplyAffine&); |
||||
}; |
||||
|
||||
|
||||
inline Color vtkcolor(const Color& color) |
||||
{ |
||||
Color scaled_color = color * (1.0/255.0); |
||||
std::swap(scaled_color[0], scaled_color[2]); |
||||
return scaled_color; |
||||
} |
||||
|
||||
inline Vec3d vtkpoint(const Point3f& point) { return Vec3d(point.x, point.y, point.z); } |
||||
template<typename _Tp> inline _Tp normalized(const _Tp& v) { return v * 1/cv::norm(v); } |
||||
|
||||
struct ConvertToVtkImage |
||||
{ |
||||
struct Impl |
||||
{ |
||||
static void copyImageMultiChannel(const Mat &image, vtkSmartPointer<vtkImageData> output) |
||||
{ |
||||
int i_chs = image.channels(); |
||||
|
||||
for (int i = 0; i < image.rows; ++i) |
||||
{ |
||||
const unsigned char * irows = image.ptr<unsigned char>(i); |
||||
for (int j = 0; j < image.cols; ++j, irows += i_chs) |
||||
{ |
||||
unsigned char * vrows = static_cast<unsigned char *>(output->GetScalarPointer(j,i,0)); |
||||
memcpy(vrows, irows, i_chs); |
||||
std::swap(vrows[0], vrows[2]); // BGR -> RGB
|
||||
} |
||||
} |
||||
output->Modified(); |
||||
} |
||||
|
||||
static void copyImageSingleChannel(const Mat &image, vtkSmartPointer<vtkImageData> output) |
||||
{ |
||||
for (int i = 0; i < image.rows; ++i) |
||||
{ |
||||
const unsigned char * irows = image.ptr<unsigned char>(i); |
||||
for (int j = 0; j < image.cols; ++j, ++irows) |
||||
{ |
||||
unsigned char * vrows = static_cast<unsigned char *>(output->GetScalarPointer(j,i,0)); |
||||
*vrows = *irows; |
||||
} |
||||
} |
||||
output->Modified(); |
||||
} |
||||
}; |
||||
|
||||
static void convert(const Mat &image, vtkSmartPointer<vtkImageData> output) |
||||
{ |
||||
// Create the vtk image
|
||||
output->SetDimensions(image.cols, image.rows, 1); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
output->SetNumberOfScalarComponents(image.channels()); |
||||
output->SetScalarTypeToUnsignedChar(); |
||||
output->AllocateScalars(); |
||||
#else |
||||
output->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels()); |
||||
#endif |
||||
|
||||
int i_chs = image.channels(); |
||||
if (i_chs > 1) |
||||
{ |
||||
// Multi channel images are handled differently because of BGR <-> RGB
|
||||
Impl::copyImageMultiChannel(image, output); |
||||
} |
||||
else |
||||
{ |
||||
Impl::copyImageSingleChannel(image, output); |
||||
} |
||||
} |
||||
}; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,312 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Ozan Tonkal, ozantonkal@gmail.com
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
cv::Affine3d cv::viz::makeTransformToGlobal(const Vec3d& axis_x, const Vec3d& axis_y, const Vec3d& axis_z, const Vec3d& origin) |
||||
{ |
||||
Affine3d::Mat3 R(axis_x[0], axis_y[0], axis_z[0], |
||||
axis_x[1], axis_y[1], axis_z[1], |
||||
axis_x[2], axis_y[2], axis_z[2]); |
||||
|
||||
return Affine3d(R, origin); |
||||
} |
||||
|
||||
cv::Affine3d cv::viz::makeCameraPose(const Vec3d& position, const Vec3d& focal_point, const Vec3d& y_dir) |
||||
{ |
||||
// Compute the transformation matrix for drawing the camera frame in a scene
|
||||
Vec3d n = normalize(focal_point - position); |
||||
Vec3d u = normalize(y_dir.cross(n)); |
||||
Vec3d v = n.cross(u); |
||||
|
||||
return makeTransformToGlobal(u, v, n, position); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// VizStorage implementation
|
||||
|
||||
cv::viz::VizMap cv::viz::VizStorage::storage; |
||||
void cv::viz::VizStorage::unregisterAll() { storage.clear(); } |
||||
|
||||
cv::viz::Viz3d& cv::viz::VizStorage::get(const String &window_name) |
||||
{ |
||||
String name = generateWindowName(window_name); |
||||
VizMap::iterator vm_itr = storage.find(name); |
||||
CV_Assert(vm_itr != storage.end()); |
||||
return vm_itr->second; |
||||
} |
||||
|
||||
void cv::viz::VizStorage::add(const Viz3d& window) |
||||
{ |
||||
String window_name = window.getWindowName(); |
||||
VizMap::iterator vm_itr = storage.find(window_name); |
||||
CV_Assert(vm_itr == storage.end()); |
||||
storage.insert(std::make_pair(window_name, window)); |
||||
} |
||||
|
||||
bool cv::viz::VizStorage::windowExists(const String &window_name) |
||||
{ |
||||
String name = generateWindowName(window_name); |
||||
return storage.find(name) != storage.end(); |
||||
} |
||||
|
||||
void cv::viz::VizStorage::removeUnreferenced() |
||||
{ |
||||
for(VizMap::iterator pos = storage.begin(); pos != storage.end();) |
||||
if(pos->second.impl_->ref_counter == 1) |
||||
storage.erase(pos++); |
||||
else |
||||
++pos; |
||||
} |
||||
|
||||
cv::String cv::viz::VizStorage::generateWindowName(const String &window_name) |
||||
{ |
||||
String output = "Viz"; |
||||
// Already is Viz
|
||||
if (window_name == output) |
||||
return output; |
||||
|
||||
String prefixed = output + " - "; |
||||
if (window_name.substr(0, prefixed.length()) == prefixed) |
||||
output = window_name; // Already has "Viz - "
|
||||
else if (window_name.substr(0, output.length()) == output) |
||||
output = prefixed + window_name; // Doesn't have prefix
|
||||
else |
||||
output = (window_name == "" ? output : prefixed + window_name); |
||||
|
||||
return output; |
||||
} |
||||
|
||||
cv::viz::Viz3d cv::viz::getWindowByName(const String &window_name) { return Viz3d (window_name); } |
||||
void cv::viz::unregisterAllWindows() { VizStorage::unregisterAll(); } |
||||
|
||||
cv::viz::Viz3d cv::viz::imshow(const String& window_name, InputArray image, const Size& window_size) |
||||
{ |
||||
Viz3d viz = getWindowByName(window_name); |
||||
viz.showImage(image, window_size); |
||||
return viz; |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Read/write clouds. Supported formats: ply, stl, xyz, obj
|
||||
|
||||
void cv::viz::writeCloud(const String& file, InputArray cloud, InputArray colors, InputArray normals, bool binary) |
||||
{ |
||||
CV_Assert(file.size() > 4 && "Extention is required"); |
||||
String extention = file.substr(file.size()-4); |
||||
|
||||
vtkSmartPointer<vtkCloudMatSource> source = vtkSmartPointer<vtkCloudMatSource>::New(); |
||||
source->SetColorCloudNormals(cloud, colors, normals); |
||||
|
||||
vtkSmartPointer<vtkWriter> writer; |
||||
if (extention == ".xyz") |
||||
{ |
||||
writer = vtkSmartPointer<vtkXYZWriter>::New(); |
||||
vtkXYZWriter::SafeDownCast(writer)->SetFileName(file.c_str()); |
||||
} |
||||
else if (extention == ".ply") |
||||
{ |
||||
writer = vtkSmartPointer<vtkPLYWriter>::New(); |
||||
vtkPLYWriter::SafeDownCast(writer)->SetFileName(file.c_str()); |
||||
vtkPLYWriter::SafeDownCast(writer)->SetFileType(binary ? VTK_BINARY : VTK_ASCII); |
||||
vtkPLYWriter::SafeDownCast(writer)->SetArrayName("Colors"); |
||||
} |
||||
else if (extention == ".obj") |
||||
{ |
||||
writer = vtkSmartPointer<vtkOBJWriter>::New(); |
||||
vtkOBJWriter::SafeDownCast(writer)->SetFileName(file.c_str()); |
||||
} |
||||
else |
||||
CV_Assert(!"Unsupported format"); |
||||
|
||||
writer->SetInputConnection(source->GetOutputPort()); |
||||
writer->Write(); |
||||
} |
||||
|
||||
cv::Mat cv::viz::readCloud(const String& file, OutputArray colors, OutputArray normals) |
||||
{ |
||||
CV_Assert(file.size() > 4 && "Extention is required"); |
||||
String extention = file.substr(file.size()-4); |
||||
|
||||
vtkSmartPointer<vtkPolyDataAlgorithm> reader; |
||||
if (extention == ".xyz") |
||||
{ |
||||
reader = vtkSmartPointer<vtkSimplePointsReader>::New(); |
||||
vtkSimplePointsReader::SafeDownCast(reader)->SetFileName(file.c_str()); |
||||
} |
||||
else if (extention == ".ply") |
||||
{ |
||||
reader = vtkSmartPointer<vtkPLYReader>::New(); |
||||
CV_Assert(vtkPLYReader::CanReadFile(file.c_str())); |
||||
vtkPLYReader::SafeDownCast(reader)->SetFileName(file.c_str()); |
||||
} |
||||
else if (extention == ".obj") |
||||
{ |
||||
reader = vtkSmartPointer<vtkOBJReader>::New(); |
||||
vtkOBJReader::SafeDownCast(reader)->SetFileName(file.c_str()); |
||||
} |
||||
else if (extention == ".stl") |
||||
{ |
||||
reader = vtkSmartPointer<vtkSTLReader>::New(); |
||||
vtkSTLReader::SafeDownCast(reader)->SetFileName(file.c_str()); |
||||
} |
||||
else |
||||
CV_Assert(!"Unsupported format"); |
||||
|
||||
cv::Mat cloud; |
||||
|
||||
vtkSmartPointer<vtkCloudMatSink> sink = vtkSmartPointer<vtkCloudMatSink>::New(); |
||||
sink->SetInputConnection(reader->GetOutputPort()); |
||||
sink->SetOutput(cloud, colors, normals); |
||||
sink->Write(); |
||||
|
||||
return cloud; |
||||
} |
||||
|
||||
cv::viz::Mesh cv::viz::readMesh(const String& file) { return Mesh::load(file); } |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Read/write poses and trajectories
|
||||
|
||||
bool cv::viz::readPose(const String& file, Affine3d& pose, const String& tag) |
||||
{ |
||||
FileStorage fs(file, FileStorage::READ); |
||||
if (!fs.isOpened()) |
||||
return false; |
||||
|
||||
Mat hdr(pose.matrix, false); |
||||
fs[tag] >> hdr; |
||||
if (hdr.empty() || hdr.cols != pose.matrix.cols || hdr.rows != pose.matrix.rows) |
||||
return false; |
||||
|
||||
hdr.convertTo(pose.matrix, CV_64F); |
||||
return true; |
||||
} |
||||
|
||||
void cv::viz::writePose(const String& file, const Affine3d& pose, const String& tag) |
||||
{ |
||||
FileStorage fs(file, FileStorage::WRITE); |
||||
fs << tag << Mat(pose.matrix, false); |
||||
} |
||||
|
||||
void cv::viz::readTrajectory(OutputArray _traj, const String& files_format, int start, int end, const String& tag) |
||||
{ |
||||
CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); |
||||
|
||||
start = max(0, std::min(start, end)); |
||||
end = std::max(start, end); |
||||
|
||||
std::vector<Affine3d> traj; |
||||
|
||||
for(int i = start; i < end; ++i) |
||||
{ |
||||
Affine3d affine; |
||||
bool ok = readPose(cv::format(files_format.c_str(), i), affine, tag); |
||||
if (!ok) |
||||
break; |
||||
|
||||
traj.push_back(affine); |
||||
} |
||||
|
||||
Mat(traj).convertTo(_traj, _traj.depth()); |
||||
} |
||||
|
||||
void cv::viz::writeTrajectory(InputArray _traj, const String& files_format, int start, const String& tag) |
||||
{ |
||||
if (_traj.kind() == _InputArray::STD_VECTOR_MAT) |
||||
{ |
||||
std::vector<Mat>& v = *(std::vector<Mat>*)_traj.getObj(); |
||||
|
||||
for(size_t i = 0, index = max(0, start); i < v.size(); ++i, ++index) |
||||
{ |
||||
Affine3d affine; |
||||
Mat pose = v[i]; |
||||
CV_Assert(pose.type() == CV_32FC(16) || pose.type() == CV_64FC(16)); |
||||
pose.copyTo(affine.matrix); |
||||
writePose(cv::format(files_format.c_str(), index), affine, tag); |
||||
} |
||||
return; |
||||
} |
||||
|
||||
if (_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT) |
||||
{ |
||||
CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); |
||||
|
||||
Mat traj = _traj.getMat(); |
||||
|
||||
if (traj.depth() == CV_32F) |
||||
for(size_t i = 0, index = max(0, start); i < traj.total(); ++i, ++index) |
||||
writePose(cv::format(files_format.c_str(), index), traj.at<Affine3f>(i), tag); |
||||
|
||||
if (traj.depth() == CV_64F) |
||||
for(size_t i = 0, index = max(0, start); i < traj.total(); ++i, ++index) |
||||
writePose(cv::format(files_format.c_str(), index), traj.at<Affine3d>(i), tag); |
||||
} |
||||
|
||||
CV_Assert(!"Unsupported array kind"); |
||||
} |
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Computing normals for mesh
|
||||
|
||||
void cv::viz::computeNormals(const Mesh& mesh, OutputArray _normals) |
||||
{ |
||||
vtkSmartPointer<vtkPolyData> polydata = getPolyData(WMesh(mesh)); |
||||
vtkSmartPointer<vtkPolyData> with_normals = VtkUtils::ComputeNormals(polydata); |
||||
|
||||
vtkSmartPointer<vtkDataArray> generic_normals = with_normals->GetPointData()->GetNormals(); |
||||
if(generic_normals) |
||||
{ |
||||
Mat normals(1, generic_normals->GetNumberOfTuples(), CV_64FC3); |
||||
Vec3d *optr = normals.ptr<Vec3d>(); |
||||
|
||||
for(int i = 0; i < generic_normals->GetNumberOfTuples(); ++i, ++optr) |
||||
generic_normals->GetTuple(i, optr->val); |
||||
|
||||
normals.convertTo(_normals, mesh.cloud.type()); |
||||
} |
||||
else |
||||
_normals.release(); |
||||
} |
@ -0,0 +1,138 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Ozan Tonkal, ozantonkal@gmail.com
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __OPENCV_VIZ_VIZ3D_IMPL_HPP__ |
||||
#define __OPENCV_VIZ_VIZ3D_IMPL_HPP__ |
||||
|
||||
struct cv::viz::Viz3d::VizImpl |
||||
{ |
||||
public: |
||||
typedef Viz3d::KeyboardCallback KeyboardCallback; |
||||
typedef Viz3d::MouseCallback MouseCallback; |
||||
|
||||
int ref_counter; |
||||
|
||||
VizImpl(const String &name); |
||||
virtual ~VizImpl() {}; |
||||
|
||||
bool wasStopped() const; |
||||
void close(); |
||||
|
||||
void spin(); |
||||
void spinOnce(int time = 1, bool force_redraw = false); |
||||
|
||||
void showWidget(const String &id, const Widget &widget, const Affine3d &pose = Affine3d::Identity()); |
||||
void removeWidget(const String &id); |
||||
Widget getWidget(const String &id) const; |
||||
void removeAllWidgets(); |
||||
|
||||
void showImage(InputArray image, const Size& window_size); |
||||
|
||||
void setWidgetPose(const String &id, const Affine3d &pose); |
||||
void updateWidgetPose(const String &id, const Affine3d &pose); |
||||
Affine3d getWidgetPose(const String &id) const; |
||||
|
||||
void setRepresentation(int representation); |
||||
|
||||
void setCamera(const Camera &camera); |
||||
Camera getCamera() const; |
||||
|
||||
/** \brief Reset the camera to a given widget */ |
||||
void resetCameraViewpoint(const String& id); |
||||
void resetCamera(); |
||||
|
||||
void setViewerPose(const Affine3d &pose); |
||||
Affine3d getViewerPose(); |
||||
|
||||
void convertToWindowCoordinates(const Point3d &pt, Point3d &window_coord); |
||||
void converTo3DRay(const Point3d &window_coord, Point3d &origin, Vec3d &direction); |
||||
|
||||
void saveScreenshot(const String &file); |
||||
void setWindowPosition(const Point& position); |
||||
Size getWindowSize() const; |
||||
void setWindowSize(const Size& window_size); |
||||
void setFullScreen(bool mode); |
||||
String getWindowName() const; |
||||
void setBackgroundColor(const Color& color, const Color& color2); |
||||
void setBackgroundTexture(InputArray image); |
||||
void setBackgroundMeshLab(); |
||||
|
||||
void registerKeyboardCallback(KeyboardCallback callback, void* cookie = 0); |
||||
void registerMouseCallback(MouseCallback callback, void* cookie = 0); |
||||
|
||||
private: |
||||
struct TimerCallback : public vtkCommand |
||||
{ |
||||
static TimerCallback* New() { return new TimerCallback; } |
||||
virtual void Execute(vtkObject* caller, unsigned long event_id, void* cookie); |
||||
int timer_id; |
||||
}; |
||||
|
||||
struct ExitCallback : public vtkCommand |
||||
{ |
||||
static ExitCallback* New() { return new ExitCallback; } |
||||
virtual void Execute(vtkObject*, unsigned long event_id, void*); |
||||
VizImpl* viz; |
||||
}; |
||||
|
||||
mutable bool spin_once_state_; |
||||
vtkSmartPointer<vtkRenderWindowInteractor> interactor_; |
||||
|
||||
vtkSmartPointer<vtkRenderWindow> window_; |
||||
String window_name_; |
||||
Vec2i window_position_; |
||||
|
||||
vtkSmartPointer<TimerCallback> timer_callback_; |
||||
vtkSmartPointer<ExitCallback> exit_callback_; |
||||
|
||||
vtkSmartPointer<vtkRenderer> renderer_; |
||||
vtkSmartPointer<InteractorStyle> style_; |
||||
Ptr<WidgetActorMap> widget_actor_map_; |
||||
|
||||
bool removeActorFromRenderer(vtkSmartPointer<vtkProp> actor); |
||||
void recreateRenderWindow(); |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,158 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { namespace viz |
||||
{ |
||||
vtkStandardNewMacro(vtkCloudMatSink); |
||||
}} |
||||
|
||||
cv::viz::vtkCloudMatSink::vtkCloudMatSink() {} |
||||
cv::viz::vtkCloudMatSink::~vtkCloudMatSink() {} |
||||
|
||||
void cv::viz::vtkCloudMatSink::SetOutput(OutputArray _cloud, OutputArray _colors, OutputArray _normals, OutputArray _tcoords) |
||||
{ |
||||
cloud = _cloud; |
||||
colors = _colors; |
||||
normals = _normals; |
||||
tcoords = _tcoords; |
||||
} |
||||
|
||||
void cv::viz::vtkCloudMatSink::WriteData() |
||||
{ |
||||
vtkPolyData *input = this->GetInput(); |
||||
if (!input) |
||||
return; |
||||
|
||||
vtkSmartPointer<vtkPoints> points_Data = input->GetPoints(); |
||||
|
||||
if (cloud.needed() && points_Data) |
||||
{ |
||||
int vtktype = points_Data->GetDataType(); |
||||
CV_Assert(vtktype == VTK_FLOAT || vtktype == VTK_DOUBLE); |
||||
|
||||
cloud.create(1, points_Data->GetNumberOfPoints(), vtktype == VTK_FLOAT ? CV_32FC3 : CV_64FC3); |
||||
Vec3d *ddata = cloud.getMat().ptr<Vec3d>(); |
||||
Vec3f *fdata = cloud.getMat().ptr<Vec3f>(); |
||||
|
||||
if (cloud.depth() == CV_32F) |
||||
for(size_t i = 0; i < cloud.total(); ++i) |
||||
*fdata++ = Vec3d(points_Data->GetPoint(i)); |
||||
|
||||
if (cloud.depth() == CV_64F) |
||||
for(size_t i = 0; i < cloud.total(); ++i) |
||||
*ddata++ = Vec3d(points_Data->GetPoint(i)); |
||||
} |
||||
else |
||||
cloud.release(); |
||||
|
||||
vtkSmartPointer<vtkDataArray> scalars_data = input->GetPointData() ? input->GetPointData()->GetScalars() : 0; |
||||
|
||||
if (colors.needed() && scalars_data) |
||||
{ |
||||
int channels = scalars_data->GetNumberOfComponents(); |
||||
int vtktype = scalars_data->GetDataType(); |
||||
|
||||
CV_Assert((channels == 3 || channels == 4) && "Only 3- or 4-channel color data support is implemented"); |
||||
CV_Assert(cloud.total() == (size_t)scalars_data->GetNumberOfTuples()); |
||||
|
||||
Mat buffer(cloud.size(), CV_64FC(channels)); |
||||
Vec3d *cptr = buffer.ptr<Vec3d>(); |
||||
for(size_t i = 0; i < buffer.total(); ++i) |
||||
*cptr++ = Vec3d(scalars_data->GetTuple(i)); |
||||
|
||||
buffer.convertTo(colors, CV_8U, vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE ? 255.0 : 1.0); |
||||
} |
||||
else |
||||
colors.release(); |
||||
|
||||
vtkSmartPointer<vtkDataArray> normals_data = input->GetPointData() ? input->GetPointData()->GetNormals() : 0; |
||||
|
||||
if (normals.needed() && normals_data) |
||||
{ |
||||
int channels = normals_data->GetNumberOfComponents(); |
||||
int vtktype = normals_data->GetDataType(); |
||||
|
||||
CV_Assert((vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE) && (channels == 3 || channels == 4)); |
||||
CV_Assert(cloud.total() == (size_t)normals_data->GetNumberOfTuples()); |
||||
|
||||
Mat buffer(cloud.size(), CV_64FC(channels)); |
||||
Vec3d *cptr = buffer.ptr<Vec3d>(); |
||||
for(size_t i = 0; i < buffer.total(); ++i) |
||||
*cptr++ = Vec3d(normals_data->GetTuple(i)); |
||||
|
||||
buffer.convertTo(normals, vtktype == VTK_FLOAT ? CV_32F : CV_64F); |
||||
} |
||||
else |
||||
normals.release(); |
||||
|
||||
vtkSmartPointer<vtkDataArray> coords_data = input->GetPointData() ? input->GetPointData()->GetTCoords() : 0; |
||||
|
||||
if (tcoords.needed() && coords_data) |
||||
{ |
||||
int vtktype = coords_data->GetDataType(); |
||||
|
||||
CV_Assert(vtktype == VTK_FLOAT || VTK_FLOAT == VTK_DOUBLE); |
||||
CV_Assert(cloud.total() == (size_t)coords_data->GetNumberOfTuples()); |
||||
|
||||
Mat buffer(cloud.size(), CV_64FC2); |
||||
Vec2d *cptr = buffer.ptr<Vec2d>(); |
||||
for(size_t i = 0; i < buffer.total(); ++i) |
||||
*cptr++ = Vec2d(coords_data->GetTuple(i)); |
||||
|
||||
buffer.convertTo(tcoords, vtktype == VTK_FLOAT ? CV_32F : CV_64F); |
||||
|
||||
} |
||||
else |
||||
tcoords.release(); |
||||
} |
||||
|
||||
void cv::viz::vtkCloudMatSink::PrintSelf(ostream& os, vtkIndent indent) |
||||
{ |
||||
Superclass::PrintSelf(os, indent); |
||||
os << indent << "Cloud: " << cloud.needed() << "\n"; |
||||
os << indent << "Colors: " << colors.needed() << "\n"; |
||||
os << indent << "Normals: " << normals.needed() << "\n"; |
||||
} |
@ -0,0 +1,79 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __vtkCloudMatSink_h |
||||
#define __vtkCloudMatSink_h |
||||
|
||||
#include <opencv2/core.hpp> |
||||
#include <vtkPolyDataWriter.h> |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace viz |
||||
{ |
||||
class vtkCloudMatSink : public vtkPolyDataWriter |
||||
{ |
||||
public: |
||||
static vtkCloudMatSink *New(); |
||||
vtkTypeMacro(vtkCloudMatSink,vtkPolyDataWriter) |
||||
void PrintSelf(ostream& os, vtkIndent indent); |
||||
|
||||
void SetOutput(OutputArray cloud, OutputArray colors = noArray(), OutputArray normals = noArray(), OutputArray tcoords = noArray()); |
||||
|
||||
protected: |
||||
vtkCloudMatSink(); |
||||
~vtkCloudMatSink(); |
||||
|
||||
void WriteData(); |
||||
|
||||
_OutputArray cloud, colors, normals, tcoords; |
||||
|
||||
private: |
||||
vtkCloudMatSink(const vtkCloudMatSink&); // Not implemented.
|
||||
void operator=(const vtkCloudMatSink&); // Not implemented.
|
||||
}; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,286 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { namespace viz |
||||
{ |
||||
vtkStandardNewMacro(vtkCloudMatSource); |
||||
|
||||
template<typename _Tp> struct VtkDepthTraits; |
||||
|
||||
template<> struct VtkDepthTraits<float> |
||||
{ |
||||
const static int data_type = VTK_FLOAT; |
||||
typedef vtkFloatArray array_type; |
||||
}; |
||||
|
||||
template<> struct VtkDepthTraits<double> |
||||
{ |
||||
const static int data_type = VTK_DOUBLE; |
||||
typedef vtkDoubleArray array_type; |
||||
}; |
||||
}} |
||||
|
||||
cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); } |
||||
cv::viz::vtkCloudMatSource::~vtkCloudMatSource() {} |
||||
|
||||
int cv::viz::vtkCloudMatSource::SetCloud(InputArray _cloud) |
||||
{ |
||||
CV_Assert(_cloud.depth() == CV_32F || _cloud.depth() == CV_64F); |
||||
CV_Assert(_cloud.channels() == 3 || _cloud.channels() == 4); |
||||
|
||||
Mat cloud = _cloud.getMat(); |
||||
|
||||
int total = _cloud.depth() == CV_32F ? filterNanCopy<float>(cloud) : filterNanCopy<double>(cloud); |
||||
|
||||
vertices = vtkSmartPointer<vtkCellArray>::New(); |
||||
vertices->Allocate(vertices->EstimateSize(1, total)); |
||||
vertices->InsertNextCell(total); |
||||
for(int i = 0; i < total; ++i) |
||||
vertices->InsertCellPoint(i); |
||||
|
||||
return total; |
||||
} |
||||
|
||||
int cv::viz::vtkCloudMatSource::SetColorCloud(InputArray _cloud, InputArray _colors) |
||||
{ |
||||
int total = SetCloud(_cloud); |
||||
|
||||
if (_colors.empty()) |
||||
return total; |
||||
|
||||
CV_Assert(_colors.depth() == CV_8U && _colors.channels() <= 4 && _colors.channels() != 2); |
||||
CV_Assert(_colors.size() == _cloud.size()); |
||||
|
||||
Mat cloud = _cloud.getMat(); |
||||
Mat colors = _colors.getMat(); |
||||
|
||||
if (cloud.depth() == CV_32F) |
||||
filterNanColorsCopy<float>(colors, cloud, total); |
||||
else if (cloud.depth() == CV_64F) |
||||
filterNanColorsCopy<double>(colors, cloud, total); |
||||
|
||||
return total; |
||||
} |
||||
|
||||
int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArray _colors, InputArray _normals) |
||||
{ |
||||
int total = SetColorCloud(_cloud, _colors); |
||||
|
||||
if (_normals.empty()) |
||||
return total; |
||||
|
||||
CV_Assert(_normals.depth() == CV_32F || _normals.depth() == CV_64F); |
||||
CV_Assert(_normals.channels() == 3 || _normals.channels() == 4); |
||||
CV_Assert(_normals.size() == _cloud.size()); |
||||
|
||||
Mat c = _cloud.getMat(); |
||||
Mat n = _normals.getMat(); |
||||
|
||||
if (n.depth() == CV_32F && c.depth() == CV_32F) |
||||
filterNanNormalsCopy<float, float>(n, c, total); |
||||
else if (n.depth() == CV_32F && c.depth() == CV_64F) |
||||
filterNanNormalsCopy<float, double>(n, c, total); |
||||
else if (n.depth() == CV_64F && c.depth() == CV_32F) |
||||
filterNanNormalsCopy<double, float>(n, c, total); |
||||
else if (n.depth() == CV_64F && c.depth() == CV_64F) |
||||
filterNanNormalsCopy<double, double>(n, c, total); |
||||
else |
||||
CV_Assert(!"Unsupported normals/cloud type"); |
||||
|
||||
return total; |
||||
} |
||||
|
||||
int cv::viz::vtkCloudMatSource::SetColorCloudNormalsTCoords(InputArray _cloud, InputArray _colors, InputArray _normals, InputArray _tcoords) |
||||
{ |
||||
int total = SetColorCloudNormals(_cloud, _colors, _normals); |
||||
|
||||
if (_tcoords.empty()) |
||||
return total; |
||||
|
||||
CV_Assert(_tcoords.depth() == CV_32F || _tcoords.depth() == CV_64F); |
||||
CV_Assert(_tcoords.channels() == 2 && _tcoords.size() == _cloud.size()); |
||||
|
||||
Mat cl = _cloud.getMat(); |
||||
Mat tc = _tcoords.getMat(); |
||||
|
||||
if (tc.depth() == CV_32F && cl.depth() == CV_32F) |
||||
filterNanTCoordsCopy<float, float>(tc, cl, total); |
||||
else if (tc.depth() == CV_32F && cl.depth() == CV_64F) |
||||
filterNanTCoordsCopy<float, double>(tc, cl, total); |
||||
else if (tc.depth() == CV_64F && cl.depth() == CV_32F) |
||||
filterNanTCoordsCopy<double, float>(tc, cl, total); |
||||
else if (tc.depth() == CV_64F && cl.depth() == CV_64F) |
||||
filterNanTCoordsCopy<double, double>(tc, cl, total); |
||||
else |
||||
CV_Assert(!"Unsupported tcoords/cloud type"); |
||||
|
||||
return total; |
||||
} |
||||
|
||||
int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) |
||||
{ |
||||
vtkInformation *outInfo = outputVector->GetInformationObject(0); |
||||
vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); |
||||
|
||||
output->SetPoints(points); |
||||
output->SetVerts(vertices); |
||||
if (scalars) |
||||
output->GetPointData()->SetScalars(scalars); |
||||
|
||||
if (normals) |
||||
output->GetPointData()->SetNormals(normals); |
||||
|
||||
if (tcoords) |
||||
output->GetPointData()->SetTCoords(tcoords); |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
template<typename _Tp> |
||||
int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& cloud) |
||||
{ |
||||
CV_DbgAssert(DataType<_Tp>::depth == cloud.depth()); |
||||
points = vtkSmartPointer<vtkPoints>::New(); |
||||
points->SetDataType(VtkDepthTraits<_Tp>::data_type); |
||||
points->Allocate(cloud.total()); |
||||
points->SetNumberOfPoints(cloud.total()); |
||||
|
||||
int s_chs = cloud.channels(); |
||||
int total = 0; |
||||
for (int y = 0; y < cloud.rows; ++y) |
||||
{ |
||||
const _Tp* srow = cloud.ptr<_Tp>(y); |
||||
const _Tp* send = srow + cloud.cols * s_chs; |
||||
|
||||
for (; srow != send; srow += s_chs) |
||||
if (!isNan(srow)) |
||||
points->SetPoint(total++, srow); |
||||
} |
||||
points->SetNumberOfPoints(total); |
||||
points->Squeeze(); |
||||
return total; |
||||
} |
||||
|
||||
template<typename _Msk> |
||||
void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, const Mat& mask, int total) |
||||
{ |
||||
Vec3b* array = new Vec3b[total]; |
||||
Vec3b* pos = array; |
||||
|
||||
int s_chs = cloud_colors.channels(); |
||||
int m_chs = mask.channels(); |
||||
for (int y = 0; y < cloud_colors.rows; ++y) |
||||
{ |
||||
const unsigned char* srow = cloud_colors.ptr<unsigned char>(y); |
||||
const unsigned char* send = srow + cloud_colors.cols * s_chs; |
||||
const _Msk* mrow = mask.ptr<_Msk>(y); |
||||
|
||||
if (cloud_colors.channels() == 1) |
||||
{ |
||||
for (; srow != send; srow += s_chs, mrow += m_chs) |
||||
if (!isNan(mrow)) |
||||
*pos++ = Vec3b(srow[0], srow[0], srow[0]); |
||||
} |
||||
else |
||||
for (; srow != send; srow += s_chs, mrow += m_chs) |
||||
if (!isNan(mrow)) |
||||
*pos++ = Vec3b(srow[2], srow[1], srow[0]); |
||||
|
||||
} |
||||
|
||||
scalars = vtkSmartPointer<vtkUnsignedCharArray>::New(); |
||||
scalars->SetName("Colors"); |
||||
scalars->SetNumberOfComponents(3); |
||||
scalars->SetNumberOfTuples(total); |
||||
scalars->SetArray(array->val, total * 3, 0); |
||||
} |
||||
|
||||
template<typename _Tn, typename _Msk> |
||||
void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total) |
||||
{ |
||||
normals = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New(); |
||||
normals->SetName("Normals"); |
||||
normals->SetNumberOfComponents(3); |
||||
normals->SetNumberOfTuples(total); |
||||
|
||||
int s_chs = cloud_normals.channels(); |
||||
int m_chs = mask.channels(); |
||||
|
||||
int pos = 0; |
||||
for (int y = 0; y < cloud_normals.rows; ++y) |
||||
{ |
||||
const _Tn* srow = cloud_normals.ptr<_Tn>(y); |
||||
const _Tn* send = srow + cloud_normals.cols * s_chs; |
||||
|
||||
const _Msk* mrow = mask.ptr<_Msk>(y); |
||||
|
||||
for (; srow != send; srow += s_chs, mrow += m_chs) |
||||
if (!isNan(mrow)) |
||||
normals->SetTuple(pos++, srow); |
||||
} |
||||
} |
||||
|
||||
template<typename _Tn, typename _Msk> |
||||
void cv::viz::vtkCloudMatSource::filterNanTCoordsCopy(const Mat& _tcoords, const Mat& mask, int total) |
||||
{ |
||||
typedef Vec<_Tn, 2> Vec2; |
||||
tcoords = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New(); |
||||
tcoords->SetName("TextureCoordinates"); |
||||
tcoords->SetNumberOfComponents(2); |
||||
tcoords->SetNumberOfTuples(total); |
||||
|
||||
int pos = 0; |
||||
for (int y = 0; y < mask.rows; ++y) |
||||
{ |
||||
const Vec2* srow = _tcoords.ptr<Vec2>(y); |
||||
const Vec2* send = srow + _tcoords.cols; |
||||
const _Msk* mrow = mask.ptr<_Msk>(y); |
||||
|
||||
for (; srow != send; ++srow, mrow += mask.channels()) |
||||
if (!isNan(mrow)) |
||||
tcoords->SetTuple(pos++, srow->val); |
||||
} |
||||
} |
@ -0,0 +1,96 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __vtkCloudMatSource_h |
||||
#define __vtkCloudMatSource_h |
||||
|
||||
#include <opencv2/core.hpp> |
||||
#include <vtkPolyDataAlgorithm.h> |
||||
#include <vtkSmartPointer.h> |
||||
#include <vtkPoints.h> |
||||
#include <vtkCellArray.h> |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace viz |
||||
{ |
||||
class vtkCloudMatSource : public vtkPolyDataAlgorithm |
||||
{ |
||||
public: |
||||
static vtkCloudMatSource *New(); |
||||
vtkTypeMacro(vtkCloudMatSource,vtkPolyDataAlgorithm) |
||||
|
||||
virtual int SetCloud(InputArray cloud); |
||||
virtual int SetColorCloud(InputArray cloud, InputArray colors); |
||||
virtual int SetColorCloudNormals(InputArray cloud, InputArray colors, InputArray normals); |
||||
virtual int SetColorCloudNormalsTCoords(InputArray cloud, InputArray colors, InputArray normals, InputArray tcoords); |
||||
|
||||
protected: |
||||
vtkCloudMatSource(); |
||||
~vtkCloudMatSource(); |
||||
|
||||
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); |
||||
|
||||
vtkSmartPointer<vtkPoints> points; |
||||
vtkSmartPointer<vtkCellArray> vertices; |
||||
vtkSmartPointer<vtkUnsignedCharArray> scalars; |
||||
vtkSmartPointer<vtkDataArray> normals; |
||||
vtkSmartPointer<vtkDataArray> tcoords; |
||||
private: |
||||
vtkCloudMatSource(const vtkCloudMatSource&); // Not implemented.
|
||||
void operator=(const vtkCloudMatSource&); // Not implemented.
|
||||
|
||||
template<typename _Tp> int filterNanCopy(const Mat& cloud); |
||||
template<typename _Msk> void filterNanColorsCopy(const Mat& cloud_colors, const Mat& mask, int total); |
||||
|
||||
template<typename _Tn, typename _Msk> |
||||
void filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total); |
||||
|
||||
template<typename _Tn, typename _Msk> |
||||
void filterNanTCoordsCopy(const Mat& tcoords, const Mat& mask, int total); |
||||
}; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,143 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { namespace viz |
||||
{ |
||||
vtkStandardNewMacro(vtkImageMatSource); |
||||
}} |
||||
|
||||
cv::viz::vtkImageMatSource::vtkImageMatSource() |
||||
{ |
||||
this->SetNumberOfInputPorts(0); |
||||
this->ImageData = vtkImageData::New(); |
||||
} |
||||
|
||||
int cv::viz::vtkImageMatSource::RequestInformation(vtkInformation *, vtkInformationVector**, vtkInformationVector *outputVector) |
||||
{ |
||||
vtkInformation* outInfo = outputVector->GetInformationObject(0); |
||||
|
||||
outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->ImageData->GetExtent(), 6); |
||||
outInfo->Set(vtkDataObject::SPACING(), 1.0, 1.0, 1.0); |
||||
outInfo->Set(vtkDataObject::ORIGIN(), 0.0, 0.0, 0.0); |
||||
|
||||
vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->ImageData->GetScalarType(), this->ImageData->GetNumberOfScalarComponents()); |
||||
return 1; |
||||
} |
||||
|
||||
int cv::viz::vtkImageMatSource::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector *outputVector) |
||||
{ |
||||
vtkInformation *outInfo = outputVector->GetInformationObject(0); |
||||
|
||||
vtkImageData *output = vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()) ); |
||||
output->ShallowCopy(this->ImageData); |
||||
return 1; |
||||
} |
||||
|
||||
void cv::viz::vtkImageMatSource::SetImage(InputArray _image) |
||||
{ |
||||
CV_Assert(_image.depth() == CV_8U && (_image.channels() == 1 || _image.channels() == 3 || _image.channels() == 4)); |
||||
|
||||
Mat image = _image.getMat(); |
||||
|
||||
this->ImageData->SetDimensions(image.cols, image.rows, 1); |
||||
#if VTK_MAJOR_VERSION <= 5 |
||||
this->ImageData->SetNumberOfScalarComponents(image.channels()); |
||||
this->ImageData->SetScalarTypeToUnsignedChar(); |
||||
this->ImageData->AllocateScalars(); |
||||
#else |
||||
this->ImageData->AllocateScalars(VTK_UNSIGNED_CHAR, image.channels()); |
||||
#endif |
||||
|
||||
switch(image.channels()) |
||||
{ |
||||
case 1: copyGrayImage(image, this->ImageData); break; |
||||
case 3: copyRGBImage (image, this->ImageData); break; |
||||
case 4: copyRGBAImage(image, this->ImageData); break; |
||||
} |
||||
this->ImageData->Modified(); |
||||
} |
||||
|
||||
void cv::viz::vtkImageMatSource::copyGrayImage(const Mat &source, vtkSmartPointer<vtkImageData> output) |
||||
{ |
||||
unsigned char* dptr = reinterpret_cast<unsigned char*>(output->GetScalarPointer()); |
||||
size_t elem_step = output->GetIncrements()[1]/sizeof(unsigned char); |
||||
|
||||
for (int y = 0; y < source.rows; ++y) |
||||
{ |
||||
unsigned char* drow = dptr + elem_step * y; |
||||
const unsigned char *srow = source.ptr<unsigned char>(y); |
||||
for (int x = 0; x < source.cols; ++x) |
||||
drow[x] = *srow++; |
||||
} |
||||
} |
||||
|
||||
void cv::viz::vtkImageMatSource::copyRGBImage(const Mat &source, vtkSmartPointer<vtkImageData> output) |
||||
{ |
||||
Vec3b* dptr = reinterpret_cast<Vec3b*>(output->GetScalarPointer()); |
||||
size_t elem_step = output->GetIncrements()[1]/sizeof(Vec3b); |
||||
|
||||
for (int y = 0; y < source.rows; ++y) |
||||
{ |
||||
Vec3b* drow = dptr + elem_step * y; |
||||
const unsigned char *srow = source.ptr<unsigned char>(y); |
||||
for (int x = 0; x < source.cols; ++x, srow += source.channels()) |
||||
drow[x] = Vec3b(srow[2], srow[1], srow[0]); |
||||
} |
||||
} |
||||
|
||||
void cv::viz::vtkImageMatSource::copyRGBAImage(const Mat &source, vtkSmartPointer<vtkImageData> output) |
||||
{ |
||||
Vec4b* dptr = reinterpret_cast<Vec4b*>(output->GetScalarPointer()); |
||||
size_t elem_step = output->GetIncrements()[1]/sizeof(Vec4b); |
||||
|
||||
for (int y = 0; y < source.rows; ++y) |
||||
{ |
||||
Vec4b* drow = dptr + elem_step * y; |
||||
const unsigned char *srow = source.ptr<unsigned char>(y); |
||||
for (int x = 0; x < source.cols; ++x, srow += source.channels()) |
||||
drow[x] = Vec4b(srow[2], srow[1], srow[0], srow[3]); |
||||
} |
||||
} |
@ -0,0 +1,82 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
#ifndef __vtkImageMatSource_h |
||||
#define __vtkImageMatSource_h |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace viz |
||||
{ |
||||
class vtkImageMatSource : public vtkImageAlgorithm |
||||
{ |
||||
public: |
||||
static vtkImageMatSource *New(); |
||||
vtkTypeMacro(vtkImageMatSource,vtkImageAlgorithm); |
||||
|
||||
void SetImage(InputArray image); |
||||
|
||||
protected: |
||||
vtkImageMatSource(); |
||||
~vtkImageMatSource() {} |
||||
|
||||
vtkSmartPointer<vtkImageData> ImageData; |
||||
|
||||
int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*); |
||||
int RequestData (vtkInformation*, vtkInformationVector**, vtkInformationVector*); |
||||
private: |
||||
vtkImageMatSource(const vtkImageMatSource&); // Not implemented.
|
||||
void operator=(const vtkImageMatSource&); // Not implemented.
|
||||
|
||||
static void copyGrayImage(const Mat &source, vtkSmartPointer<vtkImageData> output); |
||||
static void copyRGBImage (const Mat &source, vtkSmartPointer<vtkImageData> output); |
||||
static void copyRGBAImage(const Mat &source, vtkSmartPointer<vtkImageData> output); |
||||
}; |
||||
} |
||||
} |
||||
|
||||
|
||||
#endif |
@ -0,0 +1,241 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { namespace viz |
||||
{ |
||||
vtkStandardNewMacro(vtkOBJWriter); |
||||
}} |
||||
|
||||
cv::viz::vtkOBJWriter::vtkOBJWriter() |
||||
{ |
||||
std::ofstream fout; // only used to extract the default precision
|
||||
this->DecimalPrecision = fout.precision(); |
||||
this->FileName = NULL; |
||||
this->FileType = VTK_ASCII; |
||||
} |
||||
|
||||
cv::viz::vtkOBJWriter::~vtkOBJWriter(){} |
||||
|
||||
void cv::viz::vtkOBJWriter::WriteData() |
||||
{ |
||||
vtkPolyData *input = this->GetInput(); |
||||
if (!input) |
||||
return; |
||||
|
||||
std::ostream *outfilep = this->OpenVTKFile(); |
||||
if (!outfilep) |
||||
return; |
||||
|
||||
std::ostream& outfile = *outfilep; |
||||
|
||||
//write header
|
||||
outfile << "# wavefront obj file written by the visualization toolkit" << std::endl << std::endl; |
||||
outfile << "mtllib NONE" << std::endl << std::endl; |
||||
|
||||
// write out the points
|
||||
for (int i = 0; i < input->GetNumberOfPoints(); i++) |
||||
{ |
||||
Vec3d p; |
||||
input->GetPoint(i, p.val); |
||||
outfile << std::setprecision(this->DecimalPrecision) << "v " << p[0] << " " << p[1] << " " << p[2] << std::endl; |
||||
} |
||||
|
||||
const int idStart = 1; |
||||
|
||||
// write out the point data
|
||||
vtkSmartPointer<vtkDataArray> normals = input->GetPointData()->GetNormals(); |
||||
if(normals) |
||||
{ |
||||
for (int i = 0; i < normals->GetNumberOfTuples(); i++) |
||||
{ |
||||
Vec3d p; |
||||
normals->GetTuple(i, p.val); |
||||
outfile << std::setprecision(this->DecimalPrecision) << "vn " << p[0] << " " << p[1] << " " << p[2] << std::endl; |
||||
} |
||||
} |
||||
|
||||
vtkSmartPointer<vtkDataArray> tcoords = input->GetPointData()->GetTCoords(); |
||||
if (tcoords) |
||||
{ |
||||
for (int i = 0; i < tcoords->GetNumberOfTuples(); i++) |
||||
{ |
||||
Vec2d p; |
||||
tcoords->GetTuple(i, p.val); |
||||
outfile << std::setprecision(this->DecimalPrecision) << "vt " << p[0] << " " << p[1] << std::endl; |
||||
} |
||||
} |
||||
|
||||
// write out a group name and material
|
||||
outfile << std::endl << "g grp" << idStart << std::endl; |
||||
outfile << "usemtl mtlNONE" << std::endl; |
||||
|
||||
// write out verts if any
|
||||
if (input->GetNumberOfVerts() > 0) |
||||
{ |
||||
vtkIdType npts = 0, *index = 0; |
||||
vtkCellArray *cells = input->GetVerts(); |
||||
for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) |
||||
{ |
||||
outfile << "p "; |
||||
for (int i = 0; i < npts; i++) |
||||
outfile << index[i] + idStart << " "; |
||||
outfile << std::endl; |
||||
} |
||||
} |
||||
|
||||
// write out lines if any
|
||||
if (input->GetNumberOfLines() > 0) |
||||
{ |
||||
vtkIdType npts = 0, *index = 0; |
||||
vtkCellArray *cells = input->GetLines(); |
||||
for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) |
||||
{ |
||||
outfile << "l "; |
||||
if (tcoords) |
||||
{ |
||||
for (int i = 0; i < npts; i++) |
||||
outfile << index[i] + idStart << "/" << index[i] + idStart << " "; |
||||
} |
||||
else |
||||
for (int i = 0; i < npts; i++) |
||||
outfile << index[i] + idStart << " "; |
||||
|
||||
outfile << std::endl; |
||||
} |
||||
} |
||||
|
||||
// write out polys if any
|
||||
if (input->GetNumberOfPolys() > 0) |
||||
{ |
||||
vtkIdType npts = 0, *index = 0; |
||||
vtkCellArray *cells = input->GetPolys(); |
||||
for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) |
||||
{ |
||||
outfile << "f "; |
||||
for (int i = 0; i < npts; i++) |
||||
{ |
||||
if (normals) |
||||
{ |
||||
if (tcoords) |
||||
outfile << index[i] + idStart << "/" << index[i] + idStart << "/" << index[i] + idStart << " "; |
||||
else |
||||
outfile << index[i] + idStart << "//" << index[i] + idStart << " "; |
||||
} |
||||
else |
||||
{ |
||||
if (tcoords) |
||||
outfile << index[i] + idStart << " " << index[i] + idStart << " "; |
||||
else |
||||
outfile << index[i] + idStart << " "; |
||||
} |
||||
} |
||||
outfile << std::endl; |
||||
} |
||||
} |
||||
|
||||
// write out tstrips if any
|
||||
if (input->GetNumberOfStrips() > 0) |
||||
{ |
||||
vtkIdType npts = 0, *index = 0; |
||||
vtkCellArray *cells = input->GetStrips(); |
||||
for (cells->InitTraversal(); cells->GetNextCell(npts, index); ) |
||||
{ |
||||
for (int i = 2, i1, i2; i < npts; ++i) |
||||
{ |
||||
if (i % 2) |
||||
{ |
||||
i1 = i - 1; |
||||
i2 = i - 2; |
||||
} |
||||
else |
||||
{ |
||||
i1 = i - 1; |
||||
i2 = i - 2; |
||||
} |
||||
|
||||
if(normals) |
||||
{ |
||||
if (tcoords) |
||||
{ |
||||
outfile << "f " << index[i1] + idStart << "/" << index[i1] + idStart << "/" << index[i1] + idStart << " " |
||||
<< index[i2]+ idStart << "/" << index[i2] + idStart << "/" << index[i2] + idStart << " " |
||||
<< index[i] + idStart << "/" << index[i] + idStart << "/" << index[i] + idStart << std::endl; |
||||
} |
||||
else |
||||
{ |
||||
outfile << "f " << index[i1] + idStart << "//" << index[i1] + idStart << " " << index[i2] + idStart |
||||
<< "//" << index[i2] + idStart << " " << index[i] + idStart << "//" << index[i] + idStart << std::endl; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
if (tcoords) |
||||
{ |
||||
outfile << "f " << index[i1] + idStart << "/" << index[i1] + idStart << " " << index[i2] + idStart |
||||
<< "/" << index[i2] + idStart << " " << index[i] + idStart << "/" << index[i] + idStart << std::endl; |
||||
} |
||||
else |
||||
outfile << "f " << index[i1] + idStart << " " << index[i2] + idStart << " " << index[i] + idStart << std::endl; |
||||
} |
||||
} /* for (int i = 2; i < npts; ++i) */ |
||||
} |
||||
} /* if (input->GetNumberOfStrips() > 0) */ |
||||
|
||||
this->CloseVTKFile(outfilep); |
||||
|
||||
// Delete the file if an error occurred
|
||||
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) |
||||
{ |
||||
vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); |
||||
unlink(this->FileName); |
||||
} |
||||
} |
||||
|
||||
void cv::viz::vtkOBJWriter::PrintSelf(ostream& os, vtkIndent indent) |
||||
{ |
||||
Superclass::PrintSelf(os, indent); |
||||
os << indent << "DecimalPrecision: " << DecimalPrecision << "\n"; |
||||
} |
@ -0,0 +1,110 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { namespace viz |
||||
{ |
||||
vtkStandardNewMacro(vtkTrajectorySource); |
||||
}} |
||||
|
||||
cv::viz::vtkTrajectorySource::vtkTrajectorySource() { SetNumberOfInputPorts(0); } |
||||
cv::viz::vtkTrajectorySource::~vtkTrajectorySource() {} |
||||
|
||||
void cv::viz::vtkTrajectorySource::SetTrajectory(InputArray _traj) |
||||
{ |
||||
CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); |
||||
CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); |
||||
|
||||
Mat traj; |
||||
_traj.getMat().convertTo(traj, CV_64F); |
||||
const Affine3d* dpath = traj.ptr<Affine3d>(); |
||||
size_t total = traj.total(); |
||||
|
||||
points = vtkSmartPointer<vtkPoints>::New(); |
||||
points->SetDataType(VTK_DOUBLE); |
||||
points->SetNumberOfPoints(total); |
||||
|
||||
tensors = vtkSmartPointer<vtkDoubleArray>::New(); |
||||
tensors->SetNumberOfComponents(9); |
||||
tensors->SetNumberOfTuples(total); |
||||
|
||||
for(size_t i = 0; i < total; ++i, ++dpath) |
||||
{ |
||||
Matx33d R = dpath->rotation().t(); // transposed because of
|
||||
tensors->SetTuple(i, R.val); // column major order
|
||||
|
||||
Vec3d p = dpath->translation(); |
||||
points->SetPoint(i, p.val); |
||||
} |
||||
} |
||||
|
||||
cv::Mat cv::viz::vtkTrajectorySource::ExtractPoints(InputArray _traj) |
||||
{ |
||||
CV_Assert(_traj.kind() == _InputArray::STD_VECTOR || _traj.kind() == _InputArray::MAT); |
||||
CV_Assert(_traj.type() == CV_32FC(16) || _traj.type() == CV_64FC(16)); |
||||
|
||||
Mat points(1, _traj.total(), CV_MAKETYPE(_traj.depth(), 3)); |
||||
const Affine3d* dpath = _traj.getMat().ptr<Affine3d>(); |
||||
const Affine3f* fpath = _traj.getMat().ptr<Affine3f>(); |
||||
|
||||
if (_traj.depth() == CV_32F) |
||||
for(int i = 0; i < points.cols; ++i) |
||||
points.at<Vec3f>(i) = fpath[i].translation(); |
||||
|
||||
if (_traj.depth() == CV_64F) |
||||
for(int i = 0; i < points.cols; ++i) |
||||
points.at<Vec3d>(i) = dpath[i].translation(); |
||||
|
||||
return points; |
||||
} |
||||
|
||||
int cv::viz::vtkTrajectorySource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector) |
||||
{ |
||||
vtkInformation *outInfo = outputVector->GetInformationObject(0); |
||||
vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); |
||||
output->SetPoints(points); |
||||
output->GetPointData()->SetTensors(tensors); |
||||
return 1; |
||||
} |
@ -0,0 +1,84 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __vtkTrajectorySource_h |
||||
#define __vtkTrajectorySource_h |
||||
|
||||
#include <opencv2/core/mat.hpp> |
||||
#include <vtkPolyDataAlgorithm.h> |
||||
#include <vtkSmartPointer.h> |
||||
#include <vtkPoints.h> |
||||
#include <vtkCellArray.h> |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace viz |
||||
{ |
||||
class vtkTrajectorySource : public vtkPolyDataAlgorithm |
||||
{ |
||||
public: |
||||
static vtkTrajectorySource *New(); |
||||
vtkTypeMacro(vtkTrajectorySource,vtkPolyDataAlgorithm) |
||||
|
||||
virtual void SetTrajectory(InputArray trajectory); |
||||
|
||||
static Mat ExtractPoints(InputArray trajectory); |
||||
|
||||
protected: |
||||
vtkTrajectorySource(); |
||||
~vtkTrajectorySource(); |
||||
|
||||
vtkSmartPointer<vtkPoints> points; |
||||
vtkSmartPointer<vtkDoubleArray> tensors; |
||||
|
||||
int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *); |
||||
private: |
||||
vtkTrajectorySource(const vtkTrajectorySource&); // Not implemented.
|
||||
void operator=(const vtkTrajectorySource&); // Not implemented.
|
||||
|
||||
}; |
||||
} |
||||
} |
||||
|
||||
#endif |
@ -0,0 +1,93 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "precomp.hpp" |
||||
|
||||
namespace cv { namespace viz |
||||
{ |
||||
vtkStandardNewMacro(vtkXYZWriter); |
||||
}} |
||||
|
||||
cv::viz::vtkXYZWriter::vtkXYZWriter() |
||||
{ |
||||
std::ofstream fout; // only used to extract the default precision
|
||||
this->DecimalPrecision = fout.precision(); |
||||
} |
||||
|
||||
void cv::viz::vtkXYZWriter::WriteData() |
||||
{ |
||||
vtkPolyData *input = this->GetInput(); |
||||
if (!input) |
||||
return; |
||||
|
||||
// OpenVTKFile() will report any errors that happen
|
||||
ostream *outfilep = this->OpenVTKFile(); |
||||
if (!outfilep) |
||||
return; |
||||
|
||||
ostream &outfile = *outfilep; |
||||
|
||||
for(vtkIdType i = 0; i < input->GetNumberOfPoints(); ++i) |
||||
{ |
||||
Vec3d p; |
||||
input->GetPoint(i, p.val); |
||||
outfile << std::setprecision(this->DecimalPrecision) << p[0] << " " << p[1] << " " << p[2] << std::endl; |
||||
} |
||||
|
||||
// Close the file
|
||||
this->CloseVTKFile(outfilep); |
||||
|
||||
// Delete the file if an error occurred
|
||||
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) |
||||
{ |
||||
vtkErrorMacro("Ran out of disk space; deleting file: " << this->FileName); |
||||
unlink(this->FileName); |
||||
} |
||||
} |
||||
|
||||
void cv::viz::vtkXYZWriter::PrintSelf(ostream& os, vtkIndent indent) |
||||
{ |
||||
this->Superclass::PrintSelf(os,indent); |
||||
os << indent << "DecimalPrecision: " << this->DecimalPrecision << "\n"; |
||||
} |
@ -0,0 +1,78 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
// Authors:
|
||||
// * Anatoly Baksheev, Itseez Inc. myname.mysurname <> mycompany.com
|
||||
//
|
||||
//M*/
|
||||
|
||||
#ifndef __vtkXYZWriter_h |
||||
#define __vtkXYZWriter_h |
||||
|
||||
#include "vtkPolyDataWriter.h" |
||||
|
||||
namespace cv |
||||
{ |
||||
namespace viz |
||||
{ |
||||
class vtkXYZWriter : public vtkPolyDataWriter |
||||
{ |
||||
public: |
||||
static vtkXYZWriter *New(); |
||||
vtkTypeMacro(vtkXYZWriter,vtkPolyDataWriter) |
||||
void PrintSelf(ostream& os, vtkIndent indent); |
||||
|
||||
vtkGetMacro(DecimalPrecision, int) |
||||
vtkSetMacro(DecimalPrecision, int) |
||||
|
||||
protected: |
||||
vtkXYZWriter(); |
||||
~vtkXYZWriter(){} |
||||
|
||||
void WriteData(); |
||||
|
||||
int DecimalPrecision; |
||||
|
||||
private: |
||||
vtkXYZWriter(const vtkXYZWriter&); // Not implemented.
|
||||
void operator=(const vtkXYZWriter&); // Not implemented.
|
||||
}; |
||||
} |
||||
} |
||||
#endif |
@ -1,3 +1,3 @@ |
||||
#include "test_precomp.hpp" |
||||
|
||||
CV_TEST_MAIN("cv") |
||||
CV_TEST_MAIN("viz") |
||||
|
@ -1 +1,24 @@ |
||||
#include "test_precomp.hpp" |
||||
|
||||
cv::String cv::Path::combine(const String& item1, const String& item2) |
||||
{ |
||||
if (item1.empty()) |
||||
return item2; |
||||
|
||||
if (item2.empty()) |
||||
return item1; |
||||
|
||||
char last = item1[item1.size()-1]; |
||||
|
||||
bool need_append = last != '/' && last != '\\'; |
||||
return item1 + (need_append ? "/" : "") + item2; |
||||
} |
||||
|
||||
cv::String cv::Path::combine(const String& item1, const String& item2, const String& item3) |
||||
{ return combine(combine(item1, item2), item3); } |
||||
|
||||
cv::String cv::Path::change_extension(const String& file, const String& ext) |
||||
{ |
||||
String::size_type pos = file.find_last_of('.'); |
||||
return pos == String::npos ? file : file.substr(0, pos+1) + ext; |
||||
} |
||||
|
@ -0,0 +1,407 @@ |
||||
/*M///////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
||||
//
|
||||
// By downloading, copying, installing or using the software you agree to this license.
|
||||
// If you do not agree to this license, do not download, install,
|
||||
// copy or use the software.
|
||||
//
|
||||
//
|
||||
// License Agreement
|
||||
// For Open Source Computer Vision Library
|
||||
//
|
||||
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
|
||||
// Copyright (C) 2008-2013, Willow Garage Inc., all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistribution's of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistribution's in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and / or other materials provided with the distribution.
|
||||
//
|
||||
// * The name of the copyright holders may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// This software is provided by the copyright holders and contributors "as is" and
|
||||
// any express or implied warranties, including, but not limited to, the implied
|
||||
// warranties of merchantability and fitness for a particular purpose are disclaimed.
|
||||
// In no event shall the Intel Corporation or contributors be liable for any direct,
|
||||
// indirect, incidental, special, exemplary, or consequential damages
|
||||
// (including, but not limited to, procurement of substitute goods or services;
|
||||
// loss of use, data, or profits; or business interruption) however caused
|
||||
// and on any theory of liability, whether in contract, strict liability,
|
||||
// or tort (including negligence or otherwise) arising in any way out of
|
||||
// the use of this software, even if advised of the possibility of such damage.
|
||||
//
|
||||
//M*/
|
||||
|
||||
#include "test_precomp.hpp" |
||||
|
||||
using namespace cv; |
||||
using namespace cv::viz; |
||||
|
||||
TEST(Viz, show_cloud_bluberry) |
||||
{ |
||||
Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); |
||||
|
||||
Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); |
||||
|
||||
Viz3d viz("show_cloud_bluberry"); |
||||
viz.showWidget("coosys", WCoordinateSystem()); |
||||
viz.showWidget("dragon", WCloud(dragon_cloud, Color::bluberry()), pose); |
||||
|
||||
viz.showWidget("text2d", WText("Bluberry cloud", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_cloud_random_color) |
||||
{ |
||||
Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); |
||||
|
||||
Mat colors(dragon_cloud.size(), CV_8UC3); |
||||
theRNG().fill(colors, RNG::UNIFORM, 0, 255); |
||||
|
||||
Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); |
||||
|
||||
Viz3d viz("show_cloud_random_color"); |
||||
viz.setBackgroundMeshLab(); |
||||
viz.showWidget("coosys", WCoordinateSystem()); |
||||
viz.showWidget("dragon", WCloud(dragon_cloud, colors), pose); |
||||
viz.showWidget("text2d", WText("Random color cloud", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_cloud_masked) |
||||
{ |
||||
Mat dragon_cloud = readCloud(get_dragon_ply_file_path()); |
||||
|
||||
Vec3f qnan = Vec3f::all(std::numeric_limits<float>::quiet_NaN()); |
||||
for(size_t i = 0; i < dragon_cloud.total(); ++i) |
||||
if (i % 15 != 0) |
||||
dragon_cloud.at<Vec3f>(i) = qnan; |
||||
|
||||
Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); |
||||
|
||||
Viz3d viz("show_cloud_masked"); |
||||
viz.showWidget("coosys", WCoordinateSystem()); |
||||
viz.showWidget("dragon", WCloud(dragon_cloud), pose); |
||||
viz.showWidget("text2d", WText("Nan masked cloud", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_cloud_collection) |
||||
{ |
||||
Mat cloud = readCloud(get_dragon_ply_file_path()); |
||||
|
||||
WCloudCollection ccol; |
||||
ccol.addCloud(cloud, Color::white(), Affine3d().translate(Vec3d(0, 0, 0)).rotate(Vec3d(CV_PI/2, 0, 0))); |
||||
ccol.addCloud(cloud, Color::blue(), Affine3d().translate(Vec3d(1, 0, 0))); |
||||
ccol.addCloud(cloud, Color::red(), Affine3d().translate(Vec3d(2, 0, 0))); |
||||
|
||||
Viz3d viz("show_cloud_collection"); |
||||
viz.setBackgroundColor(Color::mlab()); |
||||
viz.showWidget("coosys", WCoordinateSystem()); |
||||
viz.showWidget("ccol", ccol); |
||||
viz.showWidget("text2d", WText("Cloud collection", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_painted_clouds) |
||||
{ |
||||
Mat cloud = readCloud(get_dragon_ply_file_path()); |
||||
|
||||
Viz3d viz("show_painted_clouds"); |
||||
viz.setBackgroundMeshLab(); |
||||
viz.showWidget("coosys", WCoordinateSystem()); |
||||
viz.showWidget("cloud1", WPaintedCloud(cloud), Affine3d(Vec3d(0.0, -CV_PI/2, 0.0), Vec3d(-1.5, 0.0, 0.0))); |
||||
viz.showWidget("cloud2", WPaintedCloud(cloud, Vec3d(0.0, -0.75, -1.0), Vec3d(0.0, 0.75, 0.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(1.5, 0.0, 0.0))); |
||||
viz.showWidget("cloud3", WPaintedCloud(cloud, Vec3d(0.0, 0.0, -1.0), Vec3d(0.0, 0.0, 1.0), Color::blue(), Color::red())); |
||||
viz.showWidget("arrow", WArrow(Vec3d(0.0, 1.0, -1.0), Vec3d(0.0, 1.0, 1.0), 0.009, Color::raspberry())); |
||||
viz.showWidget("text2d", WText("Painted clouds", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_mesh) |
||||
{ |
||||
Mesh mesh = Mesh::load(get_dragon_ply_file_path()); |
||||
|
||||
Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); |
||||
|
||||
Viz3d viz("show_mesh"); |
||||
viz.showWidget("coosys", WCoordinateSystem()); |
||||
viz.showWidget("mesh", WMesh(mesh), pose); |
||||
viz.showWidget("text2d", WText("Just mesh", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_mesh_random_colors) |
||||
{ |
||||
Mesh mesh = Mesh::load(get_dragon_ply_file_path()); |
||||
theRNG().fill(mesh.colors, RNG::UNIFORM, 0, 255); |
||||
|
||||
Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); |
||||
|
||||
Viz3d viz("show_mesh_random_color"); |
||||
viz.showWidget("coosys", WCoordinateSystem()); |
||||
viz.showWidget("mesh", WMesh(mesh), pose); |
||||
viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); |
||||
viz.showWidget("text2d", WText("Random color mesh", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_textured_mesh) |
||||
{ |
||||
Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); |
||||
|
||||
std::vector<Vec3d> points; |
||||
std::vector<Vec2d> tcoords; |
||||
std::vector<int> polygons; |
||||
for(size_t i = 0; i < 64; ++i) |
||||
{ |
||||
double angle = CV_PI/2 * i/64.0; |
||||
points.push_back(Vec3d(0.00, cos(angle), sin(angle))*0.75); |
||||
points.push_back(Vec3d(1.57, cos(angle), sin(angle))*0.75); |
||||
tcoords.push_back(Vec2d(0.0, i/64.0)); |
||||
tcoords.push_back(Vec2d(1.0, i/64.0)); |
||||
} |
||||
|
||||
for(size_t i = 0; i < points.size()/2-1; ++i) |
||||
{ |
||||
int polys[] = {3, 2*i, 2*i+1, 2*i+2, 3, 2*i+1, 2*i+2, 2*i+3}; |
||||
polygons.insert(polygons.end(), polys, polys + sizeof(polys)/sizeof(polys[0])); |
||||
} |
||||
|
||||
cv::viz::Mesh mesh; |
||||
mesh.cloud = Mat(points, true).reshape(3, 1); |
||||
mesh.tcoords = Mat(tcoords, true).reshape(2, 1); |
||||
mesh.polygons = Mat(polygons, true).reshape(1, 1); |
||||
mesh.texture = lena; |
||||
|
||||
Viz3d viz("show_textured_mesh"); |
||||
viz.setBackgroundMeshLab(); |
||||
viz.showWidget("coosys", WCoordinateSystem()); |
||||
viz.showWidget("mesh", WMesh(mesh)); |
||||
viz.setRenderingProperty("mesh", SHADING, SHADING_PHONG); |
||||
viz.showWidget("text2d", WText("Textured mesh", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_polyline) |
||||
{ |
||||
Mat polyline(1, 32, CV_64FC3); |
||||
for(size_t i = 0; i < polyline.total(); ++i) |
||||
polyline.at<Vec3d>(i) = Vec3d(i/16.0, cos(i * CV_PI/6), sin(i * CV_PI/6)); |
||||
|
||||
Viz3d viz("show_polyline"); |
||||
viz.showWidget("polyline", WPolyLine(Mat(polyline), Color::apricot())); |
||||
viz.showWidget("coosys", WCoordinateSystem()); |
||||
viz.showWidget("text2d", WText("Polyline", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_sampled_normals) |
||||
{ |
||||
Mesh mesh = Mesh::load(get_dragon_ply_file_path()); |
||||
computeNormals(mesh, mesh.normals); |
||||
|
||||
Affine3d pose = Affine3d().rotate(Vec3d(0, 0.8, 0)); |
||||
|
||||
Viz3d viz("show_sampled_normals"); |
||||
viz.showWidget("mesh", WMesh(mesh), pose); |
||||
viz.showWidget("normals", WCloudNormals(mesh.cloud, mesh.normals, 30, 0.1f, Color::green()), pose); |
||||
viz.setRenderingProperty("normals", LINE_WIDTH, 2.0); |
||||
viz.showWidget("text2d", WText("Cloud or mesh normals", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_trajectories) |
||||
{ |
||||
std::vector<Affine3d> path = generate_test_trajectory<double>(), sub0, sub1, sub2, sub3, sub4, sub5; |
||||
|
||||
Mat(path).rowRange(0, path.size()/10+1).copyTo(sub0); |
||||
Mat(path).rowRange(path.size()/10, path.size()/5+1).copyTo(sub1); |
||||
Mat(path).rowRange(path.size()/5, 11*path.size()/12).copyTo(sub2); |
||||
Mat(path).rowRange(11*path.size()/12, path.size()).copyTo(sub3); |
||||
Mat(path).rowRange(3*path.size()/4, 33*path.size()/40).copyTo(sub4); |
||||
Mat(path).rowRange(33*path.size()/40, 9*path.size()/10).copyTo(sub5); |
||||
Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); |
||||
|
||||
Viz3d viz("show_trajectories"); |
||||
viz.showWidget("coos", WCoordinateSystem()); |
||||
viz.showWidget("sub0", WTrajectorySpheres(sub0, 0.25, 0.07)); |
||||
viz.showWidget("sub1", WTrajectory(sub1, WTrajectory::PATH, 0.2, Color::brown())); |
||||
viz.showWidget("sub2", WTrajectory(sub2, WTrajectory::FRAMES, 0.2)); |
||||
viz.showWidget("sub3", WTrajectory(sub3, WTrajectory::BOTH, 0.2, Color::green())); |
||||
viz.showWidget("sub4", WTrajectoryFrustums(sub4, K, 0.3, Color::yellow())); |
||||
viz.showWidget("sub5", WTrajectoryFrustums(sub5, Vec2d(0.78, 0.78), 0.15)); |
||||
viz.showWidget("text2d", WText("Different kinds of supported trajectories", Point(20, 20), 20, Color::green())); |
||||
|
||||
int i = 0; |
||||
while(!viz.wasStopped()) |
||||
{ |
||||
double a = --i % 360; |
||||
Vec3d pose(sin(a * CV_PI/180), 0.7, cos(a * CV_PI/180)); |
||||
viz.setViewerPose(makeCameraPose(pose * 7.5, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); |
||||
viz.spinOnce(20, true); |
||||
} |
||||
viz.resetCamera(); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_trajectory_reposition) |
||||
{ |
||||
std::vector<Affine3f> path = generate_test_trajectory<float>(); |
||||
|
||||
Viz3d viz("show_trajectory_reposition_to_origin"); |
||||
viz.showWidget("coos", WCoordinateSystem()); |
||||
viz.showWidget("sub3", WTrajectory(Mat(path).rowRange(0, path.size()/3), WTrajectory::BOTH, 0.2, Color::brown()), path.front().inv()); |
||||
viz.showWidget("text2d", WText("Trajectory resposition to origin", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_camera_positions) |
||||
{ |
||||
Matx33d K(1024.0, 0.0, 320.0, 0.0, 1024.0, 240.0, 0.0, 0.0, 1.0); |
||||
Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); |
||||
Mat gray = make_gray(lena); |
||||
|
||||
Affine3d poses[2]; |
||||
for(int i = 0; i < 2; ++i) |
||||
{ |
||||
Vec3d pose = 5 * Vec3d(sin(3.14 + 2.7 + i*60 * CV_PI/180), 0.4 - i*0.3, cos(3.14 + 2.7 + i*60 * CV_PI/180)); |
||||
poses[i] = makeCameraPose(pose, Vec3d(0.0, 0.0, 0.0), Vec3d(0.0, -0.1, 0.0)); |
||||
} |
||||
|
||||
Viz3d viz("show_camera_positions"); |
||||
viz.showWidget("sphe", WSphere(Point3d(0,0,0), 1.0, 10, Color::orange_red())); |
||||
viz.showWidget("coos", WCoordinateSystem(1.5)); |
||||
viz.showWidget("pos1", WCameraPosition(0.75), poses[0]); |
||||
viz.showWidget("pos2", WCameraPosition(Vec2d(0.78, 0.78), lena, 2.2, Color::green()), poses[0]); |
||||
viz.showWidget("pos3", WCameraPosition(0.75), poses[1]); |
||||
viz.showWidget("pos4", WCameraPosition(K, gray, 3, Color::indigo()), poses[1]); |
||||
viz.showWidget("text2d", WText("Camera positions with images", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_overlay_image) |
||||
{ |
||||
Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); |
||||
Mat gray = make_gray(lena); |
||||
|
||||
Size2d half_lsize = Size2d(lena.size()) * 0.5; |
||||
|
||||
Viz3d viz("show_overlay_image"); |
||||
viz.setBackgroundMeshLab(); |
||||
Size vsz = viz.getWindowSize(); |
||||
|
||||
viz.showWidget("coos", WCoordinateSystem()); |
||||
viz.showWidget("cube", WCube()); |
||||
viz.showWidget("img1", WImageOverlay(lena, Rect(Point(10, 10), half_lsize))); |
||||
viz.showWidget("img2", WImageOverlay(gray, Rect(Point(vsz.width-10-lena.cols/2, 10), half_lsize))); |
||||
viz.showWidget("img3", WImageOverlay(gray, Rect(Point(10, vsz.height-10-lena.rows/2), half_lsize))); |
||||
viz.showWidget("img5", WImageOverlay(lena, Rect(Point(vsz.width-10-lena.cols/2, vsz.height-10-lena.rows/2), half_lsize))); |
||||
viz.showWidget("text2d", WText("Overlay images", Point(20, 20), 20, Color::green())); |
||||
|
||||
int i = 0; |
||||
while(!viz.wasStopped()) |
||||
{ |
||||
double a = ++i % 360; |
||||
Vec3d pose(sin(a * CV_PI/180), 0.7, cos(a * CV_PI/180)); |
||||
viz.setViewerPose(makeCameraPose(pose * 3, Vec3d(0.0, 0.5, 0.0), Vec3d(0.0, 0.1, 0.0))); |
||||
viz.getWidget("img1").cast<WImageOverlay>().setImage(lena * pow(sin(i*10*CV_PI/180) * 0.5 + 0.5, 1.0)); |
||||
viz.spinOnce(1, true); |
||||
} |
||||
viz.showWidget("text2d", WText("Overlay images (stopped)", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
|
||||
TEST(Viz, show_image_method) |
||||
{ |
||||
Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); |
||||
|
||||
Viz3d viz("show_image_method"); |
||||
viz.showImage(lena); |
||||
viz.spinOnce(1500, true); |
||||
viz.showImage(lena, lena.size()); |
||||
viz.spinOnce(1500, true); |
||||
|
||||
cv::viz::imshow("show_image_method", make_gray(lena)).spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_image_3d) |
||||
{ |
||||
Mat lena = imread(Path::combine(cvtest::TS::ptr()->get_data_path(), "lena.png")); |
||||
Mat gray = make_gray(lena); |
||||
|
||||
Viz3d viz("show_image_3d"); |
||||
viz.setBackgroundMeshLab(); |
||||
viz.showWidget("coos", WCoordinateSystem()); |
||||
viz.showWidget("cube", WCube()); |
||||
viz.showWidget("arr0", WArrow(Vec3d(0.5, 0.0, 0.0), Vec3d(1.5, 0.0, 0.0), 0.009, Color::raspberry())); |
||||
viz.showWidget("img0", WImage3D(lena, Size2d(1.0, 1.0)), Affine3d(Vec3d(0.0, CV_PI/2, 0.0), Vec3d(.5, 0.0, 0.0))); |
||||
viz.showWidget("arr1", WArrow(Vec3d(-0.5, -0.5, 0.0), Vec3d(0.2, 0.2, 0.0), 0.009, Color::raspberry())); |
||||
viz.showWidget("img1", WImage3D(gray, Size2d(1.0, 1.0), Vec3d(-0.5, -0.5, 0.0), Vec3d(1.0, 1.0, 0.0), Vec3d(0.0, 1.0, 0.0))); |
||||
|
||||
viz.showWidget("arr3", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); |
||||
|
||||
viz.showWidget("text2d", WText("Images in 3D", Point(20, 20), 20, Color::green())); |
||||
|
||||
int i = 0; |
||||
while(!viz.wasStopped()) |
||||
{ |
||||
viz.getWidget("img0").cast<WImage3D>().setImage(lena * pow(sin(i++*7.5*CV_PI/180) * 0.5 + 0.5, 1.0)); |
||||
viz.spinOnce(1, true); |
||||
} |
||||
viz.showWidget("text2d", WText("Images in 3D (stopped)", Point(20, 20), 20, Color::green())); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_simple_widgets) |
||||
{ |
||||
Viz3d viz("show_simple_widgets"); |
||||
viz.setBackgroundMeshLab(); |
||||
|
||||
viz.showWidget("coos", WCoordinateSystem()); |
||||
viz.showWidget("cube", WCube()); |
||||
viz.showWidget("cub0", WCube(Vec3d::all(-1.0), Vec3d::all(-0.5), false, Color::indigo())); |
||||
viz.showWidget("arro", WArrow(Vec3d::all(-0.5), Vec3d::all(0.5), 0.009, Color::raspberry())); |
||||
viz.showWidget("cir1", WCircle(0.5, 0.01, Color::bluberry())); |
||||
viz.showWidget("cir2", WCircle(0.5, Point3d(0.5, 0.0, 0.0), Vec3d(1.0, 0.0, 0.0), 0.01, Color::apricot())); |
||||
|
||||
viz.showWidget("cyl0", WCylinder(Vec3d(-0.5, 0.5, -0.5), Vec3d(0.5, 0.5, -0.5), 0.125, 30, Color::brown())); |
||||
viz.showWidget("con0", WCone(0.25, 0.125, 6, Color::azure())); |
||||
viz.showWidget("con1", WCone(0.125, Point3d(0.5, -0.5, 0.5), Point3d(0.5, -1.0, 0.5), 6, Color::turquoise())); |
||||
|
||||
viz.showWidget("text2d", WText("Different simple widgets", Point(20, 20), 20, Color::green())); |
||||
viz.showWidget("text3d", WText3D("Simple 3D text", Point3d( 0.5, 0.5, 0.5), 0.125, false, Color::green())); |
||||
|
||||
viz.showWidget("plane1", WPlane(Size2d(0.25, 0.75))); |
||||
viz.showWidget("plane2", WPlane(Vec3d(0.5, -0.5, -0.5), Vec3d(0.0, 1.0, 1.0), Vec3d(1.0, 1.0, 0.0), Size2d(1.0, 0.5), Color::gold())); |
||||
|
||||
viz.showWidget("grid1", WGrid(Vec2i(7,7), Vec2d::all(0.75), Color::gray()), Affine3d().translate(Vec3d(0.0, 0.0, -1.0))); |
||||
|
||||
viz.spin(); |
||||
viz.getWidget("text2d").cast<WText>().setText("Different simple widgets (updated)"); |
||||
viz.getWidget("text3d").cast<WText3D>().setText("Updated text 3D"); |
||||
viz.spin(); |
||||
} |
||||
|
||||
TEST(Viz, show_follower) |
||||
{ |
||||
Viz3d viz("show_follower"); |
||||
|
||||
viz.showWidget("coos", WCoordinateSystem()); |
||||
viz.showWidget("cube", WCube()); |
||||
viz.showWidget("t3d_2", WText3D("Simple 3D follower", Point3d(-0.5, -0.5, 0.5), 0.125, true, Color::green())); |
||||
viz.showWidget("text2d", WText("Follower: text always facing camera", Point(20, 20), 20, Color::green())); |
||||
viz.setBackgroundMeshLab(); |
||||
viz.spin(); |
||||
viz.getWidget("t3d_2").cast<WText3D>().setText("Updated follower 3D"); |
||||
viz.spin(); |
||||
} |
Loading…
Reference in new issue