1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : ShapeRec_FeatureDetector.cxx
24 // Author : Renaud NEDELEC, Open CASCADE S.A.S.
26 #include "ShapeRec_FeatureDetector.hxx"
28 #include "utilities.h"
30 // TODO : All the following methods but ComputeContours use the C API of OpenCV while ComputContours
31 // uses the C++ API of the library.
32 // This should be homogenized and preferably by using the C++ API (which is more recent for all the methods
34 // The code has to be "cleaned up" too
38 \param theFilename - image to process
40 ShapeRec_FeatureDetector::ShapeRec_FeatureDetector():
45 imagePath = ""; //theFilename;
46 // Store the dimensions of the picture
52 Sets the path of the image file to be processed
53 \param thePath - Location of the image file
55 void ShapeRec_FeatureDetector::SetPath( const std::string& thePath )
60 IplImage* src = cvLoadImage(imagePath.c_str(),CV_LOAD_IMAGE_COLOR);
61 imgHeight = src->height;
62 imgWidth = src->width;
67 Computes the corners of the image located at imagePath
69 void ShapeRec_FeatureDetector::ComputeCorners( bool useROI, ShapeRec_Parameters* parameters ){
70 ShapeRec_CornersParameters* aCornersParameters = dynamic_cast<ShapeRec_CornersParameters*>( parameters );
71 if ( !aCornersParameters ) aCornersParameters = new ShapeRec_CornersParameters();
73 // Images to be used for detection
74 IplImage *eig_img, *temp_img, *src_img_gray;
77 src_img_gray = cvLoadImage (imagePath.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
81 // If a ROI as been set use it for detection
82 cvSetImageROI( src_img_gray, rect );
85 eig_img = cvCreateImage (cvGetSize (src_img_gray), IPL_DEPTH_32F, 1);
86 temp_img = cvCreateImage (cvGetSize (src_img_gray), IPL_DEPTH_32F, 1);
87 corners = (CvPoint2D32f *) cvAlloc (cornerCount * sizeof (CvPoint2D32f));
89 // image height and width
90 imgHeight = src_img_gray->height;
91 imgWidth = src_img_gray->width;
93 // Corner detection using cvCornerMinEigenVal
94 // (one of the methods available inOpenCV, there is also a cvConerHarris method that can be used by setting a flag in cvGoodFeaturesToTrack)
95 cvGoodFeaturesToTrack (src_img_gray, eig_img, temp_img, corners, &cornerCount, aCornersParameters->qualityLevel, aCornersParameters->minDistance);
96 cvFindCornerSubPix (src_img_gray, corners, cornerCount, cvSize (aCornersParameters->kernelSize, aCornersParameters->kernelSize), cvSize (-1, -1),
97 cvTermCriteria (aCornersParameters->typeCriteria, aCornersParameters->maxIter, aCornersParameters->epsilon));
99 cvReleaseImage (&eig_img);
100 cvReleaseImage (&temp_img);
101 cvReleaseImage (&src_img_gray);
106 Computes the contours of the image located at imagePath
108 bool ShapeRec_FeatureDetector::ComputeContours( bool useROI, ShapeRec_Parameters* parameters ){
110 // Initialising images
111 cv::Mat src, src_gray;
112 cv::Mat detected_edges;
115 src = cv::imread( imagePath.c_str() );
119 if ( !useROI ) // CANNY: The problem is that with that filter the detector detects double contours
121 // Convert the image to grayscale
122 if (src.channels() == 3)
123 cv::cvtColor( src, src_gray, CV_BGR2GRAY );
124 else if (src.channels() == 1)
127 ShapeRec_CannyParameters* aCannyParameters = dynamic_cast<ShapeRec_CannyParameters*>( parameters );
128 if ( !aCannyParameters ) aCannyParameters = new ShapeRec_CannyParameters();
131 blur( src_gray, detected_edges, cv::Size( aCannyParameters->kernelSize, aCannyParameters->kernelSize ) );
133 Canny( detected_edges, detected_edges, aCannyParameters->lowThreshold, aCannyParameters->lowThreshold * aCannyParameters->ratio,
134 aCannyParameters->kernelSize, aCannyParameters->L2gradient );
138 IplImage* find_image = cvLoadImage(imagePath.c_str(),CV_LOAD_IMAGE_COLOR);
140 ShapeRec_ColorFilterParameters* aColorFilterParameters = dynamic_cast<ShapeRec_ColorFilterParameters*>( parameters );
141 if ( !aColorFilterParameters ) aColorFilterParameters = new ShapeRec_ColorFilterParameters();
144 cvSmooth( find_image, find_image, CV_GAUSSIAN, aColorFilterParameters->smoothSize, aColorFilterParameters->smoothSize );
146 // Crop the image to build an histogram from the selected part
147 cvSetImageROI(find_image, rect);
148 IplImage* test_image = cvCreateImage(cvGetSize(find_image),
150 find_image->nChannels);
151 cvCopy(find_image, test_image, NULL);
152 cvResetImageROI(find_image);
154 IplImage* test_hsv = cvCreateImage(cvGetSize(test_image),8,3);
155 IplImage* h_plane = cvCreateImage( cvGetSize(test_image), 8, 1 );
156 IplImage* s_plane = cvCreateImage( cvGetSize(test_image), 8, 1 );
159 cvCvtColor(test_image, test_hsv, CV_BGR2HSV);
161 cvCvtPixToPlane(test_hsv, h_plane, s_plane, 0, 0);
162 IplImage* planes[] = { h_plane, s_plane };
165 float hranges[] = { 0, 180 };
166 float sranges[] = { 0, 256 };
167 float* ranges[] = { hranges, sranges };
168 hist = cvCreateHist( 2, aColorFilterParameters->histSize, aColorFilterParameters->histType, ranges );
170 //calculate hue /saturation histogram
171 cvCalcHist(planes, hist, 0 ,0);
173 // // TEST print of the histogram for debugging
174 // IplImage* hist_image = cvCreateImage(cvSize(320,300),8,3);
176 // //draw hist on hist_test image.
177 // cvZero(hist_image);
178 // float max_value = 0;
179 // cvGetMinMaxHistValue(hist, 0 , &max_value, 0, 0);
180 // int bin_w = hist_image->width/size_hist;
181 // for(int i = 0; i < size_hist; i++ )
183 // //prevent overflow
184 // int val = cvRound( cvGetReal1D(hist->bins,i)*hist_image->
185 // height/max_value);
186 // CvScalar color = CV_RGB(200,0,0);
187 // //hsv2rgb(i*180.f/size_hist);
188 // cvRectangle( hist_image, cvPoint(i*bin_w,hist_image->height),
189 // cvPoint((i+1)*bin_w,hist_image->height - val),
190 // color, -1, 8, 0 );
194 // cvNamedWindow("hist", 1); cvShowImage("hist",hist_image);
197 //calculate back projection of hue and saturation planes of input image
198 IplImage* backproject = cvCreateImage(cvGetSize(test_image), 8, 1);
199 IplImage* binary_backproject = cvCreateImage(cvGetSize(test_image), 8, 1);
200 cvCalcBackProject(planes, backproject, hist);
202 // Threshold in order to obtain binary image
203 cvThreshold(backproject, binary_backproject, aColorFilterParameters->threshold, aColorFilterParameters->maxThreshold, CV_THRESH_BINARY);
204 cvReleaseImage(&test_image);
205 cvReleaseImage(&test_hsv);
206 cvReleaseImage(&h_plane);
207 cvReleaseImage(&s_plane);
208 cvReleaseImage(&find_image);
209 cvReleaseImage(&backproject);
211 detected_edges = cv::Mat(binary_backproject);
213 // else if ( detection_method == RIDGE_DETECTOR ) // Method adapted for engineering drawings (e.g. watershed functionnality could be used here cf.OpenCV documentation and samples)
219 // _detectAndRetrieveContours( detected_edges, parameters->findContoursMethod );
220 detected_edges = detected_edges > 1;
221 findContours( detected_edges, contours, hierarchy, CV_RETR_CCOMP, parameters->findContoursMethod, useROI ? cvPoint(rect.x,rect.y) : cvPoint(0,0) );
228 Computes the lines in the image located at imagePath
230 bool ShapeRec_FeatureDetector::ComputeLines(){
231 MESSAGE("ShapeRec_FeatureDetector::ComputeLines()")
232 // Initialising images
233 cv::Mat src, src_gray, detected_edges, dst;
235 src=cv::imread(imagePath.c_str(), 0);
237 Canny( src, dst, 50, 200, 3 );
238 HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 );
244 Stores a region of interest given by user in rect
245 \param theRect - Region Of Interest of the image located at imagePath
247 void ShapeRec_FeatureDetector::SetROI( const QRect& theRect )
249 if (!theRect.isEmpty()){
250 rect = cvRect(theRect.x(),theRect.y(),theRect.width(),theRect.height());
255 Crops the image located at imagePath to the region of interest given by the user via SetROI
256 and stores the result in /tmp
257 \param theRect - Region Of Interest of the image located at imagePath
259 std::string ShapeRec_FeatureDetector::CroppImage()
261 IplImage* src = cvLoadImage(imagePath.c_str(),CV_LOAD_IMAGE_COLOR);
263 cvSetImageROI(src, rect);
264 IplImage* cropped_image = cvCreateImage(cvGetSize(src),
267 cvCopy(src, cropped_image, NULL);
268 cvResetImageROI(src);
270 cvSaveImage ("/tmp/cropped_image.bmp", cropped_image);
272 return "/tmp/cropped_image.bmp";
276 \class ShapeRec_CornersParameters
277 \brief Parameters for the corners detection
279 ShapeRec_CornersParameters::ShapeRec_CornersParameters()
283 typeCriteria = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;
287 ShapeRec_CornersParameters::~ShapeRec_CornersParameters()
292 \class ShapeRec_Parameters
293 \brief Parameters for the contour/corners detection
295 ShapeRec_Parameters::ShapeRec_Parameters()
298 findContoursMethod = CV_CHAIN_APPROX_NONE;
300 ShapeRec_Parameters::~ShapeRec_Parameters()
305 \class ShapeRec_CannyParameters
306 \brief Parameters for the contour detection
308 ShapeRec_CannyParameters::ShapeRec_CannyParameters()
310 lowThreshold = 100; // is used for edge linking.
311 ratio = 3; // lowThreshold*ratio is used to find initial segments of strong edges
312 L2gradient = true; // norm L2 or L1
315 ShapeRec_CannyParameters::~ShapeRec_CannyParameters()
320 \class ShapeRec_ColorFilterParameters
321 \brief Parameters for the contour detection
323 ShapeRec_ColorFilterParameters::ShapeRec_ColorFilterParameters()
325 smoothSize = 3; // The parameter of the smoothing operation, the aperture width. Must be a positive odd number
326 histSize = new int[2]; // array of the histogram dimension sizes
327 histSize[0] = 30; // hbins
328 histSize[1] = 32; // sbins
329 histType = CV_HIST_ARRAY; // histogram representation format
330 threshold = 128; // threshold value
331 maxThreshold = 255; // maximum value to use with the THRESH_BINARY thresholding types
334 ShapeRec_ColorFilterParameters::~ShapeRec_ColorFilterParameters()