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 "Image/OpenCVUtil.H"
00037
00038 #include "GUI/XWinManaged.H"
00039
00040 #include "Image/Pixels.H"
00041 #include "Raster/Raster.H"
00042
00043 #include "Util/Timer.H"
00044 #include "Util/Types.H"
00045 #include "Util/log.H"
00046
00047 #include "Image/ColorOps.H"
00048 #include "Image/CutPaste.H"
00049 #include "Image/MathOps.H"
00050 #include "Image/DrawOps.H"
00051 #include "Image/FilterOps.H"
00052 #include "Image/Transforms.H"
00053
00054 #include "BeoSub/hysteresis.H"
00055 #include "VFAT/segmentImageTrackMC.H"
00056 #include "BeoSub/HoughTransform.H"
00057 #include "BeoSub/ColorTracker.H"
00058 #include "BeoSub/CannyEdge.H"
00059
00060 #include "rutz/compat_cmath.h"
00061
00062 #include "BeoSub/BeoSubBin.H"
00063
00064 #include <cstdio>
00065 #include <cstdlib>
00066 #include <cstring>
00067 #include <iostream>
00068 #include <math.h>
00069 #include <vector>
00070 #include <cmath>
00071
00072
00073 BeoSubBin::BeoSubBin()
00074 {
00075 imageAngles.resize(0);
00076 imageLines.resize(0);
00077 binAngles.resize(0);
00078 binLines.resize(0);
00079 binCenter = *(new Point2D<int>(-1, -1));
00080
00081 }
00082
00083
00084 BeoSubBin::~BeoSubBin()
00085 { }
00086
00087
00088
00089
00090 float BeoSubBin::getBinSceneMass(Image< PixRGB<byte> > &cameraImage, Image< PixRGB<byte> > &outputImage, Point2D<int>& center) {
00091 #ifndef HAVE_OPENCV
00092 LFATAL("OpenCV must be installed in order to use this function");
00093 return 0;
00094 #else
00095 IplImage *edge = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00096 IplImage *out = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00097 IplImage *edge2 = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1);
00098
00099
00100 cvThreshold(img2ipl(luminance(cameraImage)), edge, 170, 255, CV_THRESH_TOZERO);
00101
00102 IplConvKernel* dilation = cvCreateStructuringElementEx(8, 8, 0, 0, CV_SHAPE_RECT);
00103 cvErode(edge, edge2, dilation, 1);
00104 cvDilate(edge2, edge, dilation, 1);
00105 cvThreshold(edge, out, 200, 255, CV_THRESH_TOZERO);
00106
00107
00108 int mass=-1, x=0, y=0;
00109 Image<byte> isoWhite = luminance(ipl2gray(out));
00110
00111
00112 outputImage = toRGB(isoWhite);
00113
00114 center.i = x;
00115 center.j = y;
00116
00117 cvReleaseImage(&edge);
00118 cvReleaseImage(&edge2);
00119
00120 cvReleaseStructuringElement(&dilation);
00121 return mass;
00122 #endif
00123 }
00124
00125
00126 std::vector<LineSegment2D> BeoSubBin::getHoughLines(Image< PixRGB <byte> > &cameraImage, Image< PixRGB <byte> > &preHough,
00127 Image< PixRGB <byte> > &outputImage)
00128 {
00129 std::vector <LineSegment2D> lines;
00130
00131 #ifndef HAVE_OPENCV
00132 LFATAL("OpenCV must be installed in order to use this function");
00133 #else
00134
00135
00136 IplImage *edge = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00137 IplImage *out = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00138 IplImage *edge2 = cvCreateImage( cvGetSize(img2ipl(cameraImage)), 8, 1 );
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 cvEqualizeHist(img2ipl(luminance(cameraImage)), edge);
00150 cvThreshold(img2ipl(luminance(cameraImage)), edge, 170, 255, CV_THRESH_TOZERO );
00151
00152 cvThreshold(edge, edge2, 170, 255, CV_THRESH_TOZERO);
00153 IplConvKernel* dilation = cvCreateStructuringElementEx(8, 8, 0, 0, CV_SHAPE_RECT);
00154 out = edge;
00155 cvErode(edge, edge2, dilation, 1);
00156 cvDilate(edge2, edge, dilation, 1 );
00157 cvThreshold(edge, edge2, 200, 255, CV_THRESH_TOZERO );
00158
00159
00160
00161
00162 cvCanny(edge, out, 100, 150, 3 );
00163 preHough = ipl2gray(edge);
00164
00165
00166 CvMemStorage* storage = cvCreateMemStorage(0);
00167
00168 outputImage.clear();
00169 outputImage = toRGB( ipl2gray( out ) );
00170
00171 CvSeq* cvlines = cvHoughLines2(out, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 10, 10, 10);
00172
00173 for(int i = 0; i < MIN(cvlines->total,10); i++ )
00174 {
00175 float* line = (float*)cvGetSeqElem(cvlines,i);
00176 float rho = line[0];
00177 float theta = line[1];
00178 CvPoint pt1, pt2;
00179 double a = cos(theta), b = sin(theta);
00180 double x0 = a*rho, y0 = b*rho;
00181 pt1.x = cvRound(x0 + 1000*(-b));
00182 pt1.y = cvRound(y0 + 1000*(a));
00183 pt2.x = cvRound(x0 - 1000*(-b));
00184 pt2.y = cvRound(y0 - 1000*(a));
00185 lines.push_back(LineSegment2D(Point2D<int>(pt1.x,pt1.y),Point2D<int>(pt2.x,pt2.y)));
00186 drawLine(outputImage, Point2D<int>(pt1.x,pt1.y), Point2D<int>(pt2.x, pt2.y), PixRGB<byte>(255,0,0));
00187 }
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 cvReleaseImage(&edge);
00198 cvReleaseImage(&edge2);
00199
00200 cvReleaseStructuringElement(&dilation);
00201
00202
00203 #endif // HAVE_OPENCV
00204 return lines;
00205 }
00206
00207
00208 void BeoSubBin::pruneLines(std::vector<LineSegment2D>& lines, std::vector<LineSegment2D> &pruned, Image< PixRGB<byte> >* img ) {
00209
00210
00211 std::vector<LineSegment2D> nonSimilarLines;
00212 std::vector<LineSegment2D>::iterator iter;
00213
00214
00215
00216 if(lines.size() > 0) {
00217 nonSimilarLines.push_back(lines[0]);
00218 lines.erase(lines.begin());
00219 iter = lines.begin();
00220 }
00221 else
00222 LDEBUG("*** NO LINES ***");
00223
00224
00225 double x, y;
00226
00227
00228
00229
00230 LineSegment2D border1 ( *(new Point2D<int>(0, 0)), *(new Point2D<int>(img->getWidth(), 0) ) );
00231
00232 LineSegment2D border2 ( *(new Point2D<int>(0, 0)), *(new Point2D<int>(0, img->getHeight()) ) );
00233
00234 LineSegment2D border3 ( *(new Point2D<int>(img->getWidth(), 0)), *(new Point2D<int>(img->getWidth(), img->getHeight()) ) );
00235
00236 LineSegment2D border4 ( *(new Point2D<int>(0, img->getHeight())), *(new Point2D<int>(img->getWidth(), img->getHeight()) ) );
00237
00238
00239 for(uint i = 0; i < nonSimilarLines.size(); i++) {
00240
00241 while(iter != lines.end()) {
00242
00243 double angle = nonSimilarLines[i].angleBetween(*iter);
00244 angle *= 180/PI;
00245 double intersect = nonSimilarLines[i].intersects((*iter), x, y);
00246
00247
00248 if(!intersect) {
00249
00250 double x2, y2;
00251
00252
00253 if((nonSimilarLines[i].intersects(border1, x, y) && (*iter).intersects(border1, x2, y2)) ||
00254 (nonSimilarLines[i].intersects(border4, x, y) && (*iter).intersects(border4, x2, y2))) {
00255
00256
00257 if(fabs(x - x2) < 5.0) {
00258
00259 lines.erase(iter);
00260 }
00261
00262 }
00263
00264
00265 else if((nonSimilarLines[i].intersects(border2, x, y) && (*iter).intersects(border2, x2, y2)) ||
00266 (nonSimilarLines[i].intersects(border3, x, y) && (*iter).intersects(border3, x2, y2))) {
00267
00268 if(fabs(y - y2) < 5.0) {
00269
00270 lines.erase(iter);
00271 }
00272
00273 }
00274
00275 }
00276
00277
00278
00279 else if(intersect && img->coordsOk((int)x, (int)y) && (fabs(angle) < 2.5 || fabs(angle) > 178.5)) {
00280
00281 lines.erase(iter);
00282 }
00283
00284 if(iter != lines.end())
00285 iter++;
00286 }
00287
00288 iter = lines.begin();
00289
00290
00291
00292
00293 if(lines.size() > 0) {
00294 nonSimilarLines.push_back(*iter);
00295 lines.erase(iter);
00296 }
00297
00298
00299 }
00300
00301 pruned = nonSimilarLines;
00302
00303 binAngles.clear();
00304
00305
00306 pruneAngles(nonSimilarLines, binAngles, img);
00307
00308
00309
00310 for(uint i = 0; i < nonSimilarLines.size(); i++)
00311 drawLine(*img, nonSimilarLines[i].point1(), nonSimilarLines[i].point2(), PixRGB<byte>(255,0,0));
00312
00313
00314
00315
00316
00317
00318 drawCircle(*img, *(new Point2D<int>(160, 120)), 5, PixRGB<byte>(200, 255, 0));
00319
00320
00321
00322
00323 }
00324
00325
00326 void BeoSubBin::pruneAngles(std::vector<LineSegment2D>& lines, std::vector<BinAngles>& angles, Image< PixRGB< byte > >* img) {
00327
00328
00329 for(uint i = 0; i < lines.size(); i++) {
00330
00331 for(uint j = i+1; j < lines.size(); j++) {
00332
00333 double angle = lines[i].angleBetween(lines[j]);
00334 angle *= 180/PI;
00335
00336 double x, y;
00337 lines[i].intersects(lines[j], x, y);
00338
00339
00340
00341
00342
00343 bool add = true;
00344 for(uint k = 0; k < angles.size(); k++) {
00345 if(fabs(angles[k].angle - angle) < 5.0 &&
00346 (abs(angles[k].pos.i - (int)x) <= 2.0 && abs(angles[k].pos.j - (int)y) <= 2.0)) {
00347 add = false;
00348 break;
00349 }
00350 }
00351
00352
00353
00354 if(add && img->coordsOk((int)x, (int)y)) {
00355 BinAngles b;
00356 b.pos = *(new Point2D<int>((int)x, (int)y));
00357 b.angle = angle;
00358 angles.push_back(b);
00359 }
00360
00361 }
00362 }
00363
00364 }
00365
00366 void BeoSubBin::removeOrangePipe(Image< PixRGB<byte> >& img) {
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 }
00388
00389 void BeoSubBin::getWeightedBinMass(std::vector<BinAngles>& angles, Point2D<int> & center, bool cropWindow, Image<PixRGB<byte> > *img) {
00390
00391
00392 float DIST = 1;
00393
00394 float avgY = 0;
00395
00396 if(angles.size() > 0) {
00397 DIST = center.distance(angles[0].pos);
00398 avgY = angles[0].pos.j;
00399 }
00400
00401
00402 for(uint i = 1; i < angles.size(); i++) {
00403 float closer = center.distance(angles[i].pos);
00404
00405 avgY += angles[i].pos.j;
00406
00407 if(closer < DIST)
00408 DIST = closer;
00409
00410 }
00411
00412 avgY /= angles.size();
00413 avgY = 120 - avgY;
00414
00415 float topCap = 0, bottomCap = 240;
00416
00417 if(cropWindow && avgY < 0)
00418 bottomCap = 240 - avgY;
00419 else if(cropWindow)
00420 topCap = avgY;
00421
00422 if(cropWindow) {
00423 LINFO("avgY: %f", avgY);
00424 drawLine(*img, Point2D<int>(0, (int)avgY), Point2D<int>(320, (int)avgY), PixRGB<byte>(255, 0, 0));
00425 drawLine(*img, Point2D<int>(0, (int)topCap), Point2D<int>(320, (int)topCap), PixRGB<byte>(255,0,0));
00426 drawLine(*img, Point2D<int>(0, (int)bottomCap), Point2D<int>(320, (int)bottomCap), PixRGB<byte>(255,0,0));
00427 }
00428
00429 Point2D<int> weightedCenter = center;
00430
00431
00432
00433 printf("closest dist: %f\n", DIST);
00434
00435 for(uint i = 0; i < angles.size(); i++) {
00436
00437 if(angles[i].pos.j < bottomCap && angles[i].pos.j > topCap) {
00438 float currentDist = weightedCenter.distance(angles[i].pos);
00439 printf("current dist: %f, x: %d, y: %d\n", currentDist, angles[i].pos.i, angles[i].pos.j);
00440 float weight = 1 / (currentDist/DIST );
00441 printf("weight: %f\n", weight);
00442 float cx = (angles[i].pos.i - weightedCenter.i) * weight + weightedCenter.i;
00443 float cy = (angles[i].pos.j - weightedCenter.j) * weight + weightedCenter.j;
00444
00445 Point2D<int> weightPoint((int)cx, (int)cy);
00446 printf("new point, x: %d, y: %d\n", weightPoint.i, weightPoint.j);
00447 center += weightPoint;
00448 center /= 2;
00449 }
00450 }
00451
00452 }
00453
00454
00455 void BeoSubBin::getParallelIntersections(std::vector<LineSegment2D>& lines, std::vector<LineSegment2D>& frontLines,
00456 Image< PixRGB<byte> >& img) {
00457
00458 printf("size of lines: %d\n", (int)lines.size());
00459
00460 bool moreThanOne;
00461
00462 frontLines.clear();
00463 std::vector<LineSegment2D> tmp = lines;
00464 std::vector<LineSegment2D>::iterator iter2 = tmp.begin();
00465
00466
00467 LineSegment2D border2 ( *(new Point2D<int>(0, 0)), *(new Point2D<int>(0, img.getHeight()) ) );
00468
00469 LineSegment2D border3 ( *(new Point2D<int>(img.getWidth(), 0)), *(new Point2D<int>(img.getWidth(), img.getHeight()) ) );
00470
00471
00472 for(uint i = 0; i < tmp.size(); i++) {
00473
00474 moreThanOne = false;
00475
00476 iter2 = tmp.begin() + i + 1;
00477 while(tmp.size() > i+1 && iter2 != tmp.end()) {
00478
00479 double x, y;
00480 x = y = -1;
00481
00482
00483 if((!lines[i].intersects(*iter2, x, y) && !img.coordsOk((int)x, (int)y)) &&
00484 lines[i].intersects(border2, x, y) && lines[i].intersects(border3, x, y)) {
00485
00486 drawLine(img, (*iter2).point1(), (*iter2).point2(), PixRGB<byte>(0,255,0));
00487 frontLines.push_back(*iter2);
00488 tmp.erase(iter2);
00489 moreThanOne = true;
00490
00491
00492 }
00493 else
00494 iter2++;
00495 }
00496
00497
00498
00499 if(moreThanOne && tmp.size() > i) {
00500 iter2 = tmp.begin() + i;
00501 drawLine(img, (*iter2).point1(), (*iter2).point2(), PixRGB<byte>(0,255,200));
00502 frontLines.push_back(*iter2);
00503 tmp.erase(iter2);
00504 }
00505 }
00506
00507
00508 printf("size of frontLines before adding intersections: %d\n", (int)frontLines.size());
00509 uint size = frontLines.size();
00510 iter2 = tmp.begin();
00511 for(uint i = 0; i < size; i++) {
00512 iter2 = tmp.begin();
00513 while(tmp.size() > 0 && iter2 != tmp.end()) {
00514
00515 double x, y;
00516 x = y = -1;
00517 if(frontLines[i].intersects(*iter2, x, y) && img.coordsOk((int)x, (int)y)) {
00518 frontLines.push_back(*iter2);
00519 tmp.erase(iter2);
00520 }
00521 else
00522 iter2++;
00523 }
00524 }
00525
00526
00527 printf("size of frontLines: %d\n", (int)frontLines.size());
00528 }
00529
00530 void BeoSubBin::getBinCenter(std::vector<BinAngles>& angles, Point2D<int>& center) {
00531
00532 for(uint i = 0; i < angles.size(); i++)
00533 center += angles[i].pos;
00534
00535 center /= angles.size();
00536 }
00537
00538
00539
00540
00541
00542