findArrow.cpp
Go to the documentation of this file.
00001  /**************************************************************************************************
00002   Software License Agreement (BSD License)
00003  
00004   Copyright (c) 2011-2013, LAR toolkit developers - University of Aveiro - http://lars.mec.ua.pt
00005   All rights reserved.
00006  
00007   Redistribution and use in source and binary forms, with or without modification, are permitted
00008   provided that the following conditions are met:
00009  
00010    *Redistributions of source code must retain the above copyright notice, this list of
00011     conditions and the following disclaimer.
00012    *Redistributions in binary form must reproduce the above copyright notice, this list of
00013     conditions and the following disclaimer in the documentation and/or other materials provided
00014     with the distribution.
00015    *Neither the name of the University of Aveiro nor the names of its contributors may be used to
00016     endorse or promote products derived from this software without specific prior written permission.
00017   
00018   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
00019   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00020   FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
00021   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00024   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00025   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  ***************************************************************************************************/
00027 
00048 #include <arrow_detection/findArrow.h>
00049 
00050     //global vars
00051     //cv::Point src_centre(0,0);
00052     //unsigned int src_centre_x=0;
00053     //unsigned int src_centre_y=0;
00054     
00055     bool findArrow::found_new_point=false;
00056 
00057     // Const variables
00058 
00059     const unsigned int findArrow::EROSION_SIZE=1;
00060     const unsigned int findArrow::EROSION_SIZE_MIN=1;
00061     const unsigned int findArrow::THRESH = 100;
00062     const unsigned int findArrow::MAX_THRESH = 255;//Trackbar
00063     const unsigned int findArrow::LINE_THICKNESS = 2;
00064   
00065 // For validate_lengths function
00066     const unsigned short findArrow::VAL_MAX_LENGTH= 500;
00067     const unsigned short findArrow::VAL_MIN_LENGTH = 100;
00068     const float findArrow::VAL_MIN_RELATION_LENGTH = 1.3; 
00069     const float findArrow::VAL_MAX_RELATION_LENGTH = 3.1;
00070   
00071 // Variables for validate_contour_Area_Length function  
00072     const double findArrow::BBCA_MIN = 1.3;//1.3;
00073     const double findArrow::BBCA_MAX = 1.9;//1.7;
00074     const double findArrow::BBCL_MIN = 7;//12;
00075     const double findArrow::BBCL_MAX = 35;//30;
00076     const double findArrow::CACL_MIN = 4;//6;
00077     const double findArrow::CACL_MAX = 22;//17;
00078     const double findArrow::AREA_MIN = 500;//17;
00079 
00080 // Variable for validate_convexHull     
00081     const unsigned short findArrow::CONVEX_HULL_CORNERS = 5;
00082     
00083 // Variable for validate_corners_arrow
00084     const unsigned short findArrow::CONVEX_ARROW_CORNERS = 7;
00085 
00086 Point findArrow::calculate_center_contour(Point2f contour[],unsigned int size_contour)
00087 {
00088     
00096     assert (size_contour>0);
00097     unsigned int cont=0;
00098     double xx=0,yy=0;
00099     Point result;
00100     for(cont=0;cont<size_contour;cont++)
00101     {
00102         xx+=contour[cont].x;
00103         yy+=contour[cont].y;
00104     }
00105     result.x=xx/cont+1;
00106     result.y=yy/cont+1;
00107     
00108     return result;
00109 }
00110 
00112 void findArrow::Opening(Mat & src, Mat & dest,unsigned int erosion_size)
00113 {
00123     assert(erosion_size > 0);
00124   Mat element = getStructuringElement( MORPH_RECT,Size( 2*erosion_size + 1, 2*erosion_size+1 ),
00125                                Point( erosion_size, erosion_size ) );
00126     
00127           dilate( src, dest, element ); 
00128           erode( dest, dest, element );
00129 }
00130 
00132 void findArrow::closing(Mat & src, Mat & dest,unsigned int erosion_size)
00133 {
00143    assert(erosion_size > 0);
00144   Mat element = getStructuringElement( MORPH_RECT,Size( 2*erosion_size + 1, 2*erosion_size+1 ),
00145                                Point( erosion_size, erosion_size ) );
00146     
00147           erode( src, dest, element );
00148           dilate( dest, dest, element ); 
00149 }
00150 
00151 void findArrow::boundig_box( Mat & src_tresh, Mat & threshold_output)
00152 {
00163      vector<vector<Point> > contours;
00164      vector<Vec4i> hierarchy;
00165      // random number
00166         RNG rng(12345);
00168   findContours( src_tresh, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
00169 
00171   vector<vector<Point> > contours_poly( contours.size() );
00172   vector<Rect> boundRect( contours.size() );
00173   vector<Point2f>center( contours.size() );
00174   vector<float>radius( contours.size() );
00175 
00176   for( unsigned i = 0; i < contours.size(); i++ )
00177      { approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
00178        boundRect[i] = boundingRect( Mat(contours_poly[i]) );
00179        minEnclosingCircle( (Mat)contours_poly[i], center[i], radius[i] );
00180      }
00181 
00183   Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
00184   
00185   for( unsigned i = 0; i< contours.size(); i++ )
00186      {
00187        Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
00188        drawContours( drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
00189        rectangle( drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0 );
00190        circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );
00191      }
00192 
00194   
00195   //imshow( "Contours", drawing );
00196 
00197 }
00198 
00199 
00200 
00202 void findArrow::descritor( Mat & img_object, Mat & img_scene)
00203 {
00204   
00205 //*****************************************************
00207 //*****************************************************
00208 
00209   
00210   //-- Step 1: Detect the keypoints using SURF Detector
00211   int minHessian = 1000;
00212 
00213   SurfFeatureDetector detector( minHessian );
00214 
00215   std::vector<KeyPoint> keypoints_object, keypoints_scene;
00216 
00217   detector.detect( img_object, keypoints_object );
00218   detector.detect( img_scene, keypoints_scene );
00219 
00220   //-- Step 2: Calculate descriptors (feature vectors)
00221   SurfDescriptorExtractor extractor;
00222 
00223   Mat descriptors_object, descriptors_scene;
00224 
00225   extractor.compute( img_object, keypoints_object, descriptors_object );
00226   extractor.compute( img_scene, keypoints_scene, descriptors_scene );
00227 
00228   //-- Step 3: Matching descriptor vectors using FLANN matcher
00229   FlannBasedMatcher matcher;
00230   std::vector< DMatch > matches;
00231   matcher.match( descriptors_object, descriptors_scene, matches );
00232 
00233   double max_dist = 0; double min_dist = 100;
00234 
00235   //-- Quick calculation of max and min distances between keypoints
00236   for( int i = 0; i < descriptors_object.rows; i++ )
00237   { double dist = matches[i].distance;
00238     if( dist < min_dist ) min_dist = dist;
00239     if( dist > max_dist ) max_dist = dist;
00240   }
00241 
00242   printf("-- Max dist : %f \n", max_dist );
00243   printf("-- Min dist : %f \n", min_dist );
00244 
00245   //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
00246   std::vector< DMatch > good_matches;
00247 
00248   for( int i = 0; i < descriptors_object.rows; i++ )
00249   { if( matches[i].distance < 2*min_dist )
00250      { good_matches.push_back( matches[i]); }
00251   }
00252 
00253   Mat img_matches;
00254   drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,
00255                good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
00256                vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
00257 
00258   //-- Localize the object
00259   std::vector<Point2f> obj;
00260   std::vector<Point2f> scene;
00261 
00262   for(unsigned int i = 0; i < good_matches.size(); i++ )
00263   {
00264     //-- Get the keypoints from the good matches
00265     obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
00266     scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
00267   }
00268 
00269 cout<<"Obj "<<obj.size()<<" scene: "<<scene.size()<<endl;
00270 //alteração feita pelo jorge! da erro quando obj.size e scene.size <4
00271     if(obj.size()>=4 && scene.size()>=4)
00272     {
00273       
00274         Mat H = findHomography( obj, scene, CV_RANSAC );
00275 
00276       //-- Get the corners from the image_1 ( the object to be "detected" )
00277       std::vector<Point2f> obj_corners(4);
00278       obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 );
00279       obj_corners[2] = cvPoint( img_object.cols, img_object.rows ); obj_corners[3] = cvPoint( 0, img_object.rows );
00280       std::vector<Point2f> scene_corners(4);
00281 
00282       perspectiveTransform( obj_corners, scene_corners, H);
00283 
00284       //-- Draw lines between the corners (the mapped object in the scene - image_2 )
00285       line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0), scene_corners[1] + Point2f( img_object.cols, 0), Scalar(0, 255, 0), 4 );
00286       line( img_matches, scene_corners[1] + Point2f( img_object.cols, 0), scene_corners[2] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
00287       line( img_matches, scene_corners[2] + Point2f( img_object.cols, 0), scene_corners[3] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
00288       line( img_matches, scene_corners[3] + Point2f( img_object.cols, 0), scene_corners[0] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
00289       
00290     }
00291   //-- Show detected matches
00292   imshow( "Good Matches & Object detection", img_matches );
00293 
00294   }
00295   
00296 
00297 bool findArrow::validate_contour_Area_Length(vector<Point> contours,vector<double> bbox_points,
00298 const double bbca_min,
00299 const double bbca_max,const double bbcl_min, const double bbcl_max,
00300 const double cacl_min,const double cacl_max)
00301 {
00313     double bb_length = bbox_points[0];//previously sorted
00314     double bb_Width = bbox_points[3];
00315     double bba =  bb_Width*bb_length;
00316     
00317     double ca = contourArea(contours);
00318     double cl = arcLength( contours, true );
00319     
00320     double bb_ca = bba/ca;//relations between bounding boxes, countour area and contour lenght
00321     double bb_cl = bba/cl;
00322     double ca_cl = ca/cl;
00323     
00324     return ((bb_ca > bbca_min && bb_ca < bbca_max) && (bb_cl > bbcl_min && bb_cl < bbcl_max) && 
00325         (ca_cl > cacl_min && ca_cl < cacl_max) && ca > AREA_MIN);
00326     
00327 }
00328 
00330 vector<double> findArrow::sort_points(Point2f rect_points[])
00331 {
00332     vector<double> res(4);//store distance betwen 2 consecutive points
00333     
00334     for(unsigned short w=0; w<4 ; w++)//compute the distance betwen 2 points
00335     {
00336     res[w]= norm(Mat(rect_points[w]),Mat(rect_points[(w+1)%4]));
00337     }
00338     std::sort(res.begin(),res.end()); //sort lengths
00339     
00340     return res;
00341 }
00342 
00343 
00344 bool findArrow::validate_lengths(Point2f rect_points[], const unsigned short max_length,
00345                 const unsigned short min_length, const float min_relation_length,
00346                 const float max_relation_length)
00347 { 
00358     assert((max_length > 0) && (min_length >0) && (min_relation_length > 0) && (max_relation_length > 0));
00359     vector<double> res(4);
00360     res = sort_points(rect_points);//sort rect_points
00361    
00362     double relation_lengths = res[3]/res[0]; // height/width relation
00363  
00364     return (res[3]<max_length && (res[0]+res[3])>min_length && 
00365             relation_lengths>min_relation_length && relation_lengths< max_relation_length);
00366         
00367 }
00368 
00369 bool findArrow::validate_corners_arrow(vector<Point> contours,
00370                 const unsigned short convex_arrow_corners)
00371 {
00372     assert(convex_arrow_corners > 0);
00373     vector<Point> arrow_corners;
00374     vector<Point> hull( contours.size() );
00375             
00376     approxPolyDP(contours, arrow_corners, arcLength(Mat(contours), true) * 0.02, true );
00377                 
00378     return(arrow_corners.size() == convex_arrow_corners);
00379 }
00380 
00381 //check number of corners of convexhull 
00382 bool findArrow::validate_convexHull(vector<Point> contours,
00383                 const unsigned short convex_hull_corners)
00384 {
00385     vector<Point> approx_hull;
00386     vector<Point> hull( contours.size() );
00387     convexHull( Mat(contours), hull, false ); 
00388             
00389     approxPolyDP(Mat(hull), approx_hull, arcLength(Mat(hull), true) * 0.02, true );
00390                 
00391     return(approx_hull.size() == convex_hull_corners);
00392 }
00393 
00394 float findArrow::innerAngle(float px1, float py1, float px2, float py2, float cx1, float cy1)  
00395 {  
00397  float dist1 = sqrt(  (px1-cx1)*(px1-cx1) + (py1-cy1)*(py1-cy1) );  
00398  float dist2 = sqrt(  (px2-cx1)*(px2-cx1) + (py2-cy1)*(py2-cy1) );  
00399   
00400  float Ax, Ay;  
00401  float Bx, By;  
00402  float Cx, Cy;  
00403   
00404  //find closest point to C  
00405  //printf("dist = %lf %lf\n", dist1, dist2);  
00406   
00407  Cx = cx1;  
00408  Cy = cy1;  
00409  if(dist1 < dist2)  
00410  {    
00411   Bx = px1;  
00412   By = py1;    
00413   Ax = px2;  
00414   Ay = py2;  
00415   
00416   
00417  }else{  
00418   Bx = px2;  
00419   By = py2;  
00420   Ax = px1;  
00421   Ay = py1;  
00422  }  
00423   
00424  float Q1 = Cx - Ax;  
00425  float Q2 = Cy - Ay;  
00426  float P1 = Bx - Ax;  
00427  float P2 = By - Ay;    
00428   
00429   
00430  float A = acos( (P1*Q1 + P2*Q2) / ( sqrt(P1*P1+P2*P2) * sqrt(Q1*Q1+Q2*Q2) ) );  
00431   
00432  A = A*180/CV_PI;  
00433   
00434  return A;  
00435 }  
00436 
00437 
00438 double findArrow::angle(cv::Point pt1, cv::Point pt2, cv::Point pt0)
00439 {
00444     double dx1 = pt1.x - pt0.x;
00445     double dy1 = pt1.y - pt0.y;
00446     double dx2 = pt2.x - pt0.x;
00447     double dy2 = pt2.y - pt0.y;
00448     return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
00449 }
00450 
00451 
00452 void findArrow::setLabel(cv::Mat& im, const std::string label, std::vector<cv::Point>& contour)
00453 {
00457     int fontface = cv::FONT_HERSHEY_SIMPLEX;
00458     double scale = 0.4;
00459     int thickness = 1;
00460     int baseline = 0;
00461 
00462     cv::Size text = cv::getTextSize(label, fontface, scale, thickness, &baseline);
00463     cv::Rect r = cv::boundingRect(contour);
00464 
00465     cv::Point pt(r.x + ((r.width - text.width) / 2), r.y + ((r.height + text.height) / 2));
00466     cv::rectangle(im, pt + cv::Point(0, baseline), pt + cv::Point(text.width, -text.height), CV_RGB(255,255,255), CV_FILLED);
00467     cv::putText(im, label, pt, fontface, scale, CV_RGB(0,0,0), thickness, 8);
00468 }
00469 
00470 
00471 // Functions 
00472 
00473 int findArrow::find_arrow(cv::Mat frame,cv::Point & center_point)//unsigned int & size_cols,unsigned int & size_rows)
00474 {
00475     //doxyfile concerning
00501 // Create a obj "cap" that will get the video from the camera 
00502    
00503         
00504 // Loop cycle throug all frames
00505   
00506     
00507     Mat edges,edges_b;
00508 
00509     //cout << "size" << frame.size() << endl;
00510     
00511     // BRG to GRAY
00512     
00513     edges=frame;
00514     //size_cols = frame.cols;
00515     //size_rows = frame.rows;
00516     // Histogram Equalization 
00517     equalizeHist( edges, edges );
00518     
00519     // Adaptive Threshold
00520     imshow("antes", edges);
00521     adaptiveThreshold(edges,edges_b, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY,7,5);
00522     imshow("depois", edges_b);
00523     // Adaptative Threshold Otsu
00524     threshold(edges, edges, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
00525     
00526     // Combine both thresholds 
00527     edges = edges & edges_b;
00528     
00529     // Closing
00530    
00531     //closing(edges, edges,1);
00532     
00533     // Find countours
00534     
00535     vector<vector<Point> > contour = find_contours(edges, edges, LINE_THICKNESS);
00536      cv::imshow("imagem_teste2", edges);
00537     cv::waitKey(20);
00538     //imshow("imagem_teste3", edges);
00539     // Filtering contours
00540     edges = edges > 128;
00541             
00542     // Boundig box
00543     
00544     vector<RotatedRect> pontos_retangulos = boundig_box_small( edges,edges,contour,center_point);
00545     imshow("imagem_teste4", (edges));
00546                 
00547 //                         
00548     //process_bbox_pnts_neighbors(pontos_retangulos);
00549     
00552 //smallFrame = image(Rect(x, y, CROPPING_WIDTH, CROPPING_HEIGHT));
00553 //* a fixed CROPPING_WIDTH or HEIGHT won't do. you've got to check, 
00554 //if your Rect did not end up partly outside the image, i.e if x+CROPPING_WIDTH < img.cols-1
00555 
00557     
00558 
00560     //cv::destroyAllWindows();
00561         
00562     return 0;
00563 }
00564 
00565 
00566 vector<vector<Point> > findArrow::find_contours(Mat & src, Mat & dest,const unsigned int & line_thinckness)
00567 { 
00589     vector<vector<Point> > contours,contours2;
00590     vector<Vec4i> hierarchy;
00591     findContours(src, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0,0) );
00592     Mat drawing = Mat::zeros( dest.size(), CV_8U );
00593     
00594     for (unsigned int i=0; i<contours.size(); i++)
00595     {
00596         
00597         if ((hierarchy[i][3] >= 0) && contourArea(contours[i])>AREA_MIN)   //has parent, inner (hole) contour of a closed edge (looks good)
00598         {
00599             
00600             drawContours(drawing, contours, i, Scalar(255, 0, 0), line_thinckness, 8);                              
00601             
00602             contours2.push_back(contours[i]);
00603             
00604             
00605         }
00606     }
00607     dest=drawing;
00608 
00609     return contours;
00610 }
00611 
00612 
00613 vector<RotatedRect> findArrow::boundig_box_small( Mat & src_tresh, Mat & threshold_output,vector<vector<Point> > contours,
00614                                 cv::Point & src_centre)
00615 {
00625     bool control=true;
00626     vector<vector<Point> > contours2;
00627     vector<Vec4i> hierarchy;
00628     RNG rng(12345); // random number
00630     //imshow(" Before src_tresh",src_tresh );
00631     findContours( src_tresh, contours2, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE,
00632                     Point(0, 0) );
00633     //imshow(" After src_tresh",src_tresh );
00634     contours=contours2;
00635     
00636     //cout << "number of contours::    " << contours.size() << endl;    
00638     vector<vector<Point> > contours_poly( contours.size() );
00639     vector<Rect> boundRect( contours.size() );
00640     vector<Point2f>center( contours.size() );
00641     vector<float>radius( contours.size() );
00642           
00644     vector<RotatedRect> minRect( contours.size() );
00645     vector<RotatedRect> minEllipse( contours.size() );
00646 
00647     for( size_t i = 0; i < contours.size(); i++ )
00648     { 
00649     //cout << "contours.size " << contours[i].size() << endl;
00650     minRect[i] = minAreaRect( Mat(contours[i]) );
00651     if( contours[i].size() > 5 )
00652     { 
00653         minEllipse[i] = fitEllipse( Mat(contours[i]) ); 
00654     }
00655     }   
00656         
00658 
00660     Mat drawing = Mat::zeros( threshold_output.size(), CV_8UC3 );
00661     
00662     vector<Point> approx;
00663     vector<Point> approx_hull;
00664     vector<vector<Point> >hull( contours.size() );
00665     //travels througth all contours 
00666     for( size_t i = 0; i< contours.size(); i++ )
00667     {
00668     Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
00669               
00670         Point2f rect_points[4]; 
00671         minRect[i].points( rect_points );
00672         vector<double> bbox_points;
00673     bbox_points = sort_points(rect_points);
00674     
00676     control=true;//reset control var
00677 
00678     if(contours[i].size()<7)
00679     {
00680         control=false;// cout << "contours.size()<7" << endl;
00681     }
00683     if(control)if(!validate_contour_Area_Length(contours[i],bbox_points))
00684     {
00685         control=false;// cout << "validate_contour_Area_Length" << endl;
00686     }
00688     if(control)if(!validate_lengths(rect_points)) 
00689     {
00690         control=false;// cout << "validate_lengths" << endl;
00691     }
00693     if(control)if(!validate_corners_arrow(contours[i]))
00694     {
00695         control=false;// cout << "validate_corners_arrow" << endl;
00696     }
00699     if(control)if(!validate_convexHull(contours[i]))
00700     {
00701         control=false;// cout << "validate_convexHull" << endl;
00702     }
00703         
00704     if(control)
00705     {
00706         
00707         //cout << "centro x: " << calculate_center_contour(rect_points,4).x << endl;
00708         //cout << "centro y: " << calculate_center_contour(rect_points,4).y << endl;
00709     //draw point
00710         //Point src_centre;
00711         src_centre=calculate_center_contour(rect_points,4);
00712         
00713         //std::cout << "*******BB_SMALL__****found_point x:" << src_centre.x << "y:" << src_centre.y 
00714                         //<< "cols" << src_tresh.cols<< "rows" << src_tresh.rows <<std::endl;
00715         //src_centre.x = (double)src_tresh.cols/(double)src_centre.x;
00716         //src_centre.y = src_tresh.rows/src_centre.y;
00717         //std::cout << "*******BB_SMALL__****found_point x:" << src_centre.x << "y:" << src_centre.y << std::endl;
00718         found_new_point = true;
00719         ellipse(drawing,Point(round(src_centre.x),round(src_centre.y)),Size 
00720         (1,1),0,0,360,Scalar(102,0,255),3);
00721     //draw rectangle
00722         for( int j = 0; j < 4; j++ )
00723         {
00724             line( drawing, rect_points[j], rect_points[(j+1)%4], color, 1, 8 );
00725         }
00726         
00727     //Draw center of arrow
00728         Moments centre_arrow;
00729         centre_arrow = moments( contours[i], false );
00730 
00731     //  Get the mass centers
00732         Point2f mc;
00733          
00734         mc = Point2f( centre_arrow.m10/centre_arrow.m00 , centre_arrow.m01/centre_arrow.m00 ); 
00735         
00736         ellipse(drawing,mc,Size(1,1),0,0,360,Scalar(255,255,255),3); 
00737         drawContours(drawing, contours, i, Scalar(255, 0, 0), 1, 8);
00738         
00739          
00740     }
00741     }
00742      
00743     threshold_output=drawing;
00744  
00745  return minRect;
00746 }


arrow_detection
Author(s): César Sousa
autogenerated on Thu Nov 20 2014 11:35:16