00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifdef HAVE_OPENCV
00037
00038 #include "SeaBee/VisionRecognizer.H"
00039
00040
00041
00042 VisionRecognizer::VisionRecognizer()
00043 {
00044
00045 }
00046
00047 std::vector<LineSegment2D> VisionRecognizer::getHoughLines( IplImage cannyImage )
00048 {
00049 #ifndef HAVE_OPENCV
00050 LFATAL("OpenCV must be installed in order to use this function");
00051 #else
00052
00053 CvMemStorage* storage = cvCreateMemStorage(0);
00054
00055
00056 CvSeq* cvLines = cvHoughLines2(&cannyImage, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 30, 20, 10);
00057
00058
00059
00060 std::vector <LineSegment2D> lineSegments;
00061
00062
00063 for(int i = 0; i < cvLines->total; i++ )
00064 {
00065
00066 CvPoint* line = (CvPoint*)cvGetSeqElem(cvLines,i);
00067
00068
00069 Point2D<int> pt1 = Point2D<int>(line[0].x,line[0].y);
00070 Point2D<int> pt2 = Point2D<int>(line[1].x,line[1].y);
00071
00072
00073 lineSegments.push_back(LineSegment2D(pt1,pt2));
00074 }
00075 cvReleaseMemStorage( &storage );
00076
00077 return lineSegments;
00078 #endif // HAVE_OPENCV
00079 }
00080
00081
00082
00083 std::vector<LineSegment2D> VisionRecognizer::pruneHoughLines (const std::vector<LineSegment2D> lineSegments)
00084 {
00085 uint numLines = lineSegments.size();
00086 if(numLines == 0) { LDEBUG("No hough lines to prune"); }
00087
00088 std::vector< std::vector<LineSegment2D> > pipeLines;
00089
00090
00091 for(uint r = 0; r < numLines; r++)
00092 {
00093 int lnIndex = -1;
00094
00095
00096 for(uint c = 0; c < pipeLines.size(); c++)
00097 {
00098 LineSegment2D pipeLine = pipeLines[c][0];
00099
00100 if(pipeLine.isValid() && lineSegments[r].angleBetween(pipeLine) < 5*(M_PI/180))
00101 {
00102 lnIndex = c;
00103 break;
00104 }
00105 }
00106
00107
00108 if( lnIndex > 0 )
00109 {
00110 pipeLines[lnIndex].push_back(lineSegments[r]);
00111
00112
00113 Point2D<int> newPt1 =
00114 Point2D<int>(((lineSegments[r].point1().i + pipeLines[lnIndex][0].point1().i)/2),
00115 ((lineSegments[r].point1().j + pipeLines[lnIndex][0].point1().j)/2));
00116
00117 Point2D<int> newPt2 = Point2D<int>(((lineSegments[r].point2().i + pipeLines[lnIndex][0].point2().i)/2),
00118 ((lineSegments[r].point2().j + pipeLines[lnIndex][0].point2().j)/2));
00119
00120 pipeLines[lnIndex][0] = LineSegment2D(newPt1,newPt2);
00121
00122 }
00123
00124 else
00125 {
00126 std::vector<LineSegment2D> newCntrLines;
00127 newCntrLines.push_back(lineSegments[r]);
00128 pipeLines.push_back(newCntrLines);
00129 }
00130 }
00131
00132 std::vector<LineSegment2D> centerPipeLines;
00133
00134 uint pipeLineSize = pipeLines.size();
00135
00136 for(uint c = 0; c < pipeLineSize; c++)
00137 {
00138 centerPipeLines.push_back(pipeLines[c][0]);
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 return centerPipeLines;
00156 }
00157
00158
00159 CvSeq* VisionRecognizer::getContours( IplImage* img )
00160 {
00161
00162 Image< PixRGB<byte> > dispImg(320*2,240*2, ZEROS);
00163
00164 int thresh = 50;
00165
00166 CvMemStorage* storage = 0;
00167
00168
00169 storage = cvCreateMemStorage(0);
00170
00171 CvSeq* contours;
00172 int i, c, l, N = 11;
00173 CvSize sz = cvSize( img->width & -2, img->height & -2 );
00174 IplImage* timg = cvCloneImage( img );
00175 IplImage* gray = cvCreateImage( sz, 8, 1 );
00176 IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );
00177 IplImage* tgray;
00178 CvSeq* result;
00179 double s, t;
00180
00181
00182 CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );
00183
00184
00185
00186 cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height ));
00187
00188
00189 cvPyrDown( timg, pyr, 7 );
00190 cvPyrUp( pyr, timg, 7 );
00191 tgray = cvCreateImage( sz, 8, 1 );
00192
00193
00194 for( c = 0; c < 3; c++ )
00195 {
00196
00197 cvSetImageCOI( timg, c+1 );
00198 cvCopy( timg, tgray, 0 );
00199
00200
00201 for( l = 0; l < N; l++ )
00202 {
00203
00204
00205 if( l == 0 )
00206 {
00207
00208
00209 cvCanny( tgray, gray, 0, thresh, 5 );
00210
00211
00212 cvDilate( gray, gray, 0, 1 );
00213 }
00214 else
00215 {
00216
00217
00218 cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );
00219 }
00220
00221
00222 cvFindContours( gray, storage, &contours, sizeof(CvContour),
00223 CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
00224
00225
00226 while( contours )
00227 {
00228
00229
00230 result = cvApproxPoly( contours, sizeof(CvContour), storage,
00231 CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );
00232
00233
00234
00235
00236
00237
00238 if( result->total == 4 &&
00239 fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 &&
00240 fabs(cvContourArea(result,CV_WHOLE_SEQ)) < 2500 &&
00241 cvCheckContourConvexity(result) )
00242 {
00243 s = 0;
00244
00245
00246
00247 for( i = 0; i < 5; i++ )
00248 {
00249
00250
00251 if( i >= 2 )
00252 {
00253 t = fabs(angle(
00254 (CvPoint*)cvGetSeqElem( result, i ),
00255 (CvPoint*)cvGetSeqElem( result, i-2 ),
00256 (CvPoint*)cvGetSeqElem( result, i-1 )));
00257 s = s > t ? s : t;
00258 }
00259 }
00260
00261
00262
00263
00264 if( s < 0.3 )
00265 for( i = 0; i < 4; i++ )
00266 cvSeqPush( squares,
00267 (CvPoint*)cvGetSeqElem( result, i ));
00268 }
00269
00270
00271 contours = contours->h_next;
00272 }
00273 }
00274 }
00275
00276
00277 inplacePaste(dispImg, toRGB(ipl2gray(gray)), Point2D<int>(0,0));
00278 inplacePaste(dispImg, ipl2rgb(pyr), Point2D<int>(320,0));
00279 inplacePaste(dispImg, toRGB(ipl2gray(tgray)), Point2D<int>(0,240));
00280 inplacePaste(dispImg, ipl2rgb(timg), Point2D<int>(320,240));
00281
00282
00283
00284
00285 cvReleaseImage( &gray );
00286 cvReleaseImage( &pyr );
00287 cvReleaseImage( &tgray );
00288 cvReleaseImage( &timg );
00289
00290 return squares;
00291 }
00292
00293
00294
00295 IplImage VisionRecognizer::getCannyImage( Image<byte> colorSegmentedImage )
00296 {
00297 #ifndef HAVE_OPENCV
00298 LFATAL("OpenCV must be installed in order to use this function");
00299 #else
00300
00301 IplImage *edge = cvCreateImage( cvGetSize( img2ipl( colorSegmentedImage ) ), 8, 1 );
00302 cvCanny( img2ipl( luminance( colorSegmentedImage ) ), edge, 100, 150, 3 );
00303
00304 return *edge;
00305 #endif // HAVE_OPENCV
00306 }
00307
00308
00309
00310
00311 double VisionRecognizer::angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
00312 {
00313 double dx1 = pt1->x - pt0->x;
00314 double dy1 = pt1->y - pt0->y;
00315 double dx2 = pt2->x - pt0->x;
00316 double dy2 = pt2->y - pt0->y;
00317 return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
00318 }
00319
00320 #endif
00321
00322
00323
00324
00325
00326