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