Back to index

salome-geom  6.5.0
ShapeRec_FeatureDetector.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 // File   : ShapeRec_FeatureDetector.cxx
00024 // Author : Renaud NEDELEC, Open CASCADE S.A.S.
00025 
00026 #include "ShapeRec_FeatureDetector.hxx"
00027 #include <stdio.h>
00028 #include "utilities.h"
00029 
00030 using namespace cv;
00031 
00032 //TODO : All the following methods but ComputeContours use the C API of OpenCV while ComputContours
00033 // uses the C++ API of the library.
00034 // This should be homogenized and preferably by using the C++ API (which is more recent for all the methods
00035 
00036 // The code has to be "cleaned up" too
00037 
00042 ShapeRec_FeatureDetector::ShapeRec_FeatureDetector(): 
00043   corners()
00044 {
00045   cornerCount = 2000;
00046   rect=cvRect(0,0,0,0);
00047   imagePath = ""; //theFilename;
00048   // Store the dimensions of the picture
00049   imgHeight = 0;
00050   imgWidth  = 0;
00051 }
00052 
00057 void ShapeRec_FeatureDetector::SetPath( const std::string& thePath )
00058 {
00059   imagePath = thePath; 
00060   if (imagePath != "")
00061   {
00062     IplImage* src = cvLoadImage(imagePath.c_str(),CV_LOAD_IMAGE_COLOR);
00063     imgHeight = src->height;
00064     imgWidth = src->width; 
00065   }
00066 }
00067 
00071 void ShapeRec_FeatureDetector::ComputeCorners(){
00072   
00073   // Parameters for the corner detection
00074   double qualityLevel = 0.2;
00075   double minDistance = 1;
00076  
00077   // Images to be used for detection
00078   IplImage *eig_img, *temp_img, *src_img_gray;
00079   
00080   // Load image
00081   src_img_gray = cvLoadImage (imagePath.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
00082   
00083   if ( rect.width > 1 )
00084   {
00085     // If a ROI as been set use it for detection
00086     cvSetImageROI( src_img_gray, rect );
00087   }
00088   
00089   eig_img = cvCreateImage (cvGetSize (src_img_gray), IPL_DEPTH_32F, 1);
00090   temp_img = cvCreateImage (cvGetSize (src_img_gray), IPL_DEPTH_32F, 1);
00091   corners = (CvPoint2D32f *) cvAlloc (cornerCount * sizeof (CvPoint2D32f));
00092   
00093   // image height and width
00094   imgHeight = src_img_gray->height;
00095   imgWidth  = src_img_gray->width;
00096 
00097   // Corner detection using cvCornerMinEigenVal 
00098   // (one of the methods available inOpenCV, there is also a cvConerHarris method that can be used by setting a flag in cvGoodFeaturesToTrack)
00099   cvGoodFeaturesToTrack (src_img_gray, eig_img, temp_img, corners, &cornerCount, /*quality-level=*/qualityLevel, /*min-distance=*/minDistance);
00100   cvFindCornerSubPix (src_img_gray, corners, cornerCount,
00101                     cvSize (3, 3), cvSize (-1, -1), cvTermCriteria (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03));
00102 
00103   cvReleaseImage (&eig_img);
00104   cvReleaseImage (&temp_img);
00105   cvReleaseImage (&src_img_gray);
00106 
00107 }
00108 
00112 bool ShapeRec_FeatureDetector::ComputeContours( int detection_method ){
00113  
00114   // Initialising images
00115   Mat src, src_gray;
00116   Mat detected_edges;
00117   
00118   // Read image
00119   src = imread( imagePath.c_str() );
00120   if( !src.data )
00121     return false; 
00122   
00123   if ( detection_method == CANNY )   // The problem is that with that filter the detector detects double contours
00124   {   
00125     // Thresholds for Canny detector
00126     int lowThreshold = 100;
00127     int ratio = 3;
00128     int kernel_size = 3; // 3,5 or 7
00129     
00130     // Convert the image to grayscale
00131     if (src.channels() == 3)
00132       cvtColor( src, src_gray, CV_BGR2GRAY );
00133     else if (src.channels() == 1)
00134       src_gray = src;
00135   
00136     // Reduce noise with a kernel 3x3               
00137     blur( src_gray, detected_edges, Size(3,3) );
00138     // Canny detector
00139     Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size, /*L2gradient =*/true );      
00140   }
00141   else if ( detection_method == COLORFILTER )
00142   {
00143     if ( !rect.width > 1 )
00144       return false;
00145     detected_edges = _colorFiltering();
00146   }
00147   else if ( detection_method == RIDGE_DETECTOR )  // Method adapted for engineering drawings (e.g. watershed functionnality could be used here cf.OpenCV documentation and samples)
00148   {
00149     // TODO
00150     return false;
00151   }
00152   _detectAndRetrieveContours( detected_edges );
00153   
00154   return true;
00155   
00156 }
00157 
00161 bool ShapeRec_FeatureDetector::ComputeLines(){
00162   MESSAGE("ShapeRec_FeatureDetector::ComputeLines()")
00163   // Initialising images
00164   Mat src, src_gray, detected_edges, dst;
00165   
00166   src=imread(imagePath.c_str(), 0);
00167   
00168   Canny( src, dst, 50, 200, 3 );
00169   HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 );
00170   return true;
00171   
00172 }
00173 
00178 void ShapeRec_FeatureDetector::SetROI( const QRect& theRect )
00179 {
00180   if (!theRect.isEmpty()){
00181     rect = cvRect(theRect.x(),theRect.y(),theRect.width(),theRect.height());
00182   }
00183 }
00184 
00190 std::string ShapeRec_FeatureDetector::CroppImage()
00191 {
00192   IplImage* src = cvLoadImage(imagePath.c_str(),CV_LOAD_IMAGE_COLOR);
00193  
00194   cvSetImageROI(src, rect);
00195   IplImage* cropped_image = cvCreateImage(cvGetSize(src),
00196                                           src->depth,
00197                                           src->nChannels);
00198   cvCopy(src, cropped_image, NULL);
00199   cvResetImageROI(src);
00200   
00201   cvSaveImage ("/tmp/cropped_image.bmp", cropped_image);
00202   
00203   return "/tmp/cropped_image.bmp";
00204 }
00205 
00206 
00211 void ShapeRec_FeatureDetector::_detectAndRetrieveContours( Mat binaryImg )
00212 {
00213   binaryImg = binaryImg > 1; 
00214   int method = CV_CHAIN_APPROX_NONE;
00215   findContours( binaryImg, contours, hierarchy,CV_RETR_CCOMP, method);
00216   // Other possible approximations CV_CHAIN_APPROX_TC89_KCOS, CV_CHAIN_APPROX_TC89_L1, CV_CHAIN_APPROX_SIMPLE cf. OpenCV documentation 
00217   // for precise information
00218 }
00219 
00226 Mat ShapeRec_FeatureDetector::_colorFiltering()
00227 {  
00228   IplImage* find_image = cvLoadImage(imagePath.c_str(),CV_LOAD_IMAGE_COLOR);
00229   // Reduce noise with a kernel 3x3               
00230   cvSmooth( find_image, find_image, CV_GAUSSIAN, 3, 3 );
00231   
00232   if ( !rect.width > 1 )
00233     return Mat(find_image);
00234   
00235   // Crop the image to build an histogram from the selected part
00236   cvSetImageROI(find_image, rect);
00237   IplImage* test_image = cvCreateImage(cvGetSize(find_image),
00238                                        find_image->depth,
00239                                        find_image->nChannels);
00240   cvCopy(find_image, test_image, NULL);
00241   cvResetImageROI(find_image);
00242   
00243   IplImage* test_hsv = cvCreateImage(cvGetSize(test_image),8,3);
00244   IplImage* h_plane = cvCreateImage( cvGetSize(test_image), 8, 1 );
00245   IplImage* s_plane = cvCreateImage( cvGetSize(test_image), 8, 1 );
00246   CvHistogram* hist;
00247 
00248   cvCvtColor(test_image, test_hsv, CV_BGR2HSV);
00249   
00250   cvCvtPixToPlane(test_hsv, h_plane, s_plane, 0, 0);
00251   IplImage* planes[] = { h_plane, s_plane };
00252   
00253   //create hist
00254   int hbins = 30, sbins = 32;                        // TODO think to the best values here
00255   int   hist_size[] = { hbins, sbins };
00256   float hranges[] = { 0, 180 };
00257   float sranges[] = { 0, 255 };
00258   float* ranges[] = { hranges, sranges };
00259   hist = cvCreateHist(2, hist_size, CV_HIST_ARRAY, ranges, 1);
00260   
00261   //calculate hue /saturation histogram
00262   cvCalcHist(planes, hist, 0 ,0);
00263 
00264 //   // TEST print of the histogram for debugging
00265 //   IplImage* hist_image = cvCreateImage(cvSize(320,300),8,3);
00266 //   
00267 //   //draw hist on hist_test image.
00268 //   cvZero(hist_image);
00269 //   float max_value = 0;
00270 //   cvGetMinMaxHistValue(hist, 0 , &max_value, 0, 0);
00271 //   int bin_w = hist_image->width/size_hist;
00272 //   for(int i = 0; i < size_hist; i++ )
00273 //   {
00274 //     //prevent overflow
00275 //     int val = cvRound( cvGetReal1D(hist->bins,i)*hist_image->
00276 //     height/max_value);
00277 //     CvScalar color = CV_RGB(200,0,0);
00278 //     //hsv2rgb(i*180.f/size_hist);
00279 //     cvRectangle( hist_image, cvPoint(i*bin_w,hist_image->height),
00280 //     cvPoint((i+1)*bin_w,hist_image->height - val),
00281 //     color, -1, 8, 0 );
00282 //   }
00283 //  
00284 //    
00285 //   cvNamedWindow("hist", 1); cvShowImage("hist",hist_image);
00286   
00287   
00288   //calculate back projection of hue and saturation planes of input image
00289   IplImage* backproject = cvCreateImage(cvGetSize(find_image), 8, 1);
00290   IplImage* binary_backproject = cvCreateImage(cvGetSize(find_image), 8, 1);
00291   IplImage* find_hsv = cvCreateImage(cvGetSize(find_image),8,3);
00292   IplImage* find_hplane = cvCreateImage(cvGetSize(find_image),8,1);
00293   IplImage* find_splane = cvCreateImage(cvGetSize(find_image),8,1);
00294   
00295   cvCvtColor(find_image, find_hsv, CV_BGR2HSV);
00296   cvCvtPixToPlane(find_hsv, find_hplane, find_splane, 0, 0);
00297   IplImage* find_planes[] = { find_hplane, find_splane };
00298   cvCalcBackProject(find_planes, backproject, hist);
00299   
00300   // Threshold in order to obtain binary image
00301   cvThreshold(backproject, binary_backproject, 1, 255, CV_THRESH_BINARY);  // NOTE it would be good to think about the best threshold to use (it's 1 for now)
00302   cvReleaseImage(&test_image);
00303   cvReleaseImage(&test_hsv);
00304   cvReleaseImage(&h_plane);
00305   cvReleaseImage(&s_plane);
00306   cvReleaseImage(&find_image);
00307   cvReleaseImage(&find_hsv);
00308   cvReleaseImage(&find_hplane);
00309   cvReleaseImage(&find_splane);
00310   cvReleaseImage(&backproject);
00311   
00312   return Mat(binary_backproject);
00313 }