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;
	

}
Example #2
0
/*******************************************************************************
* 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);
 
}
Example #4
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;
}