//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); } }
//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); } }