LMPacket LMHandler::handle( cv::Point2f borderPoints[ 3 ] , MazeData mazeData , bool debugMode ) { if( debugMode ) { std::cout << std::endl ; std::cout << "<!---------------------------------------------" ; std::cout << std::endl ; std::cout << "LMHandler.handle() called. handling..." ; std::cout << std::endl ; } if ( IsNull( mazeData ) ) { std::cerr << "LMHandler: mazeData of type MazeData is Null" ; std::cerr << std::endl ; return LMPacketNull ; } if ( !mazeData.image.data ) { std::cerr << "LMHandler: No mazeImage data!" ; std::cerr << std::endl ; return LMPacketNull ; } // Declare local variables cv::Mat annotatedImage ; cv::Mat processingImage ; cv::Point2f startLocation ; cv::Point2f endLocation ; cv::Point2f ballLocation ; cv::Point2f centerLocation ; cv::Point2f criticalPoints[ 6 ] ; float criticalAngles[ 6 ] ; float zeroAngle ; float ballAngle ; int sextantIndex ; float scalingArray[ 5 ] ; float normalizedBallAngle ; // our guy! std::vector< std::vector< cv::Point > > contours ; std::vector< std::vector< cv::Point > > approxContours ; std::vector< cv::Vec4i > hierarchy ; //std::vector< cv::Point > boundingTriangleVertices ; int boundingTriangleIndex ; // Initialize local variables annotatedImage = mazeData.image.clone( ) ; startLocation = mazeData.mazePoints[ 0 ] ; endLocation = mazeData.mazePoints[ 1 ] ; ballLocation = mazeData.mazePoints[ 2 ] ; centerLocation = startLocation ; criticalPoints[ 0 ] = borderPoints[ 0 ] ; // one end of upos criticalPoints[ 2 ] = borderPoints[ 1 ] ; // one end of vpos criticalPoints[ 4 ] = borderPoints[ 2 ] ; // one end of wpos criticalPoints[ 1 ] = findMidPoint( criticalPoints[ 0 ] , criticalPoints[ 2 ] ); // one end of wneg criticalPoints[ 3 ] = findMidPoint( criticalPoints[ 2 ] , criticalPoints[ 4 ] ); // one end of uneg criticalPoints[ 5 ] = findMidPoint( criticalPoints[ 0 ] , criticalPoints[ 4 ] ); // one end of vneg for ( int i = 0 ; i < 6 ; i++ ) { std::stringstream ss; ss << std::to_string( i ) << std::fixed << std::setprecision( 0 ) << "("; ss << criticalPoints[ i ].x << "," << criticalPoints[ i ].y << ")"; std::string label = ss.str(); /* std::string label ; label.assign( std::to_string( i ) ); label += "- ( "; label += std::to_string( criticalPoints[ i ].x ); label += " , "; label += std::to_string( criticalPoints[ i ].y ); label += " )"; */ setLabel( annotatedImage , label , criticalPoints[ i ] ) ; // start } /* setLabel( annotatedImage , "0" , criticalPoints[ 0 ] ) ; // start setLabel( annotatedImage , "1" , criticalPoints[ 1 ] ) ; // start setLabel( annotatedImage , "2" , criticalPoints[ 2 ] ) ; // start setLabel( annotatedImage , "3" , criticalPoints[ 3 ] ) ; // start setLabel( annotatedImage , "4" , criticalPoints[ 4 ] ) ; // start setLabel( annotatedImage , "5" , criticalPoints[ 5 ] ) ; // start */ // Draw a line in between S & B cv::line( annotatedImage , centerLocation , criticalPoints[ 0 ] , CV_RGB ( 0 , 255 , 255 ) , 1 ) ; cv::line( annotatedImage , centerLocation , criticalPoints[ 1 ] , CV_RGB ( 0 , 255 , 255 ) , 1 ) ; cv::line( annotatedImage , centerLocation , criticalPoints[ 2 ] , CV_RGB ( 0 , 255 , 255 ) , 1 ) ; cv::line( annotatedImage , centerLocation , criticalPoints[ 3 ] , CV_RGB ( 0 , 255 , 255 ) , 1 ) ; cv::line( annotatedImage , centerLocation , criticalPoints[ 4 ] , CV_RGB ( 0 , 255 , 255 ) , 1 ) ; cv::line( annotatedImage , centerLocation , criticalPoints[ 5 ] , CV_RGB ( 0 , 255 , 255 ) , 1 ) ; ballAngle = findRelativeAngle( centerLocation, ballLocation); if( debugMode ) { std::cout << "Critical points importing complete. " ; std::cout << std::endl; std::cout << "Critical points:"; std::cout << std::endl; for( int i = 0 ; i < 6 ; i++ ) { std::cout << "[ " << i << " ] : "; std::cout << criticalPoints[ i ]; std::cout << std::endl; } std::cout << "Ball angle:"; std::cout << ballAngle << std::endl; } if( debugMode ) { std::cout << "Calculating critical angles. " ; std::cout << std::endl; } criticalAngles[ 0 ] = findRelativeAngle( centerLocation, criticalPoints[ 0 ]); // upos criticalAngles[ 1 ] = findRelativeAngle( centerLocation, criticalPoints[ 1 ]); // wneg criticalAngles[ 2 ] = findRelativeAngle( centerLocation, criticalPoints[ 2 ]); // vpos criticalAngles[ 3 ] = findRelativeAngle( centerLocation, criticalPoints[ 3 ]); // uneg criticalAngles[ 4 ] = findRelativeAngle( centerLocation, criticalPoints[ 4 ]); // wpos criticalAngles[ 5 ] = findRelativeAngle( centerLocation, criticalPoints[ 5 ]); // vneg zeroAngle = criticalAngles[ 0 ]; // uneg is our zero if( debugMode ) { std::cout << "Calculating critical angles complete. " ; std::cout << std::endl; std::cout << "Critical angles:"; std::cout << std::endl; for( int i = 0 ; i < 6 ; i++ ) { std::cout << "[ " << i << " ] : "; std::cout << criticalAngles[ i ]; std::cout << std::endl; } std::cout << "Zero angle: "; std::cout << zeroAngle; std::cout << std::endl; } if( debugMode ) { std::cout << "Finding sextant index. " ; std::cout << std::endl; } sextantIndex = -1 ; for( int i = 0 ; i < 6 ; i++ ) { if( ballAngle >= criticalAngles[ i ] ) { sextantIndex = i ; } } if( sextantIndex == -1 ) { std::cerr << "LMHandler: sextantIndex estimation failed" ; std::cerr << std::endl ; return LMPacketNull ; } if( debugMode ) { std::cout << "Finding sextant index complete. " ; std::cout << std::endl; std::cout << "Sextant index: "; std::cout << sextantIndex; std::cout << std::endl; } if( debugMode ) { std::cout << "Updating critical angles. " ; std::cout << std::endl; } for( int i = 0 ; i < 6 ; i++) { criticalAngles[ i ] -= zeroAngle ; criticalAngles[ i ] = ( criticalAngles[ i ] >= 0 ? 0 : 360 ) + criticalAngles[ i ]; } ballAngle -= zeroAngle ; ballAngle = ( ballAngle >= 0 ? 0 : 360 ) + ballAngle; if( debugMode ) { std::cout << "Updating critical angles complete. " ; std::cout << std::endl; std::cout << "Updated critical angles:"; std::cout << std::endl; for( int i = 0 ; i < 6 ; i++ ) { std::cout << "[ " << i << " ] : "; std::cout << criticalAngles[ i ]; std::cout << std::endl; } } if( debugMode ) { std::cout << "Finding scaling parameters. " ; std::cout << std::endl; } for( int i = 0; i < 6; i++ ) { scalingArray[ i ] = 60 / ( criticalAngles[ (i + 1) % 6 ] - criticalAngles[ i ] ) ; } if( debugMode ) { std::cout << "Finding scaling parameters complete. " ; std::cout << std::endl; std::cout << "Scaling parameters:"; std::cout << std::endl; for( int i = 0 ; i < 5 ; i++ ) { std::cout << "[ " << i << " ] : "; std::cout << scalingArray[ i ]; std::cout << std::endl; } } if( debugMode ) { std::cout << "Finding normalized ball angle. " ; std::cout << std::endl; } normalizedBallAngle = sextantIndex * 60 + ( ballAngle - criticalAngles[ sextantIndex ] ) * scalingArray[ sextantIndex ]; if( debugMode ) { std::cout << "Finding normalized ball angle complete. " ; std::cout << std::endl; std::cout << "Ball angle: "; std::cout << ballAngle; std::cout << std::endl; std::cout << "Normalized ball angle: "; std::cout << normalizedBallAngle; std::cout << std::endl; } if( normalizedBallAngle < 0 || normalizedBallAngle > 360 ) { std::cerr << "LMHandler: normalizedBallAngle is out of bounds!" ; std::cerr << std::endl ; return LMPacketNull ; } extractContours( mazeData.image , processingImage , contours, approxContours, hierarchy ); if( debugMode ) { std::cout << "Contour extraction complete. Number of approx. contours found: " ; std::cout << approxContours.size() ; std::cout << std::endl; } /* boundingTriangleIndex = findBoundingTriangle( approxContours ) ; if( boundingTriangleIndex == -1 ) { return LMPacketNull; } if( debugMode ) { std::cout << "The bounding triangle found at index: " ; std::cout << std::to_string( boundingTriangleIndex ) ; std::cout << std::endl; std::cout << "The related hierarchy record: " ; std::cout << hierarchy[ boundingTriangleIndex ] ; std::cout << std::endl; std::cout << "The child record: " ; std::cout << hierarchy[ boundingTriangleIndex ][ 2 ] ; std::cout << std::endl; } // Annote all vertices of the approximation curve vector and extract the vertices for( std::vector< cv::Point >::size_type i = 0 ; i != 3 ; i++ ) { setLabel( annotatedImage , "V" , approxContours[ boundingTriangleIndex ] ); } */ /* // Annote all vertices of the approximation curve vector and extract the vertices // hierarchy[i][2] -> first child int mazeBoundIndex = hierarchy[ boundingTriangleIndex ][ 2 ]; for( std::vector< cv::Point >::size_type i = 0 ; i != 3 ; i++ ) { setLabel( annotatedImage , "M" , approxContours[ mazeBoundIndex ] ); } */ cv::Mat dummyImage ; // Delete everything outside the triangle cv::Mat mask = cv::Mat::zeros( processingImage.size( ) , CV_8UC1 ); //std::vector< std::vector< cv::Point > > dummyContours ; //dummyContours.push_back( contours ); //cv::drawContours( mask , contours , -1 , cv::Scalar( 255 ) , CV_FILLED ); cv::drawContours( mask , contours , -1 , cv::Scalar( 255 ) , CV_FILLED ); if( debugMode ) { std::cout << "Search for contours is complete. Displaying the results:" ; std::cout << std::endl; showImage( "LM-mask" , mask ); } processingImage.copyTo( dummyImage , mask ) ; processingImage = dummyImage.clone( ) ; //processingImage.copyTo( processingImage , mask ) ; //annotatedImage.copyTo( dummyImage , mask ) ; //annotatedImage = dummyImage.clone( ) ; //setLabel( annotatedImage , "0" , contours[ 0 ] ) ; if( debugMode ) { std::cout << "Masking complete. Displaying the results:" ; std::cout << std::endl; showImage( "LM-maskedProcessingImage" , processingImage ); } //ballLocation centerocation if( debugMode ) { //std::cout << "Search for contours is complete. Displaying the results:" ; //std::cout << std::endl; /* displayContours( "LM-Contours on processingImage" , processingImage.clone() , contours , hierarchy , // approxContours false , true ); // true ); // for enumeration , for contour only mode */ /* displayContours( "LM-Contours on mazeImage" , mazeData.image.clone() , contours , hierarchy , // approxContours false , false ); */ /* displayContours( "LM-approxContours on processingImage" , processingImage.clone() , approxContours , hierarchy , // approxContours false , true ); // true ); // for enumeration , for contour only mode displayContours( "LM-approxContours on mazeImage" , mazeData.image.clone() , approxContours , hierarchy , // approxContours false , false ); */ } //slope = startLocation.y - ballLocation //Point2f a(0.3f, 0.f), b(0.f, 0.4f); //Point pt = (a + b)*10.f; // Label the annotatedImage setLabel( annotatedImage , "S" , centerLocation ) ; // start setLabel( annotatedImage , "E" , endLocation ) ; // end setLabel( annotatedImage , "B" , ballLocation ) ; // ball // Draw a line in between S & B cv::line( annotatedImage , centerLocation , ballLocation , CV_RGB ( 0 , 255 , 255 ) , 1 ) ; //double radius = cv::norm( startLocation - ballLocation ) ;//Euclidian distance //cv::circle( annotatedImage, startLocation, radius, CV_RGB ( 0 , 255 , 0 ) , 1 ) ; if( debugMode ) { std::cout << "Annotating feature points and drawing line complete." ; std::cout << std::endl; } /* CountNonZero(bitwise_and(ShapeAImage,ShapeBImage)). */ //////////////////////////////////////////////////////// /////////////////////// EXPORTING ////////////////////// //////////////////////////////////////////////////////// // Export private variables this -> annotatedImage = annotatedImage.clone( ) ; // Exporting state variables state.ballLocationData.wayBlocked[ 0 ] = false ; state.ballLocationData.wayBlocked[ 1 ] = false ; state.ballLocationData.wayBlocked[ 2 ] = false ; state.ballLocationData.wayBlocked[ 3 ] = false ; state.ballLocationData.currentPathNo = 5 ; state.ballPositionAngle = normalizedBallAngle ; //////////////////////////////////////////////////////// ////////////////// EXPORTING COMPLETE ////////////////// //////////////////////////////////////////////////////// if( debugMode ) { std::cout << "State exporting complete." ; std::cout << std::endl; std::cout << "---------------------------------------------->"; std::cout << std::endl; std::cout << std::endl; } return state; }
/******************************************************************************* * Function: extractFGTargets * Description: extract FG targets with given conditions and return objects * Arguments: inImg - input image fgImg - output FG mask image seLength - length of structuring elements (opening) threshVal - threshold value for converting to binary image minArea - minimum area of FG targets maxArea - maximum area of FG targets minAspRatio - minimum aspect ratio of FG targets maxAspRatio - maximum aspect ratio of FG targets * Returns: vector<FGObject>* - all extracted FG targets * Comments: * Revision: *******************************************************************************/ vector<FGObject>* FGExtraction::extractFGTargets(InputArray inImg, OutputArray fgImg, int seLength, int threshVal, double minArea, double maxArea, double minAspRatio, double maxAspRatio) { double theta = 0.4; if(!inImg.obj) return NULL; _inImg = inImg.getMat(); this->init(); //showImage("inImg", _inImg); // background subtraction by opening int err = subtractBGOpenDiagonal(inImg, _bgsImg, threshVal, seLength); if (err>0) { vector<FGObject>* fgObjects = new vector<FGObject>; return fgObjects; } //subtractBGMedian(inImg.getMat(), bgSubImg, threshVal, seLength); //showImage("inImg", _inImg, 0, 1); //showImage("bgSub", _bgsImg); // get the contour vector<vector<Point>> contours = extractContours(_bgsImg); //cout<<contours.size()<<endl; // double local thresholding // histogram backprojection Mat mask = Mat::zeros(_bgsImg.size(), CV_8U); vector<int> areas(contours.size()); int cnt = 0; int argMax = 0; int max_area = 0; for(vector<vector<Point> >::const_iterator it = contours.begin(); it != contours.end(); ++it){ Rect uprightBox = boundingRect(*it); areas[cnt] = uprightBox.height*uprightBox.width; if (areas[cnt]>max_area) { max_area = areas[cnt]; argMax = cnt; } cnt++; } //showImage("inImg", _inImg, 0, 1); vector<Point> largestContour = contours[argMax]; //***** only use the largest contour RotatedRect orientedBox = orientedBoundingBox(largestContour); orientedBox.size.width *= 1.5; orientedBox.size.height *= 1.5; ellipse(mask, orientedBox, Scalar(255), -1); //Rect tempRect = boundingRect(largestContour); //Mat tempImg = mask(tempRect); //imshow("tempImg", tempImg); //imshow("mask", mask); //waitKey(0); // double local thresholding double percentage = 0.8; doubleThresholdByValue(percentage, mask); /*finish = clock(); duration = (double)(finish - start) / (double)CLOCKS_PER_SEC; cout << duration << " sec" << endl; start = clock();*/ // remove noise by a median filter medianBlur(_fgHighImg, _fgHighImg, 3); medianBlur(_fgLowImg, _fgLowImg, 3); //showImage("_fgHighImg", _fgHighImg); //showImage("_fgLowImg", _fgLowImg); /*finish = clock(); duration = (double)(finish - start) / (double)CLOCKS_PER_SEC; cout << duration << " sec" << endl; start = clock();*/ // merge two masks using histogram backprojection //showImage("_fgImg", _fgImg); //showImage("mask", mask); updateByHistBackproject(theta, mask); ellipse(mask, orientedBox, Scalar(0), -1); ellipse(_fgHighImg, orientedBox, Scalar(0), -1); ellipse(_fgLowImg, orientedBox, Scalar(0), -1); //} // thresholding by area and variance #ifdef IMAGE_DOWNSAMPLING int dilateSESize = 3; int erodeSESize = 3; int varThresh = 30; #else int dilateSESize = 7; int erodeSESize = 7; int varThresh = 30; #endif //showImage("fg high", _fgHighImg, 0, 1); //showImage("fg low", _fgLowImg, 0, 1); //showImage("after histbp", _fgImg, 0); thresholdByAreaRatioVar(minArea, maxArea, dilateSESize, erodeSESize, minAspRatio, maxAspRatio, varThresh); //showImage("after area threshold", _fgImg, 0); // post-processing postProcessing(_fgImg, _fgImg); //imshow("_fgImg",_fgImg); //waitKey(0); // fill the holes of the fgImg _fgImg.copyTo(fgImg); floodFill(fgImg, cv::Point(0,0), Scalar(255)); //imshow("fgImg",fgImg); //waitKey(0); bitwise_not(fgImg, fgImg); bitwise_or(fgImg, _fgImg, _fgImg); //imshow("inImg", inImg); //imshow("_fgImg",_fgImg); //waitKey(0); // opening RotatedRect rotatedR = fitEllipse(Mat(largestContour)); float objHeight = min(rotatedR.size.height,rotatedR.size.width); int seSize = int(objHeight/10.0+0.5); Mat se = getStructuringElement(MORPH_ELLIPSE, Size(seSize, seSize)); //***** choose different size according to object height morphologyEx(_fgImg, _fgImg, MORPH_OPEN, se); //imshow("_fgImg",_fgImg); //waitKey(0); // close morphologyEx(_fgImg, _fgImg, MORPH_CLOSE, se); // timer /*clock_t start, finish; double duration = 0.0; start = clock(); finish = clock(); duration = (double)(finish - start) / (double)CLOCKS_PER_SEC; cout << duration << " sec" << endl;*/ thresholdByAreaRatioVar(0.5*minArea, maxArea, 1, 1, minAspRatio, maxAspRatio, 30); // push targets into our vector //Mat largeInImg; #ifdef IMAGE_DOWNSAMPLING resize(_fgImg, _fgImg, Size(), 2, 2, INTER_LINEAR); resize(_inImg, largeInImg, Size(), 2, 2, INTER_LINEAR); #endif //tempImg = _fgImg.clone(); //findContours(tempImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); //tempImg.release(); //imshow("_fgImg",_fgImg); //waitKey(0); contours = extractContours(_fgImg); vector<FGObject>* fgObjects = new vector<FGObject>; //Mat mask8U = Mat::zeros(largeInImg.size(), CV_8U); for (size_t i = 0; i < contours.size(); i++){ double area = contourArea(contours[i]); RotatedRect orientedRect = orientedBoundingBox(contours[i]); Point2f points[4]; orientedRect.points(points); /* orientedRect.size.width *= 1.5; orientedRect.size.height *= 1.5; ellipse(mask8U, orientedRect, Scalar(255), -1); int channels[] = {0}; int nbins = 16; const int histSize[] = {nbins}; float range[] = {0, 255}; const float* ranges[] = {range}; Mat hist; cv::calcHist(&largeInImg, 1, channels, mask8U, hist, 1, histSize, ranges); */ // push targets into our vector FGObject* obj = new FGObject; //obj->histogram = hist; obj->setObjectProperties(area, orientedRect.angle, contours[i], points, SOURCE_UNRECTIFIED); if(obj->isPartialOut(_fgImg.cols, _fgImg.rows) == false){ fgObjects->push_back(*obj); } delete obj; //ellipse(mask8U, orientedRect, Scalar(0), -1); } // eliminate artifacts with width of 1 at the border... rectangle(_fgImg, Point(0,0), Point(_fgImg.cols-1, _fgImg.rows-1), Scalar(0)); fgImg.getMatRef() = _fgImg.clone(); return fgObjects; }
void getContours(const char* filename) { cv::Mat img = cv::imread(filename, 0); /* //Apply blur to smooth edges and use adapative thresholding cv::Size size(3,3); cv::GaussianBlur(img,img,size,0); adaptiveThreshold(img, img,255,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,75,10); cv::bitwise_not(img, img); */ cv::Mat tmp; cv::GaussianBlur(img, tmp, cv::Size(25,25), 25); cv::addWeighted(img, 1.5, tmp, -0.5, 0, img); adaptiveThreshold(img, img,255,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY,55,60); cv::bitwise_not(img, img); cv::Mat img2 = img.clone(); std::vector<cv::Point> points; cv::Mat_<uchar>::iterator it = img.begin<uchar>(); cv::Mat_<uchar>::iterator end = img.end<uchar>(); for (; it != end; ++it) if (*it) points.push_back(it.pos()); cv::RotatedRect box = cv::minAreaRect(cv::Mat(points)); double angle = box.angle; if (angle < -45.) angle += 90.; cv::Point2f vertices[4]; box.points(vertices); for(int i = 0; i < 4; ++i) cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(255, 0, 0), 1, CV_AA); cv::Mat rot_mat = cv::getRotationMatrix2D(box.center, angle, 1); cv::Mat rotated; cv::warpAffine(img2, rotated, rot_mat, img.size(), cv::INTER_CUBIC); cv::Size box_size = box.size; if (box.angle < -45.) std::swap(box_size.width, box_size.height); cv::Mat cropped; cv::getRectSubPix(rotated, box_size, box.center, cropped); cv::imshow("Cropped", cropped); // imwrite("example5.jpg",cropped); Mat cropped2=cropped.clone(); cvtColor(cropped2,cropped2,CV_GRAY2RGB); Mat cropped3 = cropped.clone(); cvtColor(cropped3,cropped3,CV_GRAY2RGB); vector<vector<Point> > contours; vector<Vec4i> hierarchy; /// Find contours cv:: findContours( cropped, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_TC89_KCOS, Point(0, 0) ); /// Approximate contours to polygons + get bounding rects and circles vector<vector<Point> > contours_poly( contours.size() ); vector<Rect> boundRect( contours.size() ); vector<Point2f>center( contours.size() ); vector<float>radius( contours.size() ); //Get poly contours for( int i = 0; i < contours.size(); i++ ) { approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true ); } //Get only important contours, merge contours that are within another vector<vector<Point> > validContours; for (int i=0;i<contours_poly.size();i++){ Rect r = boundingRect(Mat(contours_poly[i])); if(r.area()<100)continue; bool inside = false; for(int j=0;j<contours_poly.size();j++){ if(j==i)continue; Rect r2 = boundingRect(Mat(contours_poly[j])); if(r2.area()<100||r2.area()<r.area())continue; if(r.x>r2.x&&r.x+r.width<r2.x+r2.width&& r.y>r2.y&&r.y+r.height<r2.y+r2.height){ inside = true; } } if(inside)continue; validContours.push_back(contours_poly[i]); } //Get bounding rects for(int i=0;i<validContours.size();i++){ boundRect[i] = boundingRect( Mat(validContours[i]) ); } //Display Scalar color = Scalar(0,255,0); for( int i = 0; i< validContours.size(); i++ ) { if(boundRect[i].area()<100)continue; drawContours( cropped2, validContours, i, color, 1, 8, vector<Vec4i>(), 0, Point() ); rectangle( cropped2, boundRect[i].tl(), boundRect[i].br(),color, 2, 8, 0 ); } //imwrite("example6.jpg",cropped2); imshow("Contours",cropped2); extractContours(cropped3,validContours); cv::waitKey(0); }
/******************************************************************************* * Function: subtractBGOpenDiagonal * Description: BG subtraction via opening with diagonal structuring elements * Arguments: inImg - input image bgsImg - BG subtracted image threshVal - threshold value for converting to binary image seLength - length of structuring elements * Returns: void * Comments: * Revision: *******************************************************************************/ int FGExtraction::subtractBGOpenDiagonal(InputArray src, OutputArray dst, int threshVal, int seLength) { // generate binary image by thresholding Mat bin; double thresh = threshold(src, bin, threshVal, 255, THRESH_BINARY); // opening by horizontal structuring element //Mat structElemHorizontal = Mat::ones(1, seLength, CV_8U); //morphologyEx(bin, dst, MORPH_OPEN, structElemHorizontal); // opening by vertical structuring element //Mat structElemVertical = Mat::ones(seLength, 1, CV_8U); //morphologyEx(dst, dst, MORPH_OPEN, structElemVertical); //imshow("src", src); //imshow("bin", bin); //waitKey(0); // opening by first diagonal structuring element Mat structElemBackSlash = Mat::eye(seLength, seLength, CV_8U); morphologyEx(bin, dst, MORPH_OPEN, structElemBackSlash); //imshow("dst1", dst); //waitKey(0); // opening by second diagonal structuring element Mat structElemSlash; flip(structElemBackSlash, structElemSlash, 0); morphologyEx(dst, dst, MORPH_OPEN, structElemSlash); //imshow("dst2", dst); //waitKey(0); // eliminate small noise Mat structElemEllip = getStructuringElement(MORPH_ELLIPSE, Size(seLength, seLength)); morphologyEx(dst, dst, MORPH_OPEN, structElemEllip); //imshow("dst3", dst); //waitKey(0); // get object size Mat dstImg = dst.getMat(); vector<vector<Point>> contours = extractContours(dstImg); if (contours.size()==0) return 1; Mat mask = Mat::zeros(_bgsImg.size(), CV_8U); vector<int> areas(contours.size()); int cnt = 0; int argMax = 0; int max_area = 0; for(vector<vector<Point> >::const_iterator it = contours.begin(); it != contours.end(); ++it){ Rect uprightBox = boundingRect(*it); areas[cnt] = uprightBox.height*uprightBox.width; if (areas[cnt]>max_area) { max_area = areas[cnt]; argMax = cnt; } cnt++; } vector<Point> largestContour = contours[argMax]; //***** only use the largest contour RotatedRect orientedBox = orientedBoundingBox(largestContour); int updateSeL = int(min(orientedBox.size.width, orientedBox.size.height)/5.0+0.5); // opening by first diagonal structuring element structElemBackSlash = Mat::eye(updateSeL, updateSeL, CV_8U); morphologyEx(bin, dst, MORPH_OPEN, structElemBackSlash); //imshow("dst1", dst); //waitKey(0); // opening by second diagonal structuring element flip(structElemBackSlash, structElemSlash, 0); morphologyEx(dst, dst, MORPH_OPEN, structElemSlash); //imshow("dst2", dst); //waitKey(0); // eliminate small noise structElemEllip = getStructuringElement(MORPH_ELLIPSE, Size(updateSeL, updateSeL)); morphologyEx(dst, dst, MORPH_OPEN, structElemEllip); //imshow("dst3", dst); //waitKey(0); return 0; }