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 #include "Component/ModelManager.H"
00037
00038 #include "Media/FrameSeries.H"
00039 #include "Transport/FrameIstream.H"
00040 #include "Transport/FrameInfo.H"
00041 #include "Media/MediaOpts.H"
00042
00043 #include "Image/Image.H"
00044 #include "Image/Pixels.H"
00045 #include "Raster/Raster.H"
00046 #include "Image/CutPaste.H"
00047 #include "Image/OpenCVUtil.H"
00048
00049 #include "BeoSub/IsolateColor.H"
00050 #include "Image/DrawOps.H"
00051 #include "Image/ColorOps.H"
00052
00053 #include "GUI/XWinManaged.H"
00054
00055 #ifndef HAVE_OPENCV
00056 LFATAL("OpenCV must be installed in order to use this function");
00057 #else
00058
00059 int thresh = 50;
00060
00061
00062
00063
00064 double angle( CvPoint* pt1, CvPoint* pt2, CvPoint* pt0 )
00065 {
00066 double dx1 = pt1->x - pt0->x;
00067 double dy1 = pt1->y - pt0->y;
00068 double dx2 = pt2->x - pt0->x;
00069 double dy2 = pt2->y - pt0->y;
00070 return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
00071 }
00072
00073
00074
00075 CvSeq* findSquares4( IplImage* img, CvMemStorage* storage )
00076 {
00077 CvSeq* contours;
00078 int i, c, l, N = 11;
00079 CvSize sz = cvSize( img->width & -2, img->height & -2 );
00080 IplImage* timg = cvCloneImage( img );
00081 IplImage* gray = cvCreateImage( sz, 8, 1 );
00082 IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8, 3 );
00083 IplImage* tgray;
00084 CvSeq* result;
00085 double s, t;
00086
00087
00088 CvSeq* squares = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage );
00089
00090
00091
00092 cvSetImageROI( timg, cvRect( 0, 0, sz.width, sz.height ));
00093
00094
00095 cvPyrDown( timg, pyr, 7 );
00096 cvPyrUp( pyr, timg, 7 );
00097 tgray = cvCreateImage( sz, 8, 1 );
00098
00099
00100 for( c = 0; c < 3; c++ )
00101 {
00102
00103 cvSetImageCOI( timg, c+1 );
00104 cvCopy( timg, tgray, 0 );
00105
00106
00107 for( l = 0; l < N; l++ )
00108 {
00109
00110
00111 if( l == 0 )
00112 {
00113
00114
00115 cvCanny( tgray, gray, 0, thresh, 5 );
00116
00117
00118 cvDilate( gray, gray, 0, 1 );
00119 }
00120 else
00121 {
00122
00123
00124 cvThreshold( tgray, gray, (l+1)*255/N, 255, CV_THRESH_BINARY );
00125 }
00126
00127
00128 cvFindContours( gray, storage, &contours, sizeof(CvContour),
00129 CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0) );
00130
00131
00132 while( contours )
00133 {
00134
00135
00136 result = cvApproxPoly( contours, sizeof(CvContour), storage,
00137 CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0 );
00138
00139
00140
00141
00142
00143
00144 if( result->total == 4 &&
00145 fabs(cvContourArea(result,CV_WHOLE_SEQ)) > 1000 &&
00146 cvCheckContourConvexity(result) )
00147 {
00148 s = 0;
00149
00150 for( i = 0; i < 5; i++ )
00151 {
00152
00153
00154 if( i >= 2 )
00155 {
00156 t = fabs(angle(
00157 (CvPoint*)cvGetSeqElem( result, i ),
00158 (CvPoint*)cvGetSeqElem( result, i-2 ),
00159 (CvPoint*)cvGetSeqElem( result, i-1 )));
00160 s = s > t ? s : t;
00161 }
00162 }
00163
00164
00165
00166
00167 if( s < 0.3 )
00168 for( i = 0; i < 4; i++ )
00169 cvSeqPush( squares,
00170 (CvPoint*)cvGetSeqElem( result, i ));
00171 }
00172
00173
00174 contours = contours->h_next;
00175 }
00176 }
00177 }
00178
00179
00180 cvReleaseImage( &gray );
00181 cvReleaseImage( &pyr );
00182 cvReleaseImage( &tgray );
00183 cvReleaseImage( &timg );
00184
00185 return squares;
00186 }
00187
00188
00189
00190 void drawSquares( IplImage* img, IplImage* out, CvSeq* squares )
00191 {
00192 CvSeqReader reader;
00193 int i;
00194
00195
00196 cvStartReadSeq( squares, &reader, 0 );
00197
00198
00199 for( i = 0; i < squares->total; i += 4 )
00200 {
00201 CvPoint pt[4], *rect = pt;
00202 int count = 4;
00203
00204
00205 CV_READ_SEQ_ELEM( pt[0], reader );
00206 CV_READ_SEQ_ELEM( pt[1], reader );
00207 CV_READ_SEQ_ELEM( pt[2], reader );
00208 CV_READ_SEQ_ELEM( pt[3], reader );
00209
00210
00211 cvPolyLine( out, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
00212 }
00213
00214 }
00215
00216 int main(int argc, char* argv[])
00217 {
00218
00219 MYLOGVERB = LOG_INFO;
00220
00221 ModelManager manager("CVContour Tester");
00222
00223 nub::soft_ref<InputFrameSeries> ifs(new InputFrameSeries(manager));
00224 manager.addSubComponent(ifs);
00225
00226 nub::soft_ref<OutputFrameSeries> ofs(new OutputFrameSeries(manager));
00227 manager.addSubComponent(ofs);
00228
00229 manager.exportOptions(MC_RECURSE);
00230
00231
00232 if (manager.parseCommandLine(argc, argv,
00233 "[image {*.ppm}]",
00234 0, 1)
00235 == false) return(1);
00236
00237 int w = ifs->getWidth(), h = ifs->getHeight();
00238 std::string dims = convertToString(Dims(w, h));
00239 LINFO("image size: [%dx%d]", w, h);
00240 manager.setOptionValString(&OPT_InputFrameDims, dims);
00241
00242 manager.setModelParamVal("InputFrameDims", Dims(w, h),
00243 MC_RECURSE | MC_IGNORE_MISSING);
00244
00245 manager.start();
00246
00247 bool goforever = true;
00248
00249 rutz::shared_ptr<XWinManaged> dispWin;
00250 dispWin.reset(new XWinManaged(Dims(w*2,h*2), 0, 0, "Contour Display"));
00251
00252
00253 Image< PixRGB<byte> > img(w,h, ZEROS);
00254
00255
00256 IplImage* iplImg = 0;
00257 IplImage* out = 0;
00258 CvMemStorage* storage = 0;
00259
00260 bool createMovie = true;
00261
00262 while(goforever)
00263 {
00264 Image< PixRGB<byte> > dispImg(w*2,h*2, ZEROS);
00265
00266 ifs->updateNext(); img = ifs->readRGB();
00267 if(!img.initialized()) {Raster::waitForKey(); break; }
00268
00269
00270 storage = cvCreateMemStorage(0);
00271
00272 iplImg = cvCloneImage( img2ipl(img) );
00273 out = cvCloneImage( img2ipl(img) );
00274
00275
00276 drawSquares( iplImg, out, findSquares4( iplImg, storage ) );
00277
00278 inplacePaste(dispImg, ipl2rgb(out), Point2D<int>(w,0));
00279 dispWin->drawImage(dispImg, 0, 0);
00280
00281
00282 if(createMovie)
00283 {
00284 ofs->writeRGB(ipl2rgb(out), "test-CVcontour_Display",
00285 FrameInfo("test-CVcontour_Display", SRC_POS));
00286 }
00287
00288
00289
00290
00291
00292 cvReleaseImage( &iplImg );
00293 cvReleaseImage( &out );
00294
00295
00296 cvClearMemStorage( storage );
00297 }
00298
00299
00300 manager.stop();
00301 return 0;
00302 }
00303 #endif // HAVE_OPENCV
00304
00305
00306
00307
00308
00309
00310