Пример #1
0
    void
    cloud_callback (const CloudConstPtr& cloud)
    {
      FPS_CALC ("cloud callback");
      boost::mutex::scoped_lock lock (cloud_mutex_);
      cloud_ = cloud;
      search_.setInputCloud (cloud);

      // Subsequent frames are segmented by "tracking" the parameters of the previous frame
      // We do this by using the estimated inliers from previous frames in the current frame, 
      // and refining the coefficients

      if (!first_frame_)
      {
        if (!plane_indices_ || plane_indices_->indices.empty () || !search_.getInputCloud ())
        {
          PCL_ERROR ("Lost tracking. Select the object again to continue.\n");
          first_frame_ = true;
          return;
        }
        SACSegmentation<PointT> seg;
        seg.setOptimizeCoefficients (true);
        seg.setModelType (SACMODEL_PLANE);
        seg.setMethodType (SAC_RANSAC);
        seg.setMaxIterations (1000);
        seg.setDistanceThreshold (0.01);
        seg.setInputCloud (search_.getInputCloud ());
        seg.setIndices (plane_indices_);
        ModelCoefficients coefficients;
        PointIndices inliers;
        seg.segment (inliers, coefficients);

        if (inliers.indices.empty ())
        {
          PCL_ERROR ("No planar model found. Select the object again to continue.\n");
          first_frame_ = true;
          return;
        }

        // Visualize the object in 3D...
        CloudPtr plane_inliers (new Cloud);
        pcl::copyPointCloud (*search_.getInputCloud (), inliers.indices, *plane_inliers);
        if (plane_inliers->points.empty ())
        {
          PCL_ERROR ("No planar model found. Select the object again to continue.\n");
          first_frame_ = true;
          return;
        }
        else
        {
          plane_.reset (new Cloud);

          // Compute the convex hull of the plane
          ConvexHull<PointT> chull;
          chull.setDimension (2);
          chull.setInputCloud (plane_inliers);
          chull.reconstruct (*plane_);
        }
      }
    }
Пример #2
0
static void DrawHull(const ConvexHull& hull)
{
	const Point* ConvexVerts = hull.GetVerts();
	udword NbPolys = hull.GetNbPolygons();
//	printf("NbPolys: %d\n", NbPolys);
	for(udword i=0;i<NbPolys;i++)
	{
		const HullPolygon& PolygonData = hull.GetPolygon(i);
		glNormal3f(PolygonData.mPlane.n.x, PolygonData.mPlane.n.y, PolygonData.mPlane.n.z);

		const udword NbVertsInPoly = PolygonData.mNbVerts;
		const udword NbTris = NbVertsInPoly - 2;
		const udword* Indices = PolygonData.mVRef;
		udword Offset = 1;
		for(udword i=0;i<NbTris;i++)
		{
			const udword VRef0 = Indices[0];
			const udword VRef1 = Indices[Offset];
			const udword VRef2 = Indices[Offset+1];
			Offset++;

			const Point av3LineEndpoints[] = {ConvexVerts[VRef0], ConvexVerts[VRef1], ConvexVerts[VRef2]};
			glEnableClientState(GL_VERTEX_ARRAY);
			glVertexPointer(3, GL_FLOAT, sizeof(Point), &av3LineEndpoints[0].x);
			glDrawArrays(GL_TRIANGLES, 0, 3);
			glDisableClientState(GL_VERTEX_ARRAY);
		}
	}
}
void reconstructMesh(const PointCloud<PointXYZ>::ConstPtr &cloud,
  PointCloud<PointXYZ> &output_cloud, std::vector<Vertices> &triangles)
{
  boost::shared_ptr<std::vector<int> > indices(new std::vector<int>);
  indices->resize(cloud->points.size ());
  for (size_t i = 0; i < indices->size (); ++i) { (*indices)[i] = i; }

  pcl::search::KdTree<PointXYZ>::Ptr tree(new pcl::search::KdTree<PointXYZ>);
  tree->setInputCloud(cloud);

  PointCloud<PointXYZ>::Ptr mls_points(new PointCloud<PointXYZ>);
  PointCloud<PointNormal>::Ptr mls_normals(new PointCloud<PointNormal>);
  MovingLeastSquares<PointXYZ, PointNormal> mls;

  mls.setInputCloud(cloud);
  mls.setIndices(indices);
  mls.setPolynomialFit(true);
  mls.setSearchMethod(tree);
  mls.setSearchRadius(0.03);
  
  mls.process(*mls_normals);
  
  ConvexHull<PointXYZ> ch;
  
  ch.setInputCloud(mls_points);
  ch.reconstruct(output_cloud, triangles);
}
Пример #4
0
ConvexHull inset_ch(ConvexHull ch, double dist) {
    ConvexHull ret;
    for(unsigned i = 0; i < ch.size(); i++) {
        Point bisect = (rot90(ch[i+1] - ch[i]));
        ret.merge(unit_vector(bisect)*dist+ch[i]);
        ret.merge(unit_vector(bisect)*dist+ch[i+1]);
    }
    return ret;
}
bool HeightmapSampling::calculateConvexHull()
{
  ConvexHull < PointXYZ > cv;
  cv.setInputCloud(point_cloud_);
  boost::shared_ptr < PointCloud<PointXYZ> > cv_points;
  cv_points.reset(new PointCloud<PointXYZ> ());
  cv.reconstruct(*cv_points, convex_hull_vertices_);

  convex_hull_points_ = cv_points;

  return true;
}
void COpenCVInterfaceDlg::OnMorphologyConvexhull()
{
	if(mainImage.cols)
	{
		ConvexHull c;
		Mat rez=mainImage.clone();
		mainImage=Filters::gaussianFilter(mainImage,1);
		Scalar meanVal,stdval;

		meanStdDev(mainImage,meanVal,stdval);
		Canny(mainImage,mainImage,meanVal.val[0]*1/3.,meanVal.val[0]);
		//imshow("contours",mainImage);

		vector<std::vector<cv::Point>> contours;
		findContours(mainImage,contours,CV_RETR_LIST,CV_CHAIN_APPROX_NONE,Point(2,2));

		vector<Point> Points;
		//Points.resize(contours.size()*contours[0].size());
		for(int i=0;i<contours.size();i++)
		{
			for(int j=0;j<contours[i].size();j++)
			{
				Points.push_back(contours[i][j]);
			}
		}

		//for(int i=2;i<mainImage.rows-2;i++)
		//{
		//	for(int j=2;j<mainImage.cols-2;j++)
		//	{
		//		if(mainImage.at<uchar>(i,j)==255)
		//			Points.push_back(Point(i,j));
		//	}
		//}	

		std::vector<Point> chull;
		c.graham(Points, chull);

		for(int i=0;i<chull.size()-1;i++)
		{
			line(rez,chull[i],chull[i+1],Scalar(255,255,255),2);
		}

		line(rez,chull[chull.size()-1],chull[0],Scalar(255,255,255),2);
		prelImage=rez.clone();
		ShowResult(prelImage);
	}
	else
		MessageBox("No image loaded");
}
Пример #7
0
ConvexHull findConvexHull(PointSet *pointSet) {

  int pointCount = pointSet->getSize();

  pointSet->sortPointsByAngle();

  if (pointCount <= 3) { // The points are already a convex hull
    ConvexHull hull;
    for (int i = 0; i < pointCount; ++i) {
      hull.addPoint(*pointSet->getPoint(i));
    }
    if (pointCount > 0) {
      hull.addPoint(*pointSet->getPoint(0));
    }
    return hull;
  }

  std::stack<const Point *> candiates;

  const Point *prev;
  const Point *now;

  candiates.push(pointSet->getLastPoint());
  candiates.push(pointSet->getReferencePoint()); // Is always the first (idx 0)
  // element in the point set

  for (int i = 1; i < pointCount;) {
    const Point *point = pointSet->getPoint(i);

    now = candiates.top();
    candiates.pop();
    prev = candiates.top();
    candiates.push(now);

    if (isCCW(prev->pos(), now->pos(), point->pos())) {
      if (point->pos() == now->pos() && USE_CUSTOM_ALGO_FIX) {
        std::cout << "I saved your algorithm" << std::endl;
      } else {
        candiates.push(point);
      }
      ++i;
    } else {
      candiates.pop();
    }
  }

  ConvexHull hull(candiates);
  return hull;
}
Пример #8
0
pointer PCL_CONVEX_HULL (register context *ctx, int n, pointer *argv) {
  pointer in_cloud = argv[0];

  int width = intval(get_from_pointcloud(ctx, in_cloud, K_EUSPCL_WIDTH));
  int height = intval(get_from_pointcloud(ctx, in_cloud, K_EUSPCL_HEIGHT));
  pointer points = get_from_pointcloud(ctx, in_cloud, K_EUSPCL_POINTS);

  PointCloud< Point >::Ptr ptr =
    make_pcl_pointcloud< Point > (ctx, points, NULL, NULL, NULL, width, height);

  PointCloud< Point >::Ptr cloud_hull (new PointCloud<Point>);
  ConvexHull< Point > chull;

  chull.setInputCloud (ptr);
  chull.reconstruct (*cloud_hull);

  return make_pointcloud_from_pcl (ctx, *cloud_hull);
}
Пример #9
0
::testing::AssertionResult HullContainsPoint(ConvexHull const &h, Point const &p) {
    if (h.contains(p)) {
        return ::testing::AssertionSuccess();
    } else {
        return ::testing::AssertionFailure()
            << "Convex hull:\n"
            << h << "\ndoes not contain " << p;
    }
}
Пример #10
0
ConvexHull graham_merge(ConvexHull a, ConvexHull b) {
    ConvexHull result;

    // we can avoid the find pivot step because of top_point_first
    if(b.boundary[0] <= a.boundary[0])
        std::swap(a, b);

    result.boundary = a.boundary;
    result.boundary.insert(result.boundary.end(),
                           b.boundary.begin(), b.boundary.end());

/** if we modified graham scan to work top to bottom as proposed in lect754.pdf we could replace the
 angle sort with a simple merge sort type algorithm. furthermore, we could do the graham scan
 online, avoiding a bunch of memory copies.  That would probably be linear. -- njh*/
    result.angle_sort();
    result.graham_scan();

    return result;
}
Пример #11
0
static ConvexHull* CreateConvexHull(udword nb_verts, const Point* verts)
{
	ConvexHull* CH = ICE_NEW(ConvexHull);
	ASSERT(CH);

	CONVEXHULLCREATE Create;
	Create.NbVerts		= nb_verts;
	Create.Vertices		= verts;
	Create.UnifyNormals	= true;
	Create.PolygonData	= true;

	bool status = CH->Compute(Create);
	ASSERT(status);
	if(!status)
	{
		DELETESINGLE(CH);
	}

	return CH;
}
Пример #12
0
void rot_cal(cairo_t* cr, ConvexHull ch) {
    Point tb = ch.boundary.back();
    for(unsigned i = 0; i < ch.boundary.size(); i++) {
        Point tc = ch.boundary[i];
        Point n = -rot90(tb-tc);
        Point ta = *ch.furthest(n);
        cairo_move_to(cr, tc);
        cairo_line_to(cr, ta);
        tb = tc;
    }
}
Пример #13
0
int convex_plane(eusfloat_t *src, int ssize,
                 eusfloat_t *coeff, eusfloat_t *ret) {

  typedef PointXYZ Point;
  PointCloud<Point>::Ptr cloud_projected (new PointCloud<Point>);
  PointCloud<Point>::Ptr cloud_filtered (new PointCloud<Point>);
  floatvector2pointcloud(src, ssize, 1, *cloud_filtered);

  ModelCoefficients::Ptr coefficients (new ModelCoefficients);
  coefficients->values.resize(4);
  coefficients->values[0] = coeff[0];
  coefficients->values[1] = coeff[1];
  coefficients->values[2] = coeff[2];
  coefficients->values[3] = coeff[3] / 1000.0;

  // Project the model inliers
  ProjectInliers<Point> proj;
  proj.setModelType (SACMODEL_PLANE);
  proj.setInputCloud (cloud_filtered);
  proj.setModelCoefficients (coefficients);
  proj.filter (*cloud_projected);

  // Create a Concave Hull representation of the projected inliers
  PointCloud<Point>::Ptr cloud_hull (new PointCloud<Point>);
  ConvexHull<Point> chull;

  chull.setInputCloud (cloud_projected);
  //chull.setAlpha (alpha);
  chull.reconstruct (*cloud_hull);

  for(int i = 0; i < cloud_hull->points.size(); i++) {
    *ret++ = cloud_hull->points[i].x * 1000.0;
    *ret++ = cloud_hull->points[i].y * 1000.0;
    *ret++ = cloud_hull->points[i].z * 1000.0;
  }

  return cloud_hull->points.size();
}
Пример #14
0
HullState findConvexHullStep(PointSet *pointSet, int simulateUntilStep) {

  int step = 0;

  int pointCount = pointSet->getSize();

  pointSet->sortPointsByAngle();

  //++step;
  if (step++ == simulateUntilStep) // sort done -> update numbers
  {
    return HullState::SortDone(step);
  }

  if (pointCount <= 3) { // The points are already a convex hull
    ConvexHull hull;
    for (int i = 0; i < pointCount; ++i) {
      hull.addPoint(*pointSet->getPoint(i));
    }
    if (pointCount > 0) {
      hull.addPoint(*pointSet->getPoint(0));
    }
    return HullState::HullFound(hull);
  }

  std::stack<const Point *> candiates;

  const Point *prev;
  const Point *now;

  candiates.push(pointSet->getLastPoint());
  candiates.push(pointSet->getReferencePoint()); // Is always the first (idx 0)
                                                 // element in the point set

  //++step;
  if (step++ == simulateUntilStep) // break print candidates
  {
    return HullState::CandidateAdded(candiates, step);
  }

  for (int i = 1; i < pointCount;) {
    const Point *point = pointSet->getPoint(i);

    now = candiates.top();
    candiates.pop();
    prev = candiates.top();
    candiates.push(now);

    if (isCCW(prev->pos(), now->pos(), point->pos())) {
      candiates.push(point);
      // std::cout << "adding " << i << std::endl;
      ++i;

      //++step;
      if (step++ == simulateUntilStep) // break print candidates
      {
        return HullState::CandidateAdded(candiates, step);
      }
    } else {
      //++step;
      if (step++ == simulateUntilStep) // break print candidates
      {
        return HullState::CandidatePoped(candiates, point, step);
      }
      // std::cout << "pop" << std::endl;
      candiates.pop();
    }
  }
  ConvexHull hull(candiates);
  return HullState::HullFound(hull);
}
Пример #15
0
    /** \brief Given a plane, and the set of inlier indices representing it,
      * segment out the object of intererest supported by it. 
      *
      * \param[in] picked_idx the index of a point on the object
      * \param[in] cloud the full point cloud dataset
      * \param[in] plane_indices a set of indices representing the plane supporting the object of interest
      * \param[in] plane_boundary_indices a set of indices representing the boundary of the plane
      * \param[out] object the segmented resultant object 
      */
    void
    segmentObject (int picked_idx, 
                   const CloudConstPtr &cloud, 
                   const PointIndices::Ptr &plane_indices, 
                   const PointIndices::Ptr &plane_boundary_indices, 
                   Cloud &object)
    {
      CloudPtr plane_hull (new Cloud);

      // Compute the convex hull of the plane
      ConvexHull<PointT> chull;
      chull.setDimension (2);
      chull.setInputCloud (cloud);
      chull.setIndices (plane_boundary_indices);
      chull.reconstruct (*plane_hull);

      // Remove the plane indices from the data
      PointIndices::Ptr everything_but_the_plane (new PointIndices);
      if (indices_fullset_.size () != cloud->points.size ())
      {
        indices_fullset_.resize (cloud->points.size ());
        for (int p_it = 0; p_it < static_cast<int> (indices_fullset_.size ()); ++p_it)
          indices_fullset_[p_it] = p_it;
      }
      std::vector<int> indices_subset = plane_indices->indices;
      std::sort (indices_subset.begin (), indices_subset.end ());
      set_difference (indices_fullset_.begin (), indices_fullset_.end (), 
                      indices_subset.begin (), indices_subset.end (), 
                      inserter (everything_but_the_plane->indices, everything_but_the_plane->indices.begin ()));

      // Extract all clusters above the hull
      PointIndices::Ptr points_above_plane (new PointIndices);
      ExtractPolygonalPrismData<PointT> exppd;
      exppd.setInputCloud (cloud);
      exppd.setInputPlanarHull (plane_hull);
      exppd.setIndices (everything_but_the_plane);
      exppd.setHeightLimits (0.0, 0.5);           // up to half a meter
      exppd.segment (*points_above_plane);

      // Use an organized clustering segmentation to extract the individual clusters
      EuclideanClusterComparator<PointT, Normal, Label>::Ptr euclidean_cluster_comparator (new EuclideanClusterComparator<PointT, Normal, Label>);
      euclidean_cluster_comparator->setInputCloud (cloud);
      euclidean_cluster_comparator->setDistanceThreshold (0.03f, false);
      // Set the entire scene to false, and the inliers of the objects located on top of the plane to true
      Label l; l.label = 0;
      PointCloud<Label>::Ptr scene (new PointCloud<Label> (cloud->width, cloud->height, l));
      // Mask the objects that we want to split into clusters
      for (int i = 0; i < static_cast<int> (points_above_plane->indices.size ()); ++i)
        scene->points[points_above_plane->indices[i]].label = 1;
      euclidean_cluster_comparator->setLabels (scene);

      vector<bool> exclude_labels (2);  exclude_labels[0] = true; exclude_labels[1] = false;
      euclidean_cluster_comparator->setExcludeLabels (exclude_labels);

      OrganizedConnectedComponentSegmentation<PointT, Label> euclidean_segmentation (euclidean_cluster_comparator);
      euclidean_segmentation.setInputCloud (cloud);

      PointCloud<Label> euclidean_labels;
      vector<PointIndices> euclidean_label_indices;
      euclidean_segmentation.segment (euclidean_labels, euclidean_label_indices);

      // For each cluster found
      bool cluster_found = false;
      for (size_t i = 0; i < euclidean_label_indices.size (); i++)
      {
        if (cluster_found)
          break;
        // Check if the point that we picked belongs to it
        for (size_t j = 0; j < euclidean_label_indices[i].indices.size (); ++j)
        {
          if (picked_idx != euclidean_label_indices[i].indices[j])
            continue;
          //pcl::PointCloud<PointT> cluster;
          pcl::copyPointCloud (*cloud, euclidean_label_indices[i].indices, object);
          cluster_found = true;
          break;
          //object_indices = euclidean_label_indices[i].indices;
          //clusters.push_back (cluster);
        }
      }
    }
Пример #16
0
ConvexHull* Object::getConvexHull() {
    ConvexHull *res = new ConvexHull(this->convexHull);
    res->rotate(this->orientation);
    res->translate(this->position);
    return res;
}
Пример #17
0
int main() {


	cout<<"Hello from c++ from linux \n";
	cout<<"Hello from c++ from windows \n";

	cout<<"fix some bug\n";

	Point2D ptA(1.0,1.0);
	Point2D ptB(2.0,3.0);
	Point2D ptC,ptD;
	double tmp;

	cout<<"Point A x=";cin>>tmp;ptA.x=(tmp);
	cout<<"Point A y=";cin>>tmp;ptA.y=(tmp);

	cout<<"Point B x=";cin>>tmp;ptB.x=(tmp);
	cout<<"Point B y=";cin>>tmp;ptB.y=(tmp);

	wcout<<"Distance="<<ptA.DistanceTo(ptB)<<endl;



	cout<<"Point C x=";cin>>tmp;ptC.x=(tmp);
	cout<<"Point C y=";cin>>tmp;ptC.y=(tmp);

	cout<<"Point D x=";cin>>tmp;ptD.x=(tmp);
	cout<<"Point D y=";cin>>tmp;ptD.y=(tmp);

	LineSegment l1(ptA,ptB);
	LineSegment l2(ptC,ptD);

	double x,y;

	int result=l1.Intersection2Segment(l2,x,y);


	cout<<"Result ABxCD ="<<result<<"="<<x<<";"<<y<<endl;

	ConvexHull cvh;
	cvh.AddPoint(ptA);
	cvh.AddPoint(ptB);
	cvh.AddPoint(ptC);
	cvh.AddPoint(ptD);

	if(result)
	{
		cvh.AddPoint(Point2D(x,y));
	}

	cvh.FindConvex_QuickHull();
	CPolygon  resultConvex= cvh.m_Convex;

	int numOfPoint=resultConvex.GetNumPoint();
	for	(int i=0;i<numOfPoint;i++)
	{
		cout<<"Point at "<<i<<"="<<resultConvex.GetPoint(i).x<<";"<<resultConvex.GetPoint(i).y<<endl;
	}

	cin.get();
	return 1;
}
Пример #18
0
	void Light2D::findEdges(LightProperties light, ConvexHull object, int *index0, int *index1)
	{
		float m1, n1, m2, n2, cx;
		float x1 = light.position.x, y1 = light.position.y;
		int nextIndex, index, prevIndex;
		int nV = object.getVertexCount();
		Vector2 p1, p2, p3, p4;

		Vector2 edges[2];
		int curEdge = 0;
		float al;

		bool u = 0;

		int in[2];

		bool isBackFacing[CONVEX_HULL_MAX_VERTEX_COUNT];

		for(int i = 0; i < CONVEX_HULL_MAX_VERTEX_COUNT; ++i) isBackFacing[i] = 0;

		//int backFacingCount = 0;

		for(int i = 0; i < nV + 1; ++i)
		{
			Vector2 firstVertex = Vector2(object.getVertex(i).x, object.getVertex(i).y);
			int secondIndex = (i + 1) % nV;
			Vector2 secondVertex = Vector2(object.getVertex(secondIndex).x, object.getVertex(secondIndex).y);
			Vector2 middle = (firstVertex + secondVertex) / 2;

			Vector2 L = light.position - middle;

			Vector2 N;
			N.x = firstVertex.y - secondVertex.y;
			N.y = secondVertex.x - firstVertex.x;

			isBackFacing[i] = (N.dotProduct(L) > 0);
			//backFacingCount += isBackFacing[i];
		}

		//if(backFacingCount == nV) return 0;

		int startingIndex = 0;
		int endingIndex = 0;

		for (int i = 0; i < nV; i++)
		{
			//graphics.fillEllipse(object.getVertex(i).x, object.getVertex(i).y, 5, 5, 0, 2 * pi, COLOR_RGB(255, 255, 255), - 5);

			int currentIndex = i % nV;
			int nextEdge = (i + 1) % nV;

			/*if(isBackFacing[i])
			{
				graphics.fillEllipse(object.getVertex(i).x, object.getVertex(i).y, 20, 20, 0, 2 * pi, COLOR_RGB(255, 255, i * (255 / nV) ), - 10);
			}*/

			if (isBackFacing[currentIndex] && !isBackFacing[nextEdge])
			{
				endingIndex = nextEdge;

				//break;
			}

			if (!isBackFacing[currentIndex] && isBackFacing[nextEdge])
			{
				startingIndex = nextEdge;
			}
		}

		//*i1 = edges[0];
		//*i2 = object.getVertex(1);

		*index0 = startingIndex;
		*index1 = endingIndex;

		/*Vector2 i1 = object.getVertex(startingIndex);
		Vector2 i2 = object.getVertex(endingIndex);

		graphics.fillEllipse(i1.x, i1.y, 10, 10, 0, 2 * pi, COLOR_RGB(255, 0, 0), - 10);
		graphics.fillEllipse(i2.x, i2.y, 20, 20, 0, 2 * pi, COLOR_RGB(0, 255, 0), - 10);*/

		//console.print("StartingIndex : " + INT_TO_STRING(startingIndex) + ", EndingIndex : " + INT_TO_STRING(endingIndex));
	}
Пример #19
0
//TODO: Regard some kind of aspect ration (input)
//(then also the rotation of a single component makes sense)
void ComponentSplitterLayout::reassembleDrawings(GraphAttributes& GA, const Array<List<node> > &nodesInCC)
{
	int numberOfComponents = nodesInCC.size();

	Array<IPoint> box;
	Array<IPoint> offset;
	Array<DPoint> oldOffset;
	Array<double> rotation;
	ConvexHull CH;

	// rotate components and create bounding rectangles

	//iterate through all components and compute convex hull
	for (int j = 0; j < numberOfComponents; j++)
	{
		//todo: should not use std::vector, but in order not
		//to have to change all interfaces, we do it anyway
		std::vector<DPoint> points;

		//collect node positions and at the same time center average
		// at origin
		double avg_x = 0.0;
		double avg_y = 0.0;
		for (node v : nodesInCC[j])
		{
			DPoint dp(GA.x(v), GA.y(v));
			avg_x += dp.m_x;
			avg_y += dp.m_y;
			points.push_back(dp);
		}
		avg_x /= nodesInCC[j].size();
		avg_y /= nodesInCC[j].size();

		//adapt positions to origin
		int count = 0;
		//assume same order of vertices and positions
		for (node v : nodesInCC[j])
		{
			//TODO: I am not sure if we need to update both
			GA.x(v) = GA.x(v) - avg_x;
			GA.y(v) = GA.y(v) - avg_y;
			points.at(count).m_x -= avg_x;
			points.at(count).m_y -= avg_y;

			count++;
		}

		// calculate convex hull
		DPolygon hull = CH.call(points);

		double best_area = numeric_limits<double>::max();
		DPoint best_normal;
		double best_width = 0.0;
		double best_height = 0.0;

		// find best rotation by using every face as rectangle border once.
		for (DPolygon::iterator j = hull.begin(); j != hull.end(); ++j) {
			DPolygon::iterator k = hull.cyclicSucc(j);

			double dist = 0.0;
			DPoint norm = CH.calcNormal(*k, *j);
			for (const DPoint &z : hull) {
				double d = CH.leftOfLine(norm, z, *k);
				if (d > dist) {
					dist = d;
				}
			}

			double left = 0.0;
			double right = 0.0;
			norm = CH.calcNormal(DPoint(0, 0), norm);
			for (const DPoint &z : hull) {
				double d = CH.leftOfLine(norm, z, *k);
				if (d > left) {
					left = d;
				}
				else if (d < right) {
					right = d;
				}
			}
			double width = left - right;

			dist = max(dist, 1.0);
			width = max(width, 1.0);

			double area = dist * width;

			if (area <= best_area) {
				best_height = dist;
				best_width = width;
				best_area = area;
				best_normal = CH.calcNormal(*k, *j);
			}
		}

		if (hull.size() <= 1) {
			best_height = 1.0;
			best_width = 1.0;
			best_area = 1.0;
			best_normal = DPoint(1.0, 1.0);
		}

		double angle = -atan2(best_normal.m_y, best_normal.m_x) + 1.5 * Math::pi;
		if (best_width < best_height) {
			angle += 0.5f * Math::pi;
			double temp = best_height;
			best_height = best_width;
			best_width = temp;
		}
		rotation.grow(1, angle);
		double left = hull.front().m_x;
		double top = hull.front().m_y;
		double bottom = hull.front().m_y;
		// apply rotation to hull and calc offset
		for (DPoint tempP : hull) {
			double ang = atan2(tempP.m_y, tempP.m_x);
			double len = sqrt(tempP.m_x*tempP.m_x + tempP.m_y*tempP.m_y);
			ang += angle;
			tempP.m_x = cos(ang) * len;
			tempP.m_y = sin(ang) * len;

			if (tempP.m_x < left) {
				left = tempP.m_x;
			}
			if (tempP.m_y < top) {
				top = tempP.m_y;
			}
			if (tempP.m_y > bottom) {
				bottom = tempP.m_y;
			}
		}
		oldOffset.grow(1, DPoint(left + 0.5 * static_cast<double>(m_border), -1.0 * best_height + 1.0 * bottom + 0.0 * top + 0.5 * (double)m_border));

		// save rect
		int w = static_cast<int>(best_width);
		int h = static_cast<int>(best_height);
		box.grow(1, IPoint(w + m_border, h + m_border));
	}// components

	offset.init(box.size());

	// call packer
	m_packer.get().call(box, offset, m_targetRatio);

	int index = 0;
	// Apply offset and rebuild Graph
	for (int j = 0; j < numberOfComponents; j++)
	{
		double angle = rotation[index];
		// apply rotation and offset to all nodes

		for (node v : nodesInCC[j])
		{
			double x = GA.x(v);
			double y = GA.y(v);
			double ang = atan2(y, x);
			double len = sqrt(x*x + y*y);
			ang += angle;
			x = cos(ang) * len;
			y = sin(ang) * len;

			x += static_cast<double>(offset[index].m_x);
			y += static_cast<double>(offset[index].m_y);

			x -= oldOffset[index].m_x;
			y -= oldOffset[index].m_y;

			GA.x(v) = x;
			GA.y(v) = y;

		}// while nodes in component

		index++;
	} // for components

	//now we center the whole graph again
	//TODO: why?
	//const Graph& G = GA.constGraph();
	//for(node v : G.nodes)
	//MLG.moveToZero();
}
Пример #20
0
ConvexHull rect2convexhull(Rect const & r) {
    ConvexHull ch;
    for(int i = 0; i < 4; i++)
        ch.merge(r.corner(i));
    return ch;
}
Пример #21
0
    /** \brief Given a plane, and the set of inlier indices representing it,
      * segment out the object of intererest supported by it. 
      *
      * \param[in] picked_idx the index of a point on the object
      * \param[in] cloud the full point cloud dataset
      * \param[in] plane_indices a set of indices representing the plane supporting the object of interest
      * \param[out] object the segmented resultant object 
      */
    void
    segmentObject (int picked_idx, 
                   const typename PointCloud<PointT>::ConstPtr &cloud, 
                   const PointIndices::Ptr &plane_indices, 
                   PointCloud<PointT> &object)
    {
      typename PointCloud<PointT>::Ptr plane_hull (new PointCloud<PointT>);

      // Compute the convex hull of the plane
      ConvexHull<PointT> chull;
      chull.setDimension (2);
      chull.setInputCloud (cloud);
      chull.setIndices (plane_indices);
      chull.reconstruct (*plane_hull);

      // Remove the plane indices from the data
      typename PointCloud<PointT>::Ptr plane (new PointCloud<PointT>);
      ExtractIndices<PointT> extract (true);
      extract.setInputCloud (cloud);
      extract.setIndices (plane_indices);
      extract.setNegative (false);
      extract.filter (*plane);
      PointIndices::Ptr indices_but_the_plane (new PointIndices);
      extract.getRemovedIndices (*indices_but_the_plane);

      // Extract all clusters above the hull
      PointIndices::Ptr points_above_plane (new PointIndices);
      ExtractPolygonalPrismData<PointT> exppd;
      exppd.setInputCloud (cloud);
      exppd.setIndices (indices_but_the_plane);
      exppd.setInputPlanarHull (plane_hull);
      exppd.setViewPoint (cloud->points[picked_idx].x, cloud->points[picked_idx].y, cloud->points[picked_idx].z);
      exppd.setHeightLimits (0.001, 0.5);           // up to half a meter
      exppd.segment (*points_above_plane);

      vector<PointIndices> euclidean_label_indices;
      // Prefer a faster method if the cloud is organized, over EuclidanClusterExtraction
      if (cloud_->isOrganized ())
      {
        // Use an organized clustering segmentation to extract the individual clusters
        typename EuclideanClusterComparator<PointT, Label>::Ptr euclidean_cluster_comparator (new EuclideanClusterComparator<PointT, Label>);
        euclidean_cluster_comparator->setInputCloud (cloud);
        euclidean_cluster_comparator->setDistanceThreshold (0.03f, false);
        // Set the entire scene to false, and the inliers of the objects located on top of the plane to true
        Label l; l.label = 0;
        PointCloud<Label>::Ptr scene (new PointCloud<Label> (cloud->width, cloud->height, l));
        // Mask the objects that we want to split into clusters
        for (const int &index : points_above_plane->indices)
          scene->points[index].label = 1;
        euclidean_cluster_comparator->setLabels (scene);

        boost::shared_ptr<std::set<uint32_t> > exclude_labels = boost::make_shared<std::set<uint32_t> > ();
        exclude_labels->insert (0);
        euclidean_cluster_comparator->setExcludeLabels (exclude_labels);

        OrganizedConnectedComponentSegmentation<PointT, Label> euclidean_segmentation (euclidean_cluster_comparator);
        euclidean_segmentation.setInputCloud (cloud);

        PointCloud<Label> euclidean_labels;
        euclidean_segmentation.segment (euclidean_labels, euclidean_label_indices);
      }
      else
      {
        print_highlight (stderr, "Extracting individual clusters from the points above the reference plane ");
        TicToc tt; tt.tic ();

        EuclideanClusterExtraction<PointT> ec;
        ec.setClusterTolerance (0.02); // 2cm
        ec.setMinClusterSize (100);
        ec.setSearchMethod (search_);
        ec.setInputCloud (cloud);
        ec.setIndices (points_above_plane);
        ec.extract (euclidean_label_indices);
        
        print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", euclidean_label_indices.size ()); print_info (" clusters]\n");
      }

      // For each cluster found
      bool cluster_found = false;
      for (const auto &euclidean_label_index : euclidean_label_indices)
      {
        if (cluster_found)
          break;
        // Check if the point that we picked belongs to it
        for (size_t j = 0; j < euclidean_label_index.indices.size (); ++j)
        {
          if (picked_idx != euclidean_label_index.indices[j])
            continue;
          copyPointCloud (*cloud, euclidean_label_index.indices, object);
          cluster_found = true;
          break;
        }
      }
    }
Пример #22
0
    void
    segment (const PointT &picked_point, 
             int picked_idx,
             PlanarRegion<PointT> &region,
             typename PointCloud<PointT>::Ptr &object)
    {
      object.reset ();

      // Segment out all planes
      vector<ModelCoefficients> model_coefficients;
      vector<PointIndices> inlier_indices, boundary_indices;
      vector<PlanarRegion<PointT>, Eigen::aligned_allocator<PlanarRegion<PointT> > > regions;

      // Prefer a faster method if the cloud is organized, over RANSAC
      if (cloud_->isOrganized ())
      {
        print_highlight (stderr, "Estimating normals ");
        TicToc tt; tt.tic ();
        // Estimate normals
        PointCloud<Normal>::Ptr normal_cloud (new PointCloud<Normal>);
        estimateNormals (cloud_, *normal_cloud);
        print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", normal_cloud->size ()); print_info (" points]\n");

        OrganizedMultiPlaneSegmentation<PointT, Normal, Label> mps;
        mps.setMinInliers (1000);
        mps.setAngularThreshold (deg2rad (3.0)); // 3 degrees
        mps.setDistanceThreshold (0.03); // 2 cm
        mps.setMaximumCurvature (0.001); // a small curvature
        mps.setProjectPoints (true);
        mps.setComparator (plane_comparator_);
        mps.setInputNormals (normal_cloud);
        mps.setInputCloud (cloud_);

        // Use one of the overloaded segmentAndRefine calls to get all the information that we want out
        PointCloud<Label>::Ptr labels (new PointCloud<Label>);
        vector<PointIndices> label_indices;
        mps.segmentAndRefine (regions, model_coefficients, inlier_indices, labels, label_indices, boundary_indices);
      }
      else
      {
        SACSegmentation<PointT> seg;
        seg.setOptimizeCoefficients (true);
        seg.setModelType (SACMODEL_PLANE);
        seg.setMethodType (SAC_RANSAC);
        seg.setMaxIterations (10000);
        seg.setDistanceThreshold (0.005);

        // Copy XYZ and Normals to a new cloud
        typename PointCloud<PointT>::Ptr cloud_segmented (new PointCloud<PointT> (*cloud_));
        typename PointCloud<PointT>::Ptr cloud_remaining (new PointCloud<PointT>);

        ModelCoefficients coefficients;
        ExtractIndices<PointT> extract;
        PointIndices::Ptr inliers (new PointIndices ());

        // Up until 30% of the original cloud is left
        int i = 1;
        while (double (cloud_segmented->size ()) > 0.3 * double (cloud_->size ()))
        {
          seg.setInputCloud (cloud_segmented);

          print_highlight (stderr, "Searching for the largest plane (%2.0d) ", i++);
          TicToc tt; tt.tic ();
          seg.segment (*inliers, coefficients);
          print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", inliers->indices.size ()); print_info (" points]\n");
 
          // No datasets could be found anymore
          if (inliers->indices.empty ())
            break;

          // Save this plane
          PlanarRegion<PointT> region;
          region.setCoefficients (coefficients);
          regions.push_back (region);

          inlier_indices.push_back (*inliers);
          model_coefficients.push_back (coefficients);

          // Extract the outliers
          extract.setInputCloud (cloud_segmented);
          extract.setIndices (inliers);
          extract.setNegative (true);
          extract.filter (*cloud_remaining);
          cloud_segmented.swap (cloud_remaining);
        }
      }
      print_highlight ("Number of planar regions detected: %lu for a cloud of %lu points\n", regions.size (), cloud_->size ());

      double max_dist = numeric_limits<double>::max ();
      // Compute the distances from all the planar regions to the picked point, and select the closest region
      int idx = -1;
      for (size_t i = 0; i < regions.size (); ++i)
      {
        double dist = pointToPlaneDistance (picked_point, regions[i].getCoefficients ()); 
        if (dist < max_dist)
        {
          max_dist = dist;
          idx = static_cast<int> (i);
        }
      }

      // Get the plane that holds the object of interest
      if (idx != -1)
      {
        plane_indices_.reset (new PointIndices (inlier_indices[idx]));

        if (cloud_->isOrganized ())
        {
          approximatePolygon (regions[idx], region, 0.01f, false, true);
          print_highlight ("Planar region: %lu points initial, %lu points after refinement.\n", regions[idx].getContour ().size (), region.getContour ().size ());
        }
        else
        {
          // Save the current region
          region = regions[idx]; 

          print_highlight (stderr, "Obtaining the boundary points for the region ");
          TicToc tt; tt.tic ();
          // Project the inliers to obtain a better hull
          typename PointCloud<PointT>::Ptr cloud_projected (new PointCloud<PointT>);
          ModelCoefficients::Ptr coefficients (new ModelCoefficients (model_coefficients[idx]));
          ProjectInliers<PointT> proj;
          proj.setModelType (SACMODEL_PLANE);
          proj.setInputCloud (cloud_);
          proj.setIndices (plane_indices_);
          proj.setModelCoefficients (coefficients);
          proj.filter (*cloud_projected);

          // Compute the boundary points as a ConvexHull
          ConvexHull<PointT> chull;
          chull.setDimension (2);
          chull.setInputCloud (cloud_projected);
          PointCloud<PointT> plane_hull;
          chull.reconstruct (plane_hull);
          region.setContour (plane_hull);
          print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%lu", plane_hull.size ()); print_info (" points]\n");
        }

      }

      // Segment the object of interest
      if (plane_indices_ && !plane_indices_->indices.empty ())
      {
        plane_.reset (new PointCloud<PointT>);
        copyPointCloud (*cloud_, plane_indices_->indices, *plane_);
        object.reset (new PointCloud<PointT>);
        segmentObject (picked_idx, cloud_, plane_indices_, *object);
      }
    }
int main(int argc, char* argv[])
{
	char *infile, *outfile;
	if(argc == 5)
	{
		if(!strcmp(argv[1], "-in") && !strcmp(argv[3], "-out"))
		{
			infile = argv[2];
			outfile = argv[4];
		}
		else if(!strcmp(argv[1], "-out") && !strcmp(argv[3], "-out"))
		{
			infile = argv[4];
			outfile = argv[2];
		}
	}
	else if((argc==2 && strcmp(argv[1], "-help")) || argc!=2)
	{
		cout << "help : -in [input file] -out [output file]" << endl;
		return 0;
	}

	vector< Point2D<> > pointList;
	clock_t start, end;
	ifstream ifs;
	ofstream ofs;

	//input
	ifs.open(infile, std::ios::in);
	int numOfPoint;
	ifs >> numOfPoint;
	int tempX, tempY;
	for(int i=0; i<numOfPoint; i++)
	{
		ifs >> tempX >> tempY;
		pointList.push_back(Point2D<>(tempX, tempY));
	}

	//output
	ofs.open(outfile, std::ios::out);

	//convex hull
	ConvexHull convexHull;
	start = clock();
	list<Point2D<>*> *ch = convexHull.getConVexHull(pointList);
	end = clock();
	ofs << "convex hull time" << endl;
	ofs << (float)(end-start)/CLOCKS_PER_SEC << endl;
	ofs << "convex hull set" << endl;
	for(list<Point2D<>*>::iterator itr=ch->begin(); itr!=ch->end(); itr++)
		ofs << (*itr)->X() << ' ' << (*itr)->Y() << endl;
	ofs << -1 << endl;

	//clesest pair
	ClosestPair closestPair;
	start = clock();
	pair<Point2D<>, Point2D<> > cp = closestPair.getClosestPair(pointList);
	end = clock();
	ofs << "close pair time" << endl;
	ofs << (float)(end-start)/CLOCKS_PER_SEC << endl;
	ofs << "close pair" << endl;
	ofs << cp.first.X() << ' ' << cp.first.Y() << endl;
	ofs << cp.second.X() << ' ' << cp.second.Y();

	return 0;
}