1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2013, OpenCV Foundation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of the copyright holders may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 // Authors:
41 //  * Anatoly Baksheev, Itseez Inc.  myname.mysurname <> mycompany.com
42 //
43 //M*/
44 
45 #include "precomp.hpp"
46 
47 namespace cv { namespace viz
48 {
49     vtkStandardNewMacro(vtkCloudMatSource);
50 
51     template<typename _Tp> struct VtkDepthTraits;
52 
53     template<> struct VtkDepthTraits<float>
54     {
55         const static int data_type = VTK_FLOAT;
56         typedef vtkFloatArray array_type;
57     };
58 
59     template<> struct VtkDepthTraits<double>
60     {
61         const static int data_type = VTK_DOUBLE;
62         typedef vtkDoubleArray array_type;
63     };
64 }}
65 
vtkCloudMatSource()66 cv::viz::vtkCloudMatSource::vtkCloudMatSource() { SetNumberOfInputPorts(0); }
~vtkCloudMatSource()67 cv::viz::vtkCloudMatSource::~vtkCloudMatSource() {}
68 
SetCloud(InputArray _cloud)69 int cv::viz::vtkCloudMatSource::SetCloud(InputArray _cloud)
70 {
71     CV_Assert(_cloud.depth() == CV_32F || _cloud.depth() == CV_64F);
72     CV_Assert(_cloud.channels() == 3 || _cloud.channels() == 4);
73 
74     Mat cloud = _cloud.getMat();
75 
76     int total = _cloud.depth() == CV_32F ? filterNanCopy<float>(cloud) : filterNanCopy<double>(cloud);
77 
78     vertices = vtkSmartPointer<vtkCellArray>::New();
79     vertices->Allocate(vertices->EstimateSize(1, total));
80     vertices->InsertNextCell(total);
81     for(int i = 0; i < total; ++i)
82         vertices->InsertCellPoint(i);
83 
84     return total;
85 }
86 
SetColorCloud(InputArray _cloud,InputArray _colors)87 int cv::viz::vtkCloudMatSource::SetColorCloud(InputArray _cloud, InputArray _colors)
88 {
89     int total = SetCloud(_cloud);
90 
91     if (_colors.empty())
92         return total;
93 
94     CV_Assert(_colors.depth() == CV_8U && _colors.channels() <= 4 && _colors.channels() != 2);
95     CV_Assert(_colors.size() == _cloud.size());
96 
97     Mat cloud = _cloud.getMat();
98     Mat colors = _colors.getMat();
99 
100     if (cloud.depth() == CV_32F)
101         filterNanColorsCopy<float>(colors, cloud, total);
102     else if (cloud.depth() == CV_64F)
103         filterNanColorsCopy<double>(colors, cloud, total);
104 
105     return total;
106 }
107 
SetColorCloudNormals(InputArray _cloud,InputArray _colors,InputArray _normals)108 int cv::viz::vtkCloudMatSource::SetColorCloudNormals(InputArray _cloud, InputArray _colors, InputArray _normals)
109 {
110     int total = SetColorCloud(_cloud, _colors);
111 
112     if (_normals.empty())
113         return total;
114 
115     CV_Assert(_normals.depth() == CV_32F || _normals.depth() == CV_64F);
116     CV_Assert(_normals.channels() == 3 || _normals.channels() == 4);
117     CV_Assert(_normals.size() == _cloud.size());
118 
119     Mat c = _cloud.getMat();
120     Mat n = _normals.getMat();
121 
122     if (n.depth() == CV_32F && c.depth() == CV_32F)
123         filterNanNormalsCopy<float, float>(n, c, total);
124     else if (n.depth() == CV_32F && c.depth() == CV_64F)
125         filterNanNormalsCopy<float, double>(n, c, total);
126     else if (n.depth() == CV_64F && c.depth() == CV_32F)
127         filterNanNormalsCopy<double, float>(n, c, total);
128     else if (n.depth() == CV_64F && c.depth() == CV_64F)
129         filterNanNormalsCopy<double, double>(n, c, total);
130     else
131         CV_Assert(!"Unsupported normals/cloud type");
132 
133     return total;
134 }
135 
SetColorCloudNormalsTCoords(InputArray _cloud,InputArray _colors,InputArray _normals,InputArray _tcoords)136 int cv::viz::vtkCloudMatSource::SetColorCloudNormalsTCoords(InputArray _cloud, InputArray _colors, InputArray _normals, InputArray _tcoords)
137 {
138     int total = SetColorCloudNormals(_cloud, _colors, _normals);
139 
140     if (_tcoords.empty())
141         return total;
142 
143     CV_Assert(_tcoords.depth() == CV_32F || _tcoords.depth() == CV_64F);
144     CV_Assert(_tcoords.channels() == 2 && _tcoords.size() == _cloud.size());
145 
146     Mat cl = _cloud.getMat();
147     Mat tc = _tcoords.getMat();
148 
149     if (tc.depth() == CV_32F && cl.depth() == CV_32F)
150         filterNanTCoordsCopy<float, float>(tc, cl, total);
151     else if (tc.depth() == CV_32F && cl.depth() == CV_64F)
152         filterNanTCoordsCopy<float, double>(tc, cl, total);
153     else if (tc.depth() == CV_64F && cl.depth() == CV_32F)
154         filterNanTCoordsCopy<double, float>(tc, cl, total);
155     else if (tc.depth() == CV_64F && cl.depth() == CV_64F)
156         filterNanTCoordsCopy<double, double>(tc, cl, total);
157     else
158         CV_Assert(!"Unsupported tcoords/cloud type");
159 
160     return total;
161 }
162 
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)163 int cv::viz::vtkCloudMatSource::RequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *outputVector)
164 {
165     vtkInformation *outInfo = outputVector->GetInformationObject(0);
166     vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
167 
168     output->SetPoints(points);
169     output->SetVerts(vertices);
170     if (scalars)
171         output->GetPointData()->SetScalars(scalars);
172 
173     if (normals)
174         output->GetPointData()->SetNormals(normals);
175 
176     if (tcoords)
177         output->GetPointData()->SetTCoords(tcoords);
178 
179     return 1;
180 }
181 
182 template<typename _Tp>
filterNanCopy(const Mat & cloud)183 int cv::viz::vtkCloudMatSource::filterNanCopy(const Mat& cloud)
184 {
185     CV_DbgAssert(DataType<_Tp>::depth == cloud.depth());
186     points = vtkSmartPointer<vtkPoints>::New();
187     points->SetDataType(VtkDepthTraits<_Tp>::data_type);
188     points->Allocate((vtkIdType)cloud.total());
189     points->SetNumberOfPoints((vtkIdType)cloud.total());
190 
191     int s_chs = cloud.channels();
192     int total = 0;
193     for (int y = 0; y < cloud.rows; ++y)
194     {
195         const _Tp* srow = cloud.ptr<_Tp>(y);
196         const _Tp* send = srow + cloud.cols * s_chs;
197 
198         for (; srow != send; srow += s_chs)
199             if (!isNan(srow))
200                 points->SetPoint(total++, srow);
201     }
202     points->SetNumberOfPoints(total);
203     points->Squeeze();
204     return total;
205 }
206 
207 template<typename _Msk>
filterNanColorsCopy(const Mat & cloud_colors,const Mat & mask,int total)208 void cv::viz::vtkCloudMatSource::filterNanColorsCopy(const Mat& cloud_colors, const Mat& mask, int total)
209 {
210     Vec3b* array = new Vec3b[total];
211     Vec3b* pos = array;
212 
213     int s_chs = cloud_colors.channels();
214     int m_chs = mask.channels();
215     for (int y = 0; y < cloud_colors.rows; ++y)
216     {
217         const unsigned char* srow = cloud_colors.ptr<unsigned char>(y);
218         const unsigned char* send = srow + cloud_colors.cols * s_chs;
219         const _Msk* mrow = mask.ptr<_Msk>(y);
220 
221         if (cloud_colors.channels() == 1)
222         {
223             for (; srow != send; srow += s_chs, mrow += m_chs)
224                 if (!isNan(mrow))
225                     *pos++ = Vec3b(srow[0], srow[0], srow[0]);
226         }
227         else
228             for (; srow != send; srow += s_chs, mrow += m_chs)
229                 if (!isNan(mrow))
230                     *pos++ = Vec3b(srow[2], srow[1], srow[0]);
231 
232     }
233 
234     scalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
235     scalars->SetName("Colors");
236     scalars->SetNumberOfComponents(3);
237     scalars->SetNumberOfTuples(total);
238     scalars->SetArray(array->val, total * 3, 0);
239 }
240 
241 template<typename _Tn, typename _Msk>
filterNanNormalsCopy(const Mat & cloud_normals,const Mat & mask,int total)242 void cv::viz::vtkCloudMatSource::filterNanNormalsCopy(const Mat& cloud_normals, const Mat& mask, int total)
243 {
244     normals = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New();
245     normals->SetName("Normals");
246     normals->SetNumberOfComponents(3);
247     normals->SetNumberOfTuples(total);
248 
249     int s_chs = cloud_normals.channels();
250     int m_chs = mask.channels();
251 
252     int pos = 0;
253     for (int y = 0; y < cloud_normals.rows; ++y)
254     {
255         const _Tn* srow = cloud_normals.ptr<_Tn>(y);
256         const _Tn* send = srow + cloud_normals.cols * s_chs;
257 
258         const _Msk* mrow = mask.ptr<_Msk>(y);
259 
260         for (; srow != send; srow += s_chs, mrow += m_chs)
261             if (!isNan(mrow))
262                 normals->SetTuple(pos++, srow);
263     }
264 }
265 
266 template<typename _Tn, typename _Msk>
filterNanTCoordsCopy(const Mat & _tcoords,const Mat & mask,int total)267 void cv::viz::vtkCloudMatSource::filterNanTCoordsCopy(const Mat& _tcoords, const Mat& mask, int total)
268 {
269     typedef Vec<_Tn, 2> Vec2;
270     tcoords = vtkSmartPointer< typename VtkDepthTraits<_Tn>::array_type >::New();
271     tcoords->SetName("TextureCoordinates");
272     tcoords->SetNumberOfComponents(2);
273     tcoords->SetNumberOfTuples(total);
274 
275     int pos = 0;
276     for (int y = 0; y < mask.rows; ++y)
277     {
278         const Vec2* srow = _tcoords.ptr<Vec2>(y);
279         const Vec2* send = srow + _tcoords.cols;
280         const _Msk* mrow = mask.ptr<_Msk>(y);
281 
282         for (; srow != send; ++srow, mrow += mask.channels())
283             if (!isNan(mrow))
284                 tcoords->SetTuple(pos++, srow->val);
285     }
286 }
287