OMToolkit 1.0 The polygonal mesh processing tool.

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
OMFilter.hxx
Go to the documentation of this file.
1 //==============================================================================
14 #ifndef _OM_FILTER_HXX_
15 #define _OM_FILTER_HXX_
16
17 #include <OMToolkit\OMTransformationSolver.h>
19 // Constructor - initializes vital variables and makes a liaison with target mesh
20 // @param mesh Mesh to work with
22 template <class Mesh, class MatrixT>
23 OMFilter<Mesh, MatrixT>::OMFilter(Mesh *mesh)
24 {
25 m_mesh = mesh;
26 m_loaded = false;
27 m_numKernels = 0;
28 }
29
31 // Saves maximal value of attached vertex matrix into attribute vector
32 // Save is done by push back
33 // @param matrixHandle Handle to a matrix - universal property handle
34 // @return True if all computation completed successfully
36 template <class Mesh, class MatrixT>
37 bool OMFilter<Mesh, MatrixT>::MaxAll(const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
38 {
39 Mesh::VertexIter end = m_mesh->vertices_end();
40 for (Mesh::VertexIter vertex = m_mesh->vertices_begin(); vertex != end; ++vertex)
41 m_mesh->getAttributes(vertex).push_back(m_mesh->property(matrixHandle, vertex).maxCoeff());
42 return true;
43 }
44
46 // Saves median value of attached vertex matrix into attribute vector
47 // Save is done by push back
48 // @param matrixHandle Handle to a matrix - universal property handle
49 // @return True if all computation completed successfully
51 template <class Mesh, class MatrixT>
52 bool OMFilter<Mesh, MatrixT>::MedianAll(const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
53 {
54 Mesh::VertexIter end = m_mesh->vertices_end();
55 MatrixT current;
56 Scalar *data;
57 Scalar *dataCopy;
58 int size;
59 for (Mesh::VertexIter vertex = m_mesh->vertices_begin(); vertex != end; ++vertex)
60 {
61 current = m_mesh->property(matrixHandle, vertex);
62 data = current.data();
63 size = current.size();
64 dataCopy = new Scalar[size];
65 memcpy(dataCopy, data, size * sizeof(Scalar));
66
67 std::sort(&(dataCopy[0]), &(dataCopy[size]));
68 m_mesh->getAttributes(vertex).push_back(dataCopy[size/2]);
69 delete dataCopy;
70 }
71 return true;
72 }
73
75 // Saves mean value of attached vertex matrix into attribute vector
76 // Save is done by push back
77 // @param matrixHandle Handle to a matrix - universal property handle
78 // @return True if all computation completed successfully
80 template <class Mesh, class MatrixT>
81 bool OMFilter<Mesh, MatrixT>::MeanAll(const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
82 {
83 Mesh::VertexIter end = m_mesh->vertices_end();
84 MatrixT current;
85 Scalar *data;
86 int size;
87 for (Mesh::VertexIter vertex = m_mesh->vertices_begin(); vertex != end; ++vertex)
88 {
89 current = m_mesh->property(matrixHandle, vertex);
90 data = current.data();
91 size = current.size();
92 Scalar sum = 0.0;
93 for (int i = 0; i < size; ++i)
94 sum += data[i];
95 m_mesh->getAttributes(vertex).push_back(sum /= (Scalar)size);
96 }
97 return true;
98 }
99
100
102 // Saves a variance of attached vertex matrix from a plane into attribute vector
103 // Save is done by push back
104 // @param matrixHandle Handle to a matrix - universal property handle
105 // @return True if all computation completed successfully
107 template <class Mesh, class MatrixT>
108 bool OMFilter<Mesh, MatrixT>::VarianceAll(const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
109 {
110 Mesh::VertexIter end = m_mesh->vertices_end();
111 MatrixT current;
112 Scalar *data;
113 int size;
114 for (Mesh::VertexIter vertex = m_mesh->vertices_begin(); vertex != end; ++vertex)
115 {
116 current = m_mesh->property(matrixHandle, vertex);
117 data = current.data();
118 size = current.size();
119 Scalar sum = 0.0;
120 Scalar variance = 0.0;
121 for (int i = 0; i < size; ++i)
122 sum += data[i];
123
124 sum /= (Scalar)size;
125 for (int i = 0; i < size; ++i)
126 variance += data[i] - sum;
127
128 m_mesh->getAttributes(vertex).push_back(variance /= (Scalar)size);
129 }
130 return true;
131 }
133 // Saves minimal value of attached vertex matrix into attribute vector
134 // Save is done by push back
135 // @param matrixHandle Handle to a matrix - universal property handle
136 // @return True if all computation completed successfully
138 template <class Mesh, class MatrixT>
139 bool OMFilter<Mesh, MatrixT>::MinAll(const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
140 {
141 Mesh::VertexIter end = m_mesh->vertices_end();
142 for (Mesh::VertexIter vertex = m_mesh->vertices_begin(); vertex != end; ++vertex)
143 m_mesh->getAttributes(vertex).push_back(m_mesh->property(matrixHandle, vertex).minCoeff());
144 return true;
145 }
146
148 // Saves a max distance of attached vertex matrix from a plane into attribute vector
149 // Save is done by push back
150 // @param matrixHandle Handle to a matrix - universal property handle
151 // @return True if all computation completed successfully
153 template <class Mesh, class MatrixT>
154 bool OMFilter<Mesh, MatrixT>::AbsAll(const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
155 {
156 Mesh::VertexIter end = m_mesh->vertices_end();
157 Scalar min, max;
158 for (Mesh::VertexIter vertex = m_mesh->vertices_begin(); vertex != end; ++vertex)
159 {
160 min = abs(m_mesh->property(matrixHandle, vertex).minCoeff());
161 max = abs(m_mesh->property(matrixHandle, vertex).maxCoeff());
162 m_mesh->getAttributes(vertex).push_back(min > max ? min : max);
163 }
164 return true;
165 }
166
168 // Filters matrices attached to each vertex and returns value in the middle
169 // Provides only fast filtering - computes only value in the middle of a matrix
170 // Vertex matrix must have the same size asi filter kernel
171 // Kernel must be loaded from file before calling this function
172 // Result is saved into attribute vector (push back)
173 // If there is multiple filtering kernels, result is computed as eucleidian norm of result vector
174 // (result = sqrt(x^2 + y^2 + ... + z^2))
175 // @param matrixHandle Handle to a matrix - universal property handle
176 // @return True if all computation completed successfully
178 template <class Mesh, class MatrixT>
179 bool OMFilter<Mesh, MatrixT>::FilterAll(const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
180 {
181 if (m_loaded)
182 {
183 Mesh::VertexIter end = m_mesh->vertices_end();
184 MatrixT current;
185 int rows = m_filterKernel[0].rows();
186 int cols = m_filterKernel[0].cols();
187 for (Mesh::VertexIter vertex = m_mesh->vertices_begin(); vertex != end; ++vertex)
188 {
189 current = m_mesh->property(matrixHandle, vertex);
190 if (rows < current.rows() || cols < current.cols())
191 filterOneSmall(vertex.handle(), matrixHandle);
192 else
193 m_mesh->getAttributes(vertex).push_back(filterOne(vertex.handle(), matrixHandle));
194 }
195 return true;
196 }
197 else
198 return false;
199
200 }
201
203 // Multiplies each element of the matrix with corresponding weight in filter matrix
204 // Vertex matrix must have the same size asi filter kernel
205 // Kernel must be loaded from file before calling this function
206 // If there is multiple filtering kernels, weighting is computed in series
207 // @param matrixHandle Handle to a matrix - universal property handle
208 // @return True if all computation completed successfully
210 template <class Mesh, class MatrixT>
211 bool OMFilter<Mesh, MatrixT>::WeightAll(const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
212 {
213 if (m_loaded)
214 {
215 Mesh::VertexIter end = m_mesh->vertices_end();
216 MatrixT current;
217 int rows = m_filterKernel[0].rows();
218 int cols = m_filterKernel[0].cols();
219 for (Mesh::VertexIter vertex = m_mesh->vertices_begin(); vertex != end; ++vertex)
220 {
221 current = m_mesh->property(matrixHandle, vertex);
222 if (rows != current.rows() || cols != current.cols()) return false;
223
224 weightOne(vertex.handle(), matrixHandle);
225 }
226 return true;
227 }
228 else
229 return false;
230 }
231
233 // Helper function which computes fast filtering of one matrix (used in FilterAll)
234 // @param vertex Vertex on which we are doing computations
235 // @param matrixHandle Handle to a matrix - universal property handle
236 // @return value in the middle of matrix
238 template <class Mesh, class MatrixT>
239 typename OMFilter<Mesh, MatrixT>::Scalar OMFilter<Mesh, MatrixT>::filterOne(typename Mesh::VertexHandle &vertex, const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
240 {
241 // load matrix data
242 Scalar *first = m_mesh->property(matrixHandle, vertex).data();
243 Scalar *filter = NULL;
244 Scalar result = 0.0;
245
246 for (unsigned int i = 0; i < m_numKernels; ++i)
247 {
248 Scalar aux = 0.0;
249 filter = m_filterKernel[i].data();
250 int i_max = m_filterKernel[i].size();
251 for (int j = 0; j < i_max; ++j) aux += filter[j] * first[j];
252 result += aux * aux;
253 }
254 return sqrt(result);
255 }
256
258 // Helper function which computes fast filtering of one matrix (smaller filter kernel than tangent matrix)
259 // @param vertex Vertex on which we are doing computations
260 // @param matrixHandle Handle to a matrix - universal property handle
262 template <class Mesh, class MatrixT>
263 void OMFilter<Mesh, MatrixT>::filterOneSmall(typename Mesh::VertexHandle &vertex, const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
264 {
265 MatrixT matrix = m_mesh->property(matrixHandle, vertex);
266 int rows = matrix.rows();
267 MatrixT aux(rows, rows);
268
269 MatrixT filter = m_filterKernel[0];
270 int rowsF = filter.rows();
271
272 int half = rowsF/2;
273
274 // convolution
275 for (int r = 0; r < rows; ++r)
276 for (int c = 0; c < rows; ++c)
277 {
278 Scalar result = 0.0;
279 for (int rF = -half; rF <= half; ++rF)
280 for (int cF = -half; cF <= half; ++cF)
281 {
282 if (r+rF < 0 || c+cF < 0 || r+rF >= rows || r+rF >= rows) continue;
283 else
284 {
285 result += matrix(r+rF, c+cF) * filter(rF+half, cF+half);
286 }
287 }
288 aux(r, c) = result;
289 }
290
291 m_mesh->property(matrixHandle, vertex) = aux;
292 }
293
295 // Helper function which multiplies each matrix element with corresponding weight saved in filter matrix
296 // @param vertex Vertex on which we are doing computations
297 // @param matrixHandle Handle to a matrix - universal property handle
299 template <class Mesh, class MatrixT>
300 void OMFilter<Mesh, MatrixT>::weightOne(typename Mesh::VertexHandle &vertex, const OpenMesh::VPropHandleT<MatrixT> &matrixHandle)
301 {
302 // load matrix data
303 Scalar *first = m_mesh->property(matrixHandle, vertex).data();
304 Scalar *filter = NULL;
305 for (unsigned int i = 0; i < m_numKernels; ++i)
306 {
307 filter = m_filterKernel[i].data();
308 int i_max = m_filterKernel[i].size();
309 for (int i = 0; i < i_max; ++i) first[i] = filter[i] * first[i];
310 }
311 }
312
314 // Function loads a file with saved filter matrix
315 // File can contain multiple matrices - all are loaded
316 // Structure of a file is following:
317 //
318 // Matrix 2 2
319 // 3 4
320 // 1 2
321 //
322 // First row contains keyword Matrix with specified dimensions, the other rows contains values
323 // After this, another header can follow with second matrix
324 // @param filename File name
325 // @return True, if loaded successfully
327 template <class Mesh, class MatrixT>
328 bool OMFilter<Mesh, MatrixT>::LoadFile(std::string filename)
329 {
330 std::ifstream file;
331 file.open(filename);
332
333 // check if file is open
334 if (!file.is_open()) return false;
335 m_filterKernel.clear();
336 m_numKernels = 0;
337
338 // while not eof, we read
339 while (!file.eof())
340 {
341 std::string header;
342 file >> header;
343
344 // check header
345 if (header != "Matrix") return false;
346 int rows, cols;
347 file >> rows;
348 file >> cols;
349
350 // check rows and cols information
351 if (rows <= 0 || cols <= 0) return false;
352
353 m_filterKernel.push_back(MatrixT(rows, cols));
354
355 // read matrix
356 for (int r = 0; r < rows; ++r)
357 for (int c = 0; c < rows; ++c)
358 {
359 if (file.eof()) return false;
360 file >> m_filterKernel.back()(r, c);
361 }
362 ++m_numKernels;
363 // if there is not end of file, continue with another kernel
364 }
365 file.close();
366 m_loaded = true;
367 if (m_filterKernel.size() > 0)
368 {
369 int rows = m_filterKernel[0].rows();
370 int cols = m_filterKernel[0].cols();
371 for (unsigned int i = 0; i < m_filterKernel.size(); ++i)
372 {
373 if (rows != m_filterKernel[i].rows() || cols != m_filterKernel[i].cols()) return false;
374 }
375 }
376 return true;
377 }
378
380 // Function saves internal matrices into file
381 // @param filename File name
382 // @return True, if saved successfully
384 template <class Mesh, class MatrixT>
385 bool OMFilter<Mesh, MatrixT>::SaveFile(std::string filename)
386 {
387 std::ofstream file;
388 file.open(filename);
389
390 // check if file is open
391 if (!file.is_open() || !m_loaded) return false;
392
393 // write all kernels
394 for (unsigned int i = 0; i < m_numKernels; ++i)
395 {
396 // header + dimensions
397 file << "Matrix ";
398 file << m_filterKernel[i].rows() << " "<< m_filterKernel[i].cols() << std::endl;
399
400 // each cell
401 for (int r = 0; r < m_filterKernel[i].rows(); ++r)
402 {
403 for (int c = 0; c < m_filterKernel[i].cols(); ++c)
404 file << m_filterKernel[i](r, c) << " ";
405 file << std::endl;
406 }
407 file << std::endl;
408 }
409 // close file
410 file.close();
411 return true;
412 }
413
414 #endif // _OM_FILTER_HXX_