ViSP  2.8.0
vpMomentObject.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMomentObject.cpp 4056 2013-01-05 13:04:42Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Object input structure used by moments.
36  *
37  * Authors:
38  * Filip Novotny
39  *
40  *****************************************************************************/
41 
42 #include <visp/vpMomentBasic.h>
43 #include <visp/vpMomentObject.h>
44 #include <visp/vpCameraParameters.h>
45 #include <visp/vpPixelMeterConversion.h>
46 #include <visp/vpConfig.h>
47 #include <cmath>
48 #include <limits>
49 #ifdef VISP_HAVE_OPENMP
50 #include <omp.h>
51 #endif
52 #include <cassert>
53 
63 double vpMomentObject::calc_mom_polygon(unsigned int p, unsigned int q, const std::vector<vpPoint>& points){
64  unsigned int i,k,l;
65  double den,mom,s;
66  double x_k;
67  double x_p_k;
68  double y_l;
69  double y_q_l;
70 
71  den = static_cast<double>( (p+q+2)*(p+q+1)*vpMath::comb(p+q,p) );
72 
73  mom = 0.0;
74  for (i=1;i<=points.size()-1;i++)
75  {
76  s = 0.0;
77  x_k=1;
78  for (k=0;k<=p;k++)
79  {
80  y_l=1;
81  x_p_k = pow(points[i-1].get_x(), (int)(p-k));
82  for (l=0;l<=q;l++)
83  {
84  y_q_l=pow(points[i-1].get_y(), (int)(q-l));
85 
86  s += static_cast<double>(
87  vpMath::comb(k+l,l)
88  *vpMath::comb(p+q-k-l,q-l)
89  *x_k
90  *x_p_k
91  *y_l
92  *y_q_l );
93 
94  y_l*=points[i].get_y();
95 
96  }
97  x_k*=points[i].get_x();
98 
99  }
100 
101  s *= ((points[i-1].get_x())*(points[i].get_y())-(points[i].get_x())*(points[i-1].get_y()));
102  mom += s;
103  }
104  mom /= den;
105  return(mom);
106 }
107 
121 void vpMomentObject::cacheValues(std::vector<double>& cache,double x, double y){
122  cache[0]=1;
123 
124  for(register unsigned int i=1;i<order;i++)
125  cache[i]=cache[i-1]*x;
126 
127  for(register unsigned int j=order;j<order*order;j+=order)
128  cache[j]=cache[j-order]*y;
129 
130  for(register unsigned int j=1;j<order;j++){
131  for(register unsigned int i=1;i<order-j;i++){
132  cache[j*order+i] = cache[j*order]*cache[i];
133  }
134  }
135 }
136 
209 void vpMomentObject::fromVector(std::vector<vpPoint>& points){
211  if(
212  std::abs(points.rbegin()->get_x()-points.begin()->get_x())>std::numeric_limits<double>::epsilon() ||
213  std::abs(points.rbegin()->get_y()-points.begin()->get_y())>std::numeric_limits<double>::epsilon()
214  ){
215  points.resize(points.size()+1);
216  points[points.size()-1] = points[0];
217  }
218  for(register unsigned int j=0;j<order*order;j++){
219  values[j]=calc_mom_polygon(j%order,j/order,points);
220  }
221  }else{
222  std::vector<double> cache(order*order,0.);
223  values.assign(order*order,0);
224  for(register unsigned int i=0;i<points.size();i++){
225  cacheValues(cache,points[i].get_x(),points[i].get_y());
226  for(register unsigned int j=0;j<order;j++){
227  for(register unsigned int k=0;k<order-j;k++){
228  values[j*order+k]+=cache[j*order+k];
229  }
230  }
231  }
232  }
233 }
234 
264 void vpMomentObject::fromImage(const vpImage<unsigned char>& image, unsigned char threshold, const vpCameraParameters& cam){
265 #ifdef VISP_HAVE_OPENMP
266  #pragma omp parallel shared(threshold)
267  {
268  std::vector<double> curvals(order*order);
269  curvals.assign(order*order,0.);
270  unsigned int i_, j_;
271 
272  #pragma omp for nowait//automatically organize loop counter between threads
273  for(int i=0;i<(int)image.getCols();i++){
274  for(int j=0;j<(int)image.getRows();j++){
275  i_ = static_cast<unsigned int>(i);
276  j_ = static_cast<unsigned int>(j);
277  if(image[j_][i_]>threshold){
278  double x=0;
279  double y=0;
281 
282  double xval=1.;
283  double yval=1.;
284  for(register unsigned int k=0;k<order;k++){
285  xval=1.;
286  for(register unsigned int l=0;l<order-k;l++){
287  curvals[(k*order+l)]+=(xval*yval);
288  xval*=x;
289  }
290  yval*=y;
291  }
292  }
293  }
294  }
295 
296  #pragma omp master //only set this variable in master thread
297  {
298  values.assign(order*order, 0.);
299  }
300 
301  #pragma omp barrier
302 
303  for(register unsigned int k=0;k<order;k++){
304  for(register unsigned int l=0;l<order-k;l++){
305  #pragma omp atomic
306  values[k*order+l]+= curvals[k*order+l];
307  }
308  }
309 
310  }
311 
312 #else
313  std::vector<double> cache(order*order,0.);
314  values.assign(order*order,0);
315  for(register unsigned int i=0;i<image.getCols();i++){
316  for(register unsigned int j=0;j<image.getRows();j++){
317  if(image[j][i]>threshold){
318  double x=0;
319  double y=0;
321  cacheValues(cache,x,y);
322  for(register unsigned int k=0;k<order;k++){
323  for(register unsigned int l=0;l<order-k;l++){
324  values[k*order+l]+=cache[k*order+l];
325  }
326  }
327  }
328  }
329  }
330 #endif
331 }
332 
333 
334 
346 vpMomentObject::vpMomentObject(unsigned int order) : order(order+1),type(DENSE_FULL_OBJECT){
347  values.resize((order+1)*(order+1)*12);
348  values.assign((order+1)*(order+1)*12,0);
349 }
350 
370 std::vector<double>& vpMomentObject::get() {
371  return values;
372 
373 }
374 
381 double vpMomentObject::get(unsigned int i, unsigned int j) const {
382  assert(i+j<=getOrder());
383  if(i+j>=order) throw vpException(vpException::badValue,"The requested value has not been computed, you should specify a higher order.");
384 
385  return values[j*order+i];
386 }
387 
403 std::ostream & operator<<(std::ostream & os, const vpMomentObject& m){
404  for(unsigned int i = 0;i<m.values.size();i++){
405 
406  if(i%(m.order)==0)
407  os << std::endl;
408 
409  if((i%(m.order)+i/(m.order))<m.order)
410  os << m.values[i] ;
411  else
412  os << "x";
413 
414  os << "\t";
415 
416  }
417 
418  return os;
419 }
unsigned int getCols() const
Definition: vpImage.h:178
vpMomentObject(unsigned int order)
error that can be emited by ViSP classes.
Definition: vpException.h:75
Class for generic objects.
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Point coordinates conversion from pixel coordinates to normalized coordinates in meter...
void fromImage(const vpImage< unsigned char > &image, unsigned char threshold, const vpCameraParameters &cam)
unsigned int getRows() const
Definition: vpImage.h:169
std::vector< double > & get()
Generic class defining intrinsic camera parameters.
VISP_EXPORT std::ostream & operator<<(std::ostream &os, const vpImagePoint &ip)
Definition: vpImagePoint.h:529
void fromVector(std::vector< vpPoint > &points)
static long double comb(unsigned int n, unsigned int p)
Definition: vpMath.h:213
unsigned int getOrder() const