/*
* Filter for L-shaped contours
*/
void PlaygroundDetector::filterContours(const Contours &contours, Contours &filteredContours) const
{

  filteredContours.clear();

  for(unsigned i=0; i<contours.size(); i++)
  {
    if(contours[i].size() > 5)
    {
      double area = cv::contourArea(contours[i]);
      if(area > 100 && area < 3000)
      {
        // smooth contour
        std::vector<cv::Point> approxCurve;
        cv::approxPolyDP(contours[i], approxCurve, double ( contours[i].size() ) *0.025 , true );
        
        if(approxCurve.size() != 6) continue;
        
        std::vector<cv::Point> hull;
        cv::convexHull(approxCurve, hull);
        
        float convexity = area / cv::contourArea(hull);
        
        if(convexity > 0.3f && convexity < 0.7f && hull.size() == 5)
        {
          filteredContours.push_back(approxCurve);
          //std::cout << "Area:" << area << " Convexity:" << convexity << std::endl;
        }
      }
    }
  }
  
}
示例#2
0
cv::Mat connectedComponentsFilter(cv::Mat& curFrame, cv::Mat& img) {

    if (!img.isContinuous()) {
        throwError("Parammeter 'img' in 'connectedComponentsFilter' must be continuous");
    }

    //morphology_(img);

    maskContours.clear();

    // Отрисовать найденные области обратно в маску
    cv::Mat result(img.size(), img.type());
    result.setTo(0);

    cv::findContours(img, maskContours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    size_t i = 0;

    while (i < maskContours.size()) {
        Contour& contour = maskContours[i];

        cv::Mat contourMat(contour, false);
        double len = cv::arcLength(contourMat, true);

        if (len * PERIM_SCALE < img.size().height + img.size().width) {
            // Отбрасываем контуры со слишком маленьким периметром.
            maskContours.erase(maskContours.begin() + i);
        } else {
            // Достаточно большие контуры аппроксимируем указанным методом.
            Contour newContour;

            // Методы аппроксимации.
            //cv::approxPolyDP(contourMat, newContour, CHAIN_APPROX_SIMPLE, true);
            cv::convexHull(contourMat, newContour, true);

            cv::Mat newContourMat(newContour, false);
            Rect boundingRect = cv::boundingRect(newContourMat);
            cv::rectangle(curFrame, boundingRect, cv::Scalar(255));

            maskContours[i] = newContour;

            i++;

            //points.push_back(CvPoint(boundingRect.x + boundingRect.width / 2, boundingRect.y + boundingRect.height / 2));
        }
    }


    if (!maskContours.empty()) { // Обходим баг OpenCV 2.1.0; в 2.3.1 он уже исправлен.
        cv::drawContours(result, maskContours, -1, cv::Scalar(255), FILLED);

    }
    return result;
}
/*
* Find Playground in image and calc its Extrinsics
*/
bool PlaygroundDetector::detect(const cv::Mat &image, Playground &playground, Contours &candidateContours, aruco::CameraParameters &cameraParameters)
{
  // pg not valid
  playground.id = -1;

  // get all contours from color thres image
  Contours contours;
  findContours(image, contours);
  
  // search for L shaped contours
  filterContours(contours, candidateContours);
  
    if(candidateContours.size() < 4) return false;
  
  // combine exatly 4 L-contours to one rectangle with 4 corners
  std::vector<cv::Point2f> corners; // max length: 4
  extractPlayGroundCorners(candidateContours, corners);
  
    if(corners.size() != 4) return false;
  
  playground.resize(4); 
  std::copy(corners.begin(), corners.end(), playground.begin());
  
  // playground valid
  playground.id = 0;
  
  // calc translation and rotation
  playground.calculateExtrinsics(cameraParameters);
  
  return true;
}
示例#4
0
Matrix Matrix::mask(Contours contours) {
	Matrix masked = clone();

	if (contours.size() > 0) {
		// Create mask
		cv::Mat mask = cv::Mat::zeros(size(), CV_8UC1);

		// Draw contours onto the mask so they are not removed
		for (int i = 0; i < contours.size(); ++i) {
			cv::drawContours(mask, contours, i, cv::Scalar(255), CV_FILLED);
		}

		masked = cv::Mat(cv::Mat::zeros(size(), type()));
		copyTo(masked, mask);
	}

	return masked;
}
示例#5
0
Matrix Matrix::crop(Contours contours) {
	Matrix cropped = cv::Mat(cv::Mat::zeros(1, 1, type()));

	if (contours.size() > 0) {
		// Determine ROI
		int minX = INT_MAX, minY = INT_MAX, maxX = INT_MIN, maxY = INT_MIN;
		for (int i = 0; i < contours.size(); ++i) {
			cv::Rect rect = cv::boundingRect(cv::Mat(contours[i]));
			if (rect.x < minX) minX = rect.x;
			if (rect.y < minY) minY = rect.y;
			if (rect.x + rect.width > maxX) maxX = rect.x + rect.width;
			if (rect.y + rect.height > maxY) maxY = rect.y + rect.height;
		}

		cropped = (*this)(cv::Rect(minX, minY, maxX - minX, maxY - minY)).clone();
	}

	return cropped;
}
示例#6
0
/*
* Draw playground, color according to lock / newly detected
*/
void HUD::drawPlayground(const Playground &playground, const Contours &candidateContours, bool highlight, bool pglock)
{
  // show detected single edges 
  if(candidateContours.size() > 0) {
    cv::drawContours(image, candidateContours, -1, cv::Scalar(0,0,255), 1);
  }

  cv::Scalar color = (pglock) ? cv::Scalar(0,255,0) : cv::Scalar(0,134,209);
  int lineSize = (highlight) ? 4 : 1;
  playground.draw(image,color,lineSize);
  
}
bool closeSurface(  fwVertexPosition &_vertex, fwVertexIndex &_vertexIndex )
{
    typedef std::pair< int, int  >  Edge;
    typedef std::vector< Edge > Contour; // at Border
    typedef std::vector< Contour> Contours;

    Contours contours;
    findBorderEdges( _vertexIndex , contours);
    bool closurePerformed = !contours.empty() ;
    // close each hole
    for ( Contours::iterator contour=contours.begin();  contour != contours.end(); ++contour )
    {
        int newVertexIndex = _vertex.size() ;
        // create gravity point & insert new triangle
        std::vector< float > massCenter(3,0);
        for ( Contour::iterator edge =contour->begin();  edge != contour->end(); ++edge )
        {
            for (int i=0; i<3; ++i )
            {
                massCenter[i]  += _vertex[edge->first][i];
                massCenter[i]  += _vertex[edge->second][i];
            }
            // create new Triangle
            std::vector< int > triangleIndex(3);
            triangleIndex[0] =  edge->first;
            triangleIndex[1] =  edge->second;
            triangleIndex[2] =  newVertexIndex;
            _vertexIndex.push_back( triangleIndex ); // TEST
        }
        for (int i=0; i<3; ++i )
        {
            massCenter[i] /= contour->size()*2;
        }
        _vertex.push_back( massCenter ); // normalize barycenter
    }
    return closurePerformed;
}
示例#8
0
	void Calibration::Start()
	{
		Utility::Logger* logger = Utility::Logger::GetInstance();
		logger->SetFileLoggingState(false);
		logger->Log(Utility::Logger::LOG_MESSAGE, "Calibration: Welcome to the camera calibration! Please hold an odd checkerboard or KB-06 techboard in front of the camera. Press G to start the calibration!");
		// Return empty if this isn't open
		if (!m_settings->GetIsOpenedAndGood())
		{
			return;
		}

		const char KEY_ESC = 27;
		const char KEY_U = 'u';
		const char KEY_G = 'g';

		State mode = m_settings->GetInputType() == CalibrationSettings::InputType::IMAGE_LIST
			? State::CAPTURING
			: State::DETECTION;

		cv::Size imageSize;
		cv::Mat cameraMatrix;
		cv::Mat distortionCoefficients;
		Contours contours;

		char key;
		bool isRunning = true;
		clock_t timestamp = 0;
		while (isRunning)
		{
			cv::Mat image;
			FetchNextImage(image);
			if (!image.empty())
			{
				bool blinkOutput = false;
				imageSize = image.size();
				if (m_settings->GetInputFlipHorizontal())
				{
					cv::flip(image, image, 0);
				}

				if (mode == State::CAPTURING &&
					contours.size() >= static_cast<unsigned int>(m_settings->GetNumberOfFrames()))
				{
					if (RunAndSaveCalibration(imageSize, cameraMatrix, distortionCoefficients, contours))
					{
						mode = State::CALIBRATED;
					}
					else
					{
						mode = State::DETECTION;
					}
				}

				bool found = false;
				Corners corners;
				switch (m_settings->GetCalibrationPattern())
				{
				case CalibrationSettings::Pattern::CHESSBOARD:
					found = cv::findChessboardCorners(image,
							m_settings->GetBoardSize(),
							corners,
							(CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK | CV_CALIB_CB_NORMALIZE_IMAGE));
					break;

				case CalibrationSettings::Pattern::CIRCLES_GRID:
					found = cv::findCirclesGrid(image,
							m_settings->GetBoardSize(),
							corners);
					break;

				case CalibrationSettings::Pattern::ASYMMETRIC_CIRCLES_GRID:
					found = cv::findCirclesGrid(image,
							m_settings->GetBoardSize(),
							corners,
							CALIB_CB_ASYMMETRIC_GRID);
					break;
				}

				if (found)
				{
					// improve the found corners' coordinate accuracy for chessboard
					if (m_settings->GetCalibrationPattern() == CalibrationSettings::Pattern::CHESSBOARD)
					{
						cv::Mat gray;
						cv::cvtColor(image, gray, CV_BGR2GRAY);
						cv::cornerSubPix(gray, corners, cv::Size(11, 11), cv::Size(-1, -1),
								cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
					}

					// For camera only take new samples after delay time
					if (mode == State::CAPTURING &&
						((clock() - timestamp) > (m_settings->GetInputDelay() * 1e-3 * CLOCKS_PER_SEC)))
					{
						contours.push_back(corners);
						blinkOutput = m_capture.isOpened();
						// Up the current frame
						m_currentFrame++;
					}

					// Draw the corners.
					cv::drawChessboardCorners(image, m_settings->GetBoardSize(),
							cv::Mat(corners), found);
				}

				// Check if we need to blink output
				if (blinkOutput)
				{
					cv::bitwise_not(image, image);
				}

				// Check if we can undistort output
				if (mode == State::CALIBRATED && m_settings->GetShowUndistortedImage())
				{
					cv::undistort(image.clone(), image,
							cameraMatrix,
							distortionCoefficients);
				}

				// Show image
				cv::imshow("TEST", image);
				// Delay + capture key
				key = static_cast<char>(cv::waitKey(m_capture.isOpened()
					? 50
					: m_settings->GetInputDelay()));

				// Check for esc key
				if (key == KEY_ESC)
				{
					isRunning = false;
				}
				// Check for u key
				else if (key == KEY_U)
				{
					m_settings->SetShowUndistortedImage(!m_settings->GetShowUndistortedImage());
				}
				// Check for k key
				else if (key == KEY_G && m_capture.isOpened())
				{
					mode = State::CAPTURING;
					contours.clear();
				}
			}
			else
			{
				if (contours.size() > 0)
				{
					RunAndSaveCalibration(imageSize, cameraMatrix, distortionCoefficients, contours);
					isRunning = false;
				}
			}
		}
	}
示例#9
0
Mat ScreenDetector::getTransformationMatrix(Error& error)
{
    bool approxFound = false;

    // convert image to HSV
    cvtColor(img, hsv, CV_BGR2HSV);

    // threshold the image
    inRange(hsv, hsvMin, hsvMax, thresholded);

    // Optimize threshold by reducing noise
    erode(thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) );
    dilate( thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) );
    dilate( thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) );
    erode(thresholded, thresholded, getStructuringElement(MORPH_ELLIPSE, Size(erodeDilateSize, erodeDilateSize)) );
    GaussianBlur(thresholded, thresholded, Size(3,3), 0);

    Mat forContours;
    thresholded.copyTo(forContours);
    // find all contours
    Contours contours;
    Contour approximatedScreen;
    findContours(forContours, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
    int nbContours = contours.size();
    cout << nbContours << " contours found, debug: " << DEBUG << endl;

    if(nbContours == 0)
    {
        error.setError("Unable to find the screen",
                       "The camera doesn't detect any screen or green element."
                       "Please check if your screen is turned on and directed toward the screen");
        return img;
    }

    sort(contours.begin(), contours.end(), contour_compare_area);

    // find the contour with the biggest area that have 4 points when approximated
    for(int i=0; i < nbContours; ++i)
    {
        approxPolyDP(contours.at(i), approximatedScreen, approximateEpsilon * arcLength(contours.at(i), true), true);
        // our screen has 4 point when approximated
        if(approximatedScreen.size() == 4)
        {
            approxFound = true;
            break;
        }
    }

    if(!approxFound)
    {
        error.setError("Unable to find the screen properly",
                       "It seems that the screen is not fully detectable by the camera. Try to reduce light in your room");
        return img;
    }

    if(DEBUG)
    {
        namedWindow("debug", WINDOW_KEEPRATIO);
        namedWindow("thresholded_calibration", WINDOW_KEEPRATIO);
        Mat debug = Mat::zeros(img.rows, img.cols, CV_8UC3);
        polylines(debug, approximatedScreen, true, Scalar(0,0,255), 3);
        imshow("debug", debug);
        imshow("thresholded_calibration", thresholded);
    }

    return transformImage(approximatedScreen);
}
示例#10
0
void StripIdsFromContours(const ContoursWithIds &contoursWithIds, Contours &contoursNoIds)
{
	contoursNoIds.resize(contoursWithIds.size());
	for(unsigned int j=0; j< contoursWithIds.size(); j++)
		StripIdsFromContour(contoursWithIds[j], contoursNoIds[j]);
}