1 // Copyright (C) 2007-2011 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
22 // File : ShapeRec_FeatureDetector.cxx
23 // Author : Renaud NEDELEC, Open CASCADE S.A.S.
25 #include "ShapeRec_FeatureDetector.hxx"
27 #include "utilities.h"
31 //TODO : All the following methods but ComputeContours use the C API of OpenCV while ComputContours
32 // uses the C++ API of the library.
33 // This should be homogenized and preferably by using the C++ API (which is more recent for all the methods
35 // The code has to be "cleaned up" too
39 \param theFilename - image to process
41 ShapeRec_FeatureDetector::ShapeRec_FeatureDetector():
46 imagePath = ""; //theFilename;
47 // Store the dimensions of the picture
53 Sets the path of the image file to be proccesed
54 \param thePath - Location of the image file
56 void ShapeRec_FeatureDetector::SetPath( const std::string& thePath )
61 IplImage* src = cvLoadImage(imagePath.c_str(),CV_LOAD_IMAGE_COLOR);
62 imgHeight = src->height;
63 imgWidth = src->width;
68 Computes the corners of the image located at imagePath
70 void ShapeRec_FeatureDetector::ComputeCorners(){
72 // Parameters for the corner detection
73 double qualityLevel = 0.2;
74 double minDistance = 1;
76 // Images to be used for detection
77 IplImage *eig_img, *temp_img, *src_img_gray;
80 src_img_gray = cvLoadImage (imagePath.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
84 // If a ROI as been set use it for detection
85 cvSetImageROI( src_img_gray, rect );
88 eig_img = cvCreateImage (cvGetSize (src_img_gray), IPL_DEPTH_32F, 1);
89 temp_img = cvCreateImage (cvGetSize (src_img_gray), IPL_DEPTH_32F, 1);
90 corners = (CvPoint2D32f *) cvAlloc (cornerCount * sizeof (CvPoint2D32f));
92 // image height and width
93 imgHeight = src_img_gray->height;
94 imgWidth = src_img_gray->width;
96 // Corner detection using cvCornerMinEigenVal
97 // (one of the methods available inOpenCV, there is also a cvConerHarris method that can be used by setting a flag in cvGoodFeaturesToTrack)
98 cvGoodFeaturesToTrack (src_img_gray, eig_img, temp_img, corners, &cornerCount, /*quality-level=*/qualityLevel, /*min-distance=*/minDistance);
99 cvFindCornerSubPix (src_img_gray, corners, cornerCount,
100 cvSize (3, 3), cvSize (-1, -1), cvTermCriteria (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03));
102 cvReleaseImage (&eig_img);
103 cvReleaseImage (&temp_img);
104 cvReleaseImage (&src_img_gray);
109 Computes the contours of the image located at imagePath
111 bool ShapeRec_FeatureDetector::ComputeContours( int detection_method ){
113 // Initialising images
118 src = imread( imagePath.c_str() );
122 if ( detection_method == CANNY ) // The problem is that with that filter the detector detects double contours
124 // Thresholds for Canny detector
125 int lowThreshold = 100;
127 int kernel_size = 3; // 3,5 or 7
129 // Convert the image to grayscale
130 if (src.channels() == 3)
131 cvtColor( src, src_gray, CV_BGR2GRAY );
132 else if (src.channels() == 1)
135 // Reduce noise with a kernel 3x3
136 blur( src_gray, detected_edges, Size(3,3) );
138 Canny( detected_edges, detected_edges, lowThreshold, lowThreshold*ratio, kernel_size, /*L2gradient =*/true );
140 else if ( detection_method == COLORFILTER )
142 if ( !rect.width > 1 )
144 detected_edges = _colorFiltering();
146 else if ( detection_method == RIDGE_DETECTOR ) // Method adapted for engineering drawings (e.g. watershed functionnality could be used here cf.OpenCV documentation and samples)
151 _detectAndRetrieveContours( detected_edges );
158 Computes the lines in the image located at imagePath
160 bool ShapeRec_FeatureDetector::ComputeLines(){
161 MESSAGE("ShapeRec_FeatureDetector::ComputeLines()")
162 // Initialising images
163 Mat src, src_gray, detected_edges, dst;
165 src=imread(imagePath.c_str(), 0);
167 Canny( src, dst, 50, 200, 3 );
168 HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 );
174 Stores a region of interest given by user in rect
175 \param theRect - Region Of Interest of the image located at imagePath
177 void ShapeRec_FeatureDetector::SetROI( const QRect& theRect )
179 if (!theRect.isEmpty()){
180 rect = cvRect(theRect.x(),theRect.y(),theRect.width(),theRect.height());
185 Crops the image located at imagePath to the region of interest given by the user via SetROI
186 and stores the result in /tmp
187 \param theRect - Region Of Interest of the image located at imagePath
189 std::string ShapeRec_FeatureDetector::CroppImage()
191 IplImage* src = cvLoadImage(imagePath.c_str(),CV_LOAD_IMAGE_COLOR);
193 cvSetImageROI(src, rect);
194 IplImage* cropped_image = cvCreateImage(cvGetSize(src),
197 cvCopy(src, cropped_image, NULL);
198 cvResetImageROI(src);
200 cvSaveImage ("/tmp/cropped_image.bmp", cropped_image);
202 return "/tmp/cropped_image.bmp";
207 Performs contours detection and store them in contours
208 \param src - src image to find contours of
210 void ShapeRec_FeatureDetector::_detectAndRetrieveContours( Mat src )
213 int method = CV_CHAIN_APPROX_NONE;
214 findContours( src, contours, hierarchy,CV_RETR_CCOMP, method);
215 // Other possible approximations CV_CHAIN_APPROX_TC89_KCOS, CV_CHAIN_APPROX_TC89_L1, CV_CHAIN_APPROX_SIMPLE cf. OpenCV documentation
216 // for precise information
220 Performs color filtering from the image sample contained in the ROI rect of the image
222 Thresholds the result in order ot obtain a binary image
223 \return binary image resulting from filtering and thersholding
225 Mat ShapeRec_FeatureDetector::_colorFiltering()
227 IplImage* find_image = cvLoadImage(imagePath.c_str(),CV_LOAD_IMAGE_COLOR);
228 // Reduce noise with a kernel 3x3
229 cvSmooth( find_image, find_image, CV_GAUSSIAN, 3, 3 );
231 if ( !rect.width > 1 )
232 return Mat(find_image);
234 // Crop the image to build an histogram from the selected part
235 cvSetImageROI(find_image, rect);
236 IplImage* test_image = cvCreateImage(cvGetSize(find_image),
238 find_image->nChannels);
239 cvCopy(find_image, test_image, NULL);
240 cvResetImageROI(find_image);
242 IplImage* test_hsv = cvCreateImage(cvGetSize(test_image),8,3);
243 IplImage* test_hue = cvCreateImage(cvGetSize(test_image),8,1);
246 cvCvtColor(test_image, test_hsv, CV_BGR2HSV);
247 cvCvtPixToPlane(test_hsv, test_hue, 0, 0, 0);
251 float hranges[] = {0, 180};
252 float* ranges = hranges;
253 hist = cvCreateHist(1, &size_hist, CV_HIST_ARRAY, &ranges, 1);
255 //calculate hue` histogram
256 cvCalcHist(&test_hue, hist, 0 ,0);
258 // // TEST print of the histogram for debugging
259 // IplImage* hist_image = cvCreateImage(cvSize(320,300),8,3);
261 // //draw hist on hist_test image.
262 // cvZero(hist_image);
263 // float max_value = 0;
264 // cvGetMinMaxHistValue(hist, 0 , &max_value, 0, 0);
265 // int bin_w = hist_image->width/size_hist;
266 // for(int i = 0; i < size_hist; i++ )
268 // //prevent overflow
269 // int val = cvRound( cvGetReal1D(hist->bins,i)*hist_image->
270 // height/max_value);
271 // CvScalar color = CV_RGB(200,0,0);
272 // //hsv2rgb(i*180.f/size_hist);
273 // cvRectangle( hist_image, cvPoint(i*bin_w,hist_image->height),
274 // cvPoint((i+1)*bin_w,hist_image->height - val),
275 // color, -1, 8, 0 );
279 // cvNamedWindow("hist", 1); cvShowImage("hist",hist_image);
282 //calculate back projection of hue plane of input image
283 IplImage* backproject = cvCreateImage(cvGetSize(find_image), 8, 1);
284 IplImage* binary_backproject = cvCreateImage(cvGetSize(find_image), 8, 1);
285 IplImage* find_hsv = cvCreateImage(cvGetSize(find_image),8,3);
286 IplImage* find_hue = cvCreateImage(cvGetSize(find_image),8,1);
288 cvCvtColor(find_image, find_hsv, CV_BGR2HSV);
289 cvCvtPixToPlane(find_hsv, find_hue, 0, 0, 0);
290 cvCalcBackProject(&find_hue, backproject, hist);
292 // Threshold in order to obtain binary image
293 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)
294 cvReleaseImage(&test_image);
295 cvReleaseImage(&test_hsv);
296 cvReleaseImage(&test_hue);
297 cvReleaseImage(&backproject);
299 return Mat(binary_backproject);