/*
* 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;
        }
      }
    }
  }
  
}
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;
}
Exemple #3
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;
				}
			}
		}
	}