//to compute wcv, give differenct weights to the radius of cones.
void CVT::Display_vorCone(cv::Mat & img, int numOfsites)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPointSize(3);

	double max_radius=std::max(img.size().height, img.size().width);
	
	for (int i = 0; i<numOfsites; i++)
	{
		cells[i].coverage.clear();
		float x = cells[i].site.y;
		float y = img.size().height-0.5- cells[i].site.x;
		cv::Point pix((int)cells[i].site.x, (int)cells[i].site.y);
		float d= color2dist(img, pix);//검정일때 d=1. 
		

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(x, y, 0);
		
		//integer 연산이라 i=270일때 (0,1,14)가 나온다.
		//the brighter one should have larger radius.
		glColor3ub(i / (256 * 256), (i / 256)%256 , i%256 );
		glutSolidCone(max_radius*((2 - d)+0.5f*(1+d)), 1, 16, 1);

		//draw each sites.(i.e. center of a cone)
		//glColor3ub(0, 0, 0);
		//glBegin(GL_POINTS);
		//glVertex3d(0, 0, 1);
		//glEnd();
	}
	glFinish();//double buffering하면 안된다?

}
//buil the VOR once(weighted vor diagram?)
void CVT::vor(cv::Mat &  img)
{
	cv::Mat dist(img.size(), CV_32F, cv::Scalar::all(FLT_MAX)); //an image with infinity distance
	cv::Mat root(img.size(), CV_16U, cv::Scalar::all(USHRT_MAX)); //an image of root index
	cv::Mat visited(img.size(), CV_8U, cv::Scalar::all(0)); //all unvisited


	//init
	std::vector< std::pair<float, cv::Point> > open;
	ushort site_id = 0;
	for (auto& c : this->cells)
	{
		if (debug)
		{
			if (c.site.x<0 || c.site.x>img.size().height)
				std::cout << "! Warning: c.site.x=" << c.site.x << std::endl;

			if (c.site.y<0 || c.site.y>img.size().width)
				std::cout << "! Warning: c.site.y=" << c.site.y << std::endl;
		}


		cv::Point pix((int)c.site.x, (int)c.site.y);
		float d = color2dist(img, pix);
		//dist에 2D에서의 color value저장. dist 가 크다 <-> 흰색에 가깝다.
		dist.at<float>(pix.x, pix.y) = d;
		root.at<ushort>(pix.x, pix.y) = site_id++;
		open.push_back( std::make_pair(d, pix) );//push
		c.coverage.clear();
	}
	
	std::make_heap(open.begin(), open.end(), compareCell);

	//propagate
	while (open.empty() == false)
	{
		//
		std::pop_heap(open.begin(), open.end(), compareCell);//pop, 저장된 color value와 point pair를 꺼낸다.
		auto cell = open.back();
		auto& cpos = cell.second;
		open.pop_back();

		//check if the distance from this cell is already updated
		if (cell.first > dist.at<float>(cpos.x, cpos.y)) continue;
		if (visited.at<uchar>(cpos.x, cpos.y) > 0) continue; //visited
		visited.at<uchar>(cpos.x, cpos.y) = 1;

		//check the neighbors
		for (int dx =-1; dx <= 1; dx++) //x is row
		{
			int x = cpos.x + dx;
			if (x < 0 || x >= img.size().height) continue;
			for (int dy = -1; dy <= 1; dy++) //y is column
			{
				if (dx == 0 && dy == 0) continue; //itself...

				int y = cpos.y + dy;
				if (y < 0 || y >= img.size().width) continue;
				float newd = dist.at<float>(cpos.x, cpos.y) + color2dist(img, cv::Point(x, y));
				float oldd = dist.at<float>(x, y);

				if (newd < oldd)
				{
					dist.at<float>(x, y)=newd;
					root.at<ushort>(x, y) = root.at<ushort>(cpos.x, cpos.y);
					open.push_back(std::make_pair(newd, cv::Point(x, y)));
					std::push_heap(open.begin(), open.end(), compareCell);
				}
			}//end for dy
		}//end for dx
	}//end while

	//collect cells
	for (int x = 0; x < img.size().height; x++)
	{
		for (int y = 0; y < img.size().width; y++)
		{
			ushort rootid = root.at<ushort>(x, y);
			this->cells[rootid].coverage.push_back(cv::Point(x,y));
		}//end y
	}//end x

	//remove empty cells...CVT할때를 위해
	int cvt_size = this->cells.size();
	for (int i = 0; i < cvt_size; i++)
	{
		if (this->cells[i].coverage.empty())
		{
			this->cells[i] = this->cells.back();
			this->cells.pop_back();
			i--;
			cvt_size--;
		}
	}//end for i

	if (debug)
	{
		//this shows the progress...
		double min;
		double max;
		cv::minMaxIdx(dist, &min, &max);
		cv::Mat adjMap;
		cv::convertScaleAbs(dist, adjMap, 255 / max);
		//cv::applyColorMap(adjMap, adjMap, cv::COLORMAP_JET);
	
		for (auto& c : this->cells)
		{
			cv::circle(adjMap, cv::Point(c.site.y, c.site.x), 2, CV_RGB(0, 0, 255), -1);
		}
	
		cv::imshow("CVT", adjMap);
		cv::waitKey(5);
	}
}
Example #3
0
//build the VOR once
void CVT::vor(cv::Mat &  img)
{
	cv::Mat dist(img.size(), CV_32F, cv::Scalar::all(FLT_MAX)); //an image with infinity distance
	cv::Mat root(img.size(), CV_16U, cv::Scalar::all(USHRT_MAX)); //an image of root index
	cv::Mat visited(img.size(), CV_8U, cv::Scalar::all(0)); //all unvisited


	//init
	std::vector< std::pair<float, cv::Point> > open;	//YH open is a vector(float, cvPoint)
	ushort site_id = 0;
	for (auto& c : this->cells)
	{
		if (debug)
		{
			if (c.site.x<0 || c.site.x>img.size().height)
				std::cout << "! Warning: c.site.x=" << c.site.x << std::endl;

			if (c.site.y<0 || c.site.y>img.size().width)
				std::cout << "! Warning: c.site.y=" << c.site.y << std::endl;
		}


		cv::Point pix((int)c.site.x, (int)c.site.y);	//YH a VOR site, pix(x,y)
		float d = color2dist(img, pix);		//YH d is distance, color2dist convert a color intensity to distance between 0~1
		
		dist.at<float>(pix.x, pix.y) = d;
		root.at<ushort>(pix.x, pix.y) = site_id++;
		
		open.push_back( std::make_pair(d, pix) );
		c.coverage.clear();
	}
	
	std::make_heap(open.begin(), open.end(), compareCell); // YH make min heap using the begining vector(pair) and the ending vector(pair)

	//propagate
	// YH do "while" for all cell and find the smallest distance as checking neighbors
	while (open.empty() == false)
	{
		std::pop_heap(open.begin(), open.end(), compareCell);	//move the smallest element to the end
		auto cell = open.back();	//YH from hightest node, which has the smallest value, set cell 
		auto& cpos = cell.second;	//YH cell position
		open.pop_back(); // remove it

		//if(cell.first != dist.at<float>(cpos.x, cpos.y) )("first %f \t, dist %f \n", cell.first, dist.at<float>(cpos.x, cpos.y));
		
		//check if the distance from this cell is already updated
		if (cell.first > dist.at<float>(cpos.x, cpos.y)) continue;	//YH first = distance(intensity)
		if (visited.at<uchar>(cpos.x, cpos.y) > 0) continue; //visited //YH the if cpos already visited, skip this time and do next cell
		
		visited.at<uchar>(cpos.x, cpos.y) = 1;

		//check the neighbors
		for (int dx =-1; dx <= 1; dx++) //x is row
		{
			int x = cpos.x + dx;
			if (x < 0 || x >= img.size().height) continue;	//YH check the x is inside an image
			for (int dy = -1; dy <= 1; dy++) //y is column
			{
				if (dx == 0 && dy == 0) continue; //itself...

				int y = cpos.y + dy;
				if (y < 0 || y >= img.size().width) continue;	//YH check the y is inside an image

				float newd = dist.at<float>(cpos.x, cpos.y) + color2dist(img, cv::Point(x, y));	//YH new distance
				float oldd = dist.at<float>(x, y);	//YH old distance

				//if((newd<oldd)&&oldd<100) printf("tot %.6f \t // old %.6f \n", newd, oldd);// color2dist(img, cv::Point(x, y)), dist.at<float>(cpos.x, cpos.y));
				//cv::waitKey(1000);

				if (newd < oldd)	//YH check new one has the smallest value and push it in the heap
				{
					dist.at<float>(x, y)=newd;
					root.at<ushort>(x, y) = root.at<ushort>(cpos.x, cpos.y);
					open.push_back(std::make_pair(newd, cv::Point(x, y)));	// add the element at the next end of list container
					std::push_heap(open.begin(), open.end(), compareCell);
				}
			}//end for dy
		}//end for dx
	}//end while

	//collect cells
	for (int x = 0; x < img.size().height; x++)
	{
		for (int y = 0; y < img.size().width; y++)
		{
			ushort rootid = root.at<ushort>(x, y);
			this->cells[rootid].coverage.push_back(cv::Point(x,y));	// YH make coverage
		}//end y
	}//end x

	//remove empty cells...
	int cvt_size = this->cells.size();
	for (int i = 0; i < cvt_size; i++)
	{
		if (this->cells[i].coverage.empty())
		{
			this->cells[i] = this->cells.back();
			this->cells.pop_back();
			i--;
			cvt_size--;
		}
	}//end for i

	if (debug)
	{
		//this shows the progress...
		double min;
		double max;
		cv::minMaxIdx(dist, &min, &max);	//YH finds global minimum and maximum array elements and returns their values and their locations
		cv::Mat adjMap;
		cv::convertScaleAbs(dist, adjMap, 255 / max);	//YH scales array elements, computes absolute values and converts the results to 8-bit unsigned integers: dst(i)=saturate_cast<uchar>abs(src(i)*alpha+beta)
		//cv::applyColorMap(adjMap, adjMap, cv::COLORMAP_JET);

		for (auto& c : this->cells)
		{
			cv::circle(adjMap, cv::Point(c.site.y, c.site.x), 2, CV_RGB(0, 0, 255), -1);
		}

		//cv::imshow("CVT", adjMap);
		//cv::waitKey(5);
	}
}