示例#1
0
void NonRigid::computeInflateDir(VectorXf &p_vec, VectorXf &g_vec)
{
    VectorXf arap_g = g_vec;
    VectorXf inflate_g = g_vec;
    VectorXf userCrsp_g = g_vec;
    double f_e = 0;
    computeArap(p_vec, arap_g);
    computeUserCrsp(p_vec, userCrsp_g);

    Vector3f cur_v(0,0,0);
    Vector3f cur_g(0,0,0);
    size_t P_Num = p_vec.size()/3;
    for (size_t i = 0; i < P_Num; ++i)
    {
        cur_v << p_vec(i + 0*P_Num), p_vec(i + 1*P_Num), p_vec(i + 2*P_Num);
        if (computeVertexGrad(cur_v, cur_g) > 0.0)
        {
            inflate_g(i + 0*P_Num) = cur_g(0);
            inflate_g(i + 1*P_Num) = cur_g(1);
            inflate_g(i + 2*P_Num) = cur_g(2);
        }
        else
        {
            inflate_g(i + 0*P_Num) = -P_Prime_N(0, i);
            inflate_g(i + 1*P_Num) = -P_Prime_N(1, i);
            inflate_g(i + 2*P_Num) = -P_Prime_N(2, i);
        }

    }

    g_vec = lamd_inflate*inflate_g + lamd_arap*arap_g + lamd_userCrsp*userCrsp_g;
    g_vec.normalize();
}
示例#2
0
double NonRigid::computeGradEnergy(VectorXf &p_vec, VectorXf &g_vec)
{
    VectorXf arap_g = g_vec;
    VectorXf dist_g = g_vec;
    VectorXf userCrsp_g = g_vec;
    double f_e = 0;
    computeArap(p_vec, arap_g);

    f_e += computeDistEnergy(p_vec, dist_g);

    computeUserCrsp(p_vec, userCrsp_g);

    g_vec = lamd_dist*dist_g + lamd_arap*arap_g + lamd_userCrsp*userCrsp_g;
    g_vec.normalize();
    return f_e;
}
示例#3
0
bool Energy::iterate() {
    if (step_size <= step_size_end) { return true; }

    step_size = update_step_size(step_size, step_size_end);
    if (step_size <= step_size_end) { return true; }

    // every coordinate of a vector will all equal coordinates and a norm of
    // step_size has the following value:
    float dparam = step_size;

    float energy_now = calc_energy();

    VectorXf *diff = new VectorXf(numparams);
    VectorXf *chg  = new VectorXf(numparams);

    for (int np = 0; np < numparams; np++) {
        (*diff)[np] = 0.0f;
    }

    bool *done = new bool[numparams];

    for (int np = 0; np < numparams; np++) {
        (*chg )[np] = 0;
        done[np] = false;

        (*diff)[np] = dparam;
        apply_change(diff);
        float energy_large = calc_energy();

        (*diff)[np] = -2 * dparam;
        apply_change(diff);
        float energy_small = calc_energy();

        (*diff)[np] = dparam;
        apply_change(diff);

        (*diff)[np] = 0;

        if (!boost::math::isnan(energy_small) &&
            !boost::math::isnan(energy_large)) {
            if (!is_improvement(energy_now, energy_large) &&
                !is_improvement(energy_now, energy_small)) {
                if (step_size <= step_size_end) { done[np] = true; }
                continue;
            }

            (*chg)[np] = energy_small - energy_large;
        }
        else {
            (*chg)[np] = 0.0f;
        }
    }

    bool chg_all_zeros = true;
    for (int np = 0; np < numparams; np++) {
        chg_all_zeros = chg_all_zeros && ((*chg)[np] == 0.0f);
    }

    if (!chg_all_zeros) {
        chg->normalize();
        (*chg) *= step_size * speed;
        apply_change(chg);

        float energy_new = calc_energy();

        if (!is_improvement(energy_now, energy_new) &&
            step_size > step_size_end) {
            (*chg) *= -1;
            apply_change(chg);
            step_size /= 2;
        }

        log_iteration(step_size);
    }
    else if (step_size > step_size_end) {
        step_size /= 2;
    }

    log_energies();
    
    delete chg ;
    delete diff;

    for (int np = 0; np < numparams; np++) {
        if (!done[np]) { delete done; return false; }
    }
    delete done;
    return true;
}
IplImage* CloudProjection::computeProjection(const sensor_msgs::PointCloud& data,
					     const std::vector<int>& interest_region_indices)
{
  // -- Put cluster points into matrix form.
  MatrixXf points(interest_region_indices.size(), 3);
  for(size_t i=0; i<interest_region_indices.size(); ++i) {
    points(i, 0) = data.points[interest_region_indices[i]].x;
    points(i, 1) = data.points[interest_region_indices[i]].y;
    points(i, 2) = data.points[interest_region_indices[i]].z;
  }

  // -- Subtract off the mean and flatten to z=0 to prepare for PCA.
  MatrixXf X = points;
  X.col(2) = VectorXf::Zero(X.rows());
  VectorXf pt_mean = X.colwise().sum() / (float)X.rows();
  for(int i=0; i<X.rows(); ++i) {
    X.row(i) -= pt_mean.transpose();
  }
  MatrixXf Xt = X.transpose();
  
  // -- Find the long axis.
  // Start with a random vector.
  VectorXf pc = VectorXf::Zero(3);
  pc(0) = 1; //Chosen by fair dice roll.
  pc(1) = 1;
  pc.normalize();
  
  // Power method.
  VectorXf prev = pc;
  double thresh = 1e-4;
  int ctr = 0;
  while(true) { 
    prev = pc;
    pc =  Xt * (X * pc);
    pc.normalize();
    ctr++;
    if((pc - prev).norm() < thresh)
      break;
  }
  assert(abs(pc(2)) < 1e-4);
  
  // -- Find the short axis.
  VectorXf shrt = VectorXf::Zero(3);
  shrt(1) = -pc(0);
  shrt(0) = pc(1);
  assert(abs(shrt.norm() - 1) < 1e-4);
  assert(abs(shrt.dot(pc)) < 1e-4);
  
  // -- Build the basis of normalized coordinates.
  MatrixXf basis = MatrixXf::Zero(3,3);
  basis.col(0) = pc;
  basis.col(1) = shrt;
  basis(2,2) = -1.0;
  assert(abs(basis.col(0).dot(basis.col(1))) < 1e-4);
  assert(abs(basis.col(0).norm() - 1) < 1e-4);
  assert(abs(basis.col(1).norm() - 1) < 1e-4);
  assert(abs(basis.col(2).norm() - 1) < 1e-4);


  // -- Put the cluster into normalized coordinates, and choose which axis to project on.
  MatrixXf projected_basis(3, 2);
  if(axis_ == 0) { 
    projected_basis.col(0) = basis.col(1);
    projected_basis.col(1) = basis.col(2);
  }
  else if(axis_ == 1) { 
    projected_basis.col(0) = basis.col(0);
    projected_basis.col(1) = basis.col(2);
  }
  else if(axis_ == 2) { 
    projected_basis.col(0) = basis.col(0);
    projected_basis.col(1) = basis.col(1);
  }
  MatrixXf projected = points * projected_basis;
    
  // -- Transform into pixel units.
  for(int i=0; i<projected.rows(); ++i) {
    projected(i, 0) *= pixels_per_meter_;
    projected(i, 1) *= pixels_per_meter_;
  }

  // -- Find min and max of u and v.  TODO: noise sensitivity?
  float min_v = FLT_MAX;
  float min_u = FLT_MAX;
  float max_v = -FLT_MAX;
  float max_u = -FLT_MAX;
  for(int i=0; i<projected.rows(); ++i) {
    float u = projected(i, 0);
    float v = projected(i, 1);
    if(u < min_u)
      min_u = u;
    if(u > max_u)
      max_u = u;
    if(v < min_v)
      min_v = v;
    if(v > max_v)
      max_v = v;
  }

  // -- Shift the origin based on {u,v}_offset_pct. 
  //    u_offset_pct_ is the percent of the way from min_u to max_u that the
  //    u_offset should be set to.  If this makes the window fall outside min_u or max_u,
  //    then shift the window so that it is inside.
  float u_offset = u_offset_pct_ * (max_u - min_u) + min_u;
  float v_offset = v_offset_pct_ * (max_v - min_v) + min_v;

  if(u_offset_pct_ > 0.5 && u_offset + cols_ / 2 > max_u)
    u_offset = max_u - cols_ / 2 + 1;
  if(u_offset_pct_ < 0.5 && u_offset - cols_ / 2 < min_u)
    u_offset = min_u + cols_ / 2 - 1;

  if(v_offset_pct_ > 0.5 && v_offset + rows_ / 2 > max_v)
    v_offset = max_v - rows_ / 2 + 1;
  if(v_offset_pct_ < 0.5 && v_offset - rows_ / 2 < min_v)
    v_offset = min_v + rows_ / 2 - 1;

  
  for(int i=0; i<projected.rows(); ++i) {
    projected(i, 0) -= u_offset - (float)cols_ / 2.0;
    projected(i, 1) -= v_offset - (float)rows_ / 2.0;
  }
  
  // -- Fill the IplImages.
  assert(sizeof(float) == 4);
  IplImage* acc = cvCreateImage(cvSize(cols_, rows_), IPL_DEPTH_32F, 1);
  IplImage* img = cvCreateImage(cvSize(cols_, rows_), IPL_DEPTH_32F, 1);
  cvSetZero(acc);
  cvSetZero(img);
  for(int i=0; i<projected.rows(); ++i) {
    int row = floor(projected(i, 1));
    int col = floor(projected(i, 0));
    if(row >= rows_ || col >= cols_ || row < 0 || col < 0)
      continue;

    float intensity = (float)data.channels[0].values[interest_region_indices[i]] / 255.0 * (3.0 / 4.0) + 0.25;
    //cout << i << ": " << interest_region_indices[i] << "/" << data.channels[0].values.size() << " " << (float)data.channels[0].values[interest_region_indices[i]] << " " << intensity << endl;
    assert(interest_region_indices[i] < (int)data.channels[0].values.size() && (int)interest_region_indices[i] >= 0);
    assert(intensity <= 1.0 && intensity >= 0.0);
    ((float*)(img->imageData + row * img->widthStep))[col] += intensity;
    ((float*)(acc->imageData + row * acc->widthStep))[col]++;
  }
  
  // -- Normalize by the number of points falling in each pixel.
  for(int v=0; v<rows_; ++v) {
    float* img_ptr = (float*)(img->imageData + v * img->widthStep);
    float* acc_ptr = (float*)(acc->imageData + v * acc->widthStep);
    for(int u=0; u<cols_; ++u) {
      if(*acc_ptr == 0)
	*img_ptr = 0;
      else
	*img_ptr = *img_ptr / *acc_ptr;

      img_ptr++;
      acc_ptr++;
    }
  }

  // -- Clean up and return.
  cvReleaseImage(&acc);
  return img;  
}
MatrixXf D3DCloudOrienter::orientCloud(const sensor_msgs::PointCloud& data,
				    const std::vector<int>& interest_region_indices)
{
  // -- Put cluster points into matrix form.
  MatrixXf points(interest_region_indices.size(), 3);
  for(size_t i=0; i<interest_region_indices.size(); ++i) {
    points(i, 0) = data.points[interest_region_indices[i]].x;
    points(i, 1) = data.points[interest_region_indices[i]].y;
    points(i, 2) = data.points[interest_region_indices[i]].z;
  }

  // -- Subtract off the mean of the points.
  VectorXf pt_mean = points.colwise().sum() / (float)points.rows();
  for(int i=0; i<points.rows(); ++i)
    points.row(i) -= pt_mean.transpose();

  // -- Flatten to z == 0.
  MatrixXf X = points;
  X.col(2) = VectorXf::Zero(X.rows());
  MatrixXf Xt = X.transpose();
  
  // -- Find the long axis.
  // Start with a random vector.
  VectorXf pc = VectorXf::Zero(3);
  pc(0) = 1; //Chosen by fair dice roll.
  pc(1) = 1;
  pc.normalize();
  
  // Power method.
  VectorXf prev = pc;
  double thresh = 1e-4;
  int ctr = 0;
  while(true) { 
    prev = pc;
    pc =  Xt * (X * pc);
    pc.normalize();
    ctr++;
    if((pc - prev).norm() < thresh)
      break;
  }
  assert(abs(pc(2)) < 1e-4);
  
  // -- Find the short axis.
  VectorXf shrt = VectorXf::Zero(3);
  shrt(1) = -pc(0);
  shrt(0) = pc(1);
  assert(abs(shrt.norm() - 1) < 1e-4);
  assert(abs(shrt.dot(pc)) < 1e-4);
  
  // -- Build the basis of normalized coordinates.
  MatrixXf basis = MatrixXf::Zero(3,3);
  basis.col(0) = pc;
  basis.col(1) = shrt;
  basis(2,2) = 1.0;
  assert(abs(basis.col(0).dot(basis.col(1))) < 1e-4);
  assert(abs(basis.col(0).norm() - 1) < 1e-4);
  assert(abs(basis.col(1).norm() - 1) < 1e-4);
  assert(abs(basis.col(2).norm() - 1) < 1e-4);

  // -- Rotate and return.
  MatrixXf oriented = points * basis;
  return oriented;
}
void CloudOrienter::_compute() {
    assert(input_cloud_);
    assert(input_intensities_);
    assert(!output_cloud_);
    //cout << input_intensities_->rows() << " " << input_cloud_->rows() << endl;
    assert(input_cloud_->rows() == input_intensities_->rows());
    assert(input_cloud_->rows() > 2);

    // -- Subtract off the mean of the points.
    MatrixXf& points = *input_cloud_;
    VectorXf pt_mean = points.colwise().sum() / (float)points.rows();
    for(int i=0; i<points.rows(); ++i)
        points.row(i) -= pt_mean.transpose();

    // -- Flatten to z == 0.
    MatrixXf X = points;
    X.col(2) = VectorXf::Zero(X.rows());
    MatrixXf Xt = X.transpose();

    // -- Find the long axis.
    // Start with a random vector.
    VectorXf pc = VectorXf::Zero(3);
    pc(0) = 1; //Chosen by fair dice roll.
    pc(1) = 1;
    pc.normalize();

    // Power method.
    VectorXf prev = pc;
    double thresh = 1e-4;
    int ctr = 0;
    while(true) {
        prev = pc;
        pc =  Xt * (X * pc);
        pc.normalize();
        ctr++;
        if((pc - prev).norm() < thresh)
            break;
        // -- In some degenerate cases, it is possible for the vector
        //    to never settle down to the first PC.
        if(ctr > 100)
            break;

    }
    assert(abs(pc(2)) < 1e-4);

    // -- Find the short axis.
    VectorXf shrt = VectorXf::Zero(3);
    shrt(1) = -pc(0);
    shrt(0) = pc(1);
    assert(abs(shrt.norm() - 1) < 1e-4);
    assert(abs(shrt.dot(pc)) < 1e-4);

    // -- Build the basis of normalized coordinates.
    MatrixXf basis = MatrixXf::Zero(3,3);
    basis.col(0) = pc;
    basis.col(1) = shrt;
    basis(2,2) = 1.0;
    assert(abs(basis.col(0).dot(basis.col(1))) < 1e-4);
    assert(abs(basis.col(0).norm() - 1) < 1e-4);
    assert(abs(basis.col(1).norm() - 1) < 1e-4);
    assert(abs(basis.col(2).norm() - 1) < 1e-4);

    // -- Rotate and set the output_cloud_.
    output_cloud_ = shared_ptr<MatrixXf>(new MatrixXf);
    *output_cloud_ = points * basis;
    assert(output_cloud_->rows() == input_cloud_->rows());
}