float RangeImageBorderExtractor::getNeighborDistanceChangeScore(
    const RangeImageBorderExtractor::LocalSurface& local_surface,
    int x, int y, int offset_x, int offset_y, int pixel_radius) const
{
  const PointWithRange& point = range_image_->getPoint(x, y);
  PointWithRange neighbor;
  range_image_->get1dPointAverage(x+offset_x, y+offset_y, offset_x, offset_y, pixel_radius, neighbor);
  if (pcl_isinf(neighbor.range))
  {
    if (neighbor.range < 0.0f)
      return 0.0f;
    else
    {
      //cout << "INF edge -> Setting to 1.0\n";
      return 1.0f;  // TODO: Something more intelligent
    }
  }
  
  float neighbor_distance_squared = squaredEuclideanDistance(neighbor, point);
  if (neighbor_distance_squared <= local_surface.max_neighbor_distance_squared)
    return 0.0f;
  float ret = 1.0f - sqrtf(local_surface.max_neighbor_distance_squared / neighbor_distance_squared);
  if (neighbor.range < point.range)
    ret = -ret;
  return ret;
}
bool RangeImageBorderExtractor::calculateMainPrincipalCurvature(int x, int y, int radius, int step_size, float& magnitude, Eigen::Vector3f& main_direction) const
{
  magnitude = 0.0f;
  int index = y*range_image_->width+x;
  LocalSurface* local_surface = surface_structure_[index];
  if (local_surface==NULL)
    return false;
  const PointWithRange& point = range_image_->getPointNoCheck(x,y);
  float max_distance_squared = 2.0f*local_surface->max_neighbor_distance_squared;
  
  Eigen::Vector3f& normal = local_surface->normal_no_jumps;
  
  Eigen::Matrix3f to_tangent_plane = Eigen::Matrix3f::Identity() - normal*normal.transpose();
  
  VectorAverage3f vector_average;
  for (int y2=y-radius; y2<=y+radius; y2+=step_size)
  {
    for (int x2=x-radius; x2<=x+radius; x2+=step_size)
    {
      if (!range_image_->isValid(x2,y2))
        continue;
      int index2 = y2*range_image_->width + x;
      const PointWithRange& point2 = range_image_->getPoint(index2);
      LocalSurface* local_surface2 = surface_structure_[index2];
      if (local_surface2==NULL)
        continue;
      Eigen::Vector3f& normal2 = local_surface2->normal_no_jumps;
      float distance_squared = squaredEuclideanDistance(point, point2);
      if (distance_squared > max_distance_squared)
        continue;
      vector_average.add(to_tangent_plane*normal2);
    }
  }
  if (vector_average.getNoOfSamples() < 3)
    return false;
  
  Eigen::Vector3f eigen_values, eigen_vector1, eigen_vector2;
  vector_average.doPCA(eigen_values, eigen_vector1, eigen_vector2, main_direction);
  //magnitude = sqrtf(eigen_values[2]);
  magnitude = eigen_values[2];
  magnitude = 1.0f - powf(1.0f-magnitude, 3);
  //magnitude += magnitude - powf(magnitude,2);
  //magnitude += magnitude - powf(magnitude,2);
  
  //magnitude = sqrtf(local_surface->eigen_values[0]/local_surface->eigen_values.sum());
  //magnitude = sqrtf(local_surface->eigen_values_no_jumps[0]/local_surface->eigen_values_no_jumps.sum());

  //if (surface_structure_[y*range_image_->width+x+1]==NULL||surface_structure_[y*range_image_->width+x-1]==NULL)
  //{
    //magnitude = -std::numeric_limits<float>::infinity ();
    //return false;
  //}
  //float angle2 = acosf(surface_structure_[y*range_image_->width+x+1]->normal.dot(local_surface->normal)),
        //angle1 = acosf(surface_structure_[y*range_image_->width+x-1]->normal.dot(local_surface->normal));
  //magnitude = angle2-angle1;
  return true;
}
Esempio n. 3
0
bool HierarchicalClustering::train_(MatrixFloat &data){
	
	trained = false;
    clusters.clear();
    distanceMatrix.clear();
    
    if( data.getNumRows() == 0 || data.getNumCols() == 0 ){
		return false;
	}
	
    //Set the rows and columns
    M = data.getNumRows();
	N = data.getNumCols();
    
    //Build the distance matrix
    distanceMatrix.resize(M,M);

    //Build the distance matrix
    for(UINT i=0; i<M; i++){
        for(UINT j=0; j<M; j++){
            if( i== j ) distanceMatrix[i][j] = grt_numeric_limits< Float >::max();
            else{
                distanceMatrix[i][j] = squaredEuclideanDistance(data[i], data[j]);
            }
        }
    }

    //Build the initial clusters, at the start each sample gets its own cluster
    UINT uniqueClusterID = 0;
    Vector< ClusterInfo > clusterData(M);
    for(UINT i=0; i<M; i++){
        clusterData[i].uniqueClusterID = uniqueClusterID++;
        clusterData[i].addSampleToCluster(i);
    }
    
    trainingLog << "Starting clustering..." << std::endl;
    
    //Create the first cluster level, each sample is it's own cluster
    UINT level = 0;
    ClusterLevel newLevel;
    newLevel.level = level;
    for(UINT i=0; i<M; i++){
        newLevel.clusters.push_back( clusterData[i] );
    }
    clusters.push_back( newLevel );
    
    //Move to level 1 and start the search
    level++;
    bool keepClustering = true;
    
    while( keepClustering ){
        
        //Find the closest two clusters within the cluster data
        Float minDist = grt_numeric_limits< Float >::max();
        Vector< Vector< UINT > > clusterPairs;
        UINT K = (UINT)clusterData.size();
        for(UINT i=0; i<K; i++){
            for(UINT j=0; j<K; j++){
                if( i != j ){
                    Float dist = computeClusterDistance( clusterData[i], clusterData[j]  );
             
                    if( dist < minDist ){
                        minDist = dist;
                        Vector< UINT > clusterPair(2);
                        clusterPair[0] = i;
                        clusterPair[1] = j;
                        clusterPairs.clear();
                        clusterPairs.push_back( clusterPair );
                    }
                    
                }
            }
        }
        
        if( minDist == grt_numeric_limits< Float >::max() ){
            keepClustering = false;
            warningLog << "train_(MatrixFloat &data) - Failed to find any cluster at level: " << level << std::endl;
            return false;
        }else{
        
            //Merge the two closest clusters together and create a new level
            ClusterLevel newLevel;
            newLevel.level = level;
            
            //Create the new cluster
            ClusterInfo newCluster;
            newCluster.uniqueClusterID = uniqueClusterID++;
            
            const UINT numClusterPairs = clusterPairs.getSize();
            
            for(UINT k=0; k<numClusterPairs; k++){
                //Add all the samples in the first cluster to the new cluster
                UINT numSamplesInClusterA = clusterData[ clusterPairs[k][0] ].getNumSamplesInCluster();
                for(UINT i=0; i<numSamplesInClusterA; i++){
                    UINT index = clusterData[ clusterPairs[k][0] ][ i ];
                    newCluster.addSampleToCluster( index );
                }
                
                //Add all the samples in the second cluster to the new cluster
                UINT numSamplesInClusterB = clusterData[ clusterPairs[k][1] ].getNumSamplesInCluster();
                for(UINT i=0; i<numSamplesInClusterB; i++){
                    UINT index = clusterData[ clusterPairs[k][1] ][ i ];
                    newCluster.addSampleToCluster( index );
                }
                
                //Compute the cluster variance
                newCluster.clusterVariance = computeClusterVariance( newCluster, data );
                
                //Remove the two cluster pairs (so they will not be used in the next search
                UINT idA = clusterData[ clusterPairs[k][0] ].getUniqueClusterID();
                UINT idB = clusterData[ clusterPairs[k][1] ].getUniqueClusterID();
                UINT numRemoved = 0;
                Vector< ClusterInfo >::iterator iter = clusterData.begin();
                while( iter != clusterData.end() ){
                    if( iter->getUniqueClusterID() == idA || iter->getUniqueClusterID() == idB ){
                        iter = clusterData.erase( iter );
                        if( ++numRemoved >= 2 ) break;
                    }else iter++;
                }
            }
            
            //Add the merged cluster to the clusterData
            clusterData.push_back( newCluster );
            
            //Add the new level and cluster data to the main cluster buffer
            newLevel.clusters.push_back( newCluster );
            
            clusters.push_back( newLevel );
            
            //Update the level
            level++;
        }
        
        //Check to see if we should stop clustering
        if( level >= M ){
            keepClustering = false;
        }
        
        if( clusterData.size() == 0 ){
            keepClustering = false;
        }
        
        trainingLog << "Cluster level: " << level << " Number of clusters: " << clusters.back().getNumClusters() << std::endl;
    }
    
    //Flag that the model is trained
    trained = true;
    
    //Setup the cluster labels
    clusterLabels.resize(numClusters);
    for(UINT i=0; i<numClusters; i++){
        clusterLabels[i] = i+1;
    }
    clusterLikelihoods.resize(numClusters,0);
    clusterDistances.resize(numClusters,0);

	return true;
}