#ifndef CALIBRATION__BOARD_PATTERN_HPP #define CALIBRATION__BOARD_PATTERN_HPP #include #include #include #include #include #include #include namespace calibration { enum class PatternType { circles_grid, chessboard }; struct BoardPattern { cv::Size pattern_size; double center_distance_mm; PatternType pattern_type; }; inline std::string normalize(std::string text) { std::transform( text.begin(), text.end(), text.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); }); return text; } inline PatternType parse_pattern_type(const YAML::Node & yaml) { if (!yaml["pattern_type"]) return PatternType::circles_grid; auto raw = normalize(yaml["pattern_type"].as()); if (raw == "circles_grid" || raw == "circle_grid" || raw == "circles") { return PatternType::circles_grid; } if (raw == "chessboard" || raw == "checkerboard") { return PatternType::chessboard; } throw std::runtime_error( "Unsupported pattern_type: " + raw + ". Supported values: circles_grid, chessboard."); } inline std::string pattern_name(PatternType pattern_type) { return pattern_type == PatternType::chessboard ? "chessboard" : "circles_grid"; } inline BoardPattern load_board_pattern(const YAML::Node & yaml) { BoardPattern board_pattern; board_pattern.pattern_size = cv::Size(yaml["pattern_cols"].as(), yaml["pattern_rows"].as()); board_pattern.center_distance_mm = yaml["center_distance_mm"].as(); board_pattern.pattern_type = parse_pattern_type(yaml); return board_pattern; } inline bool find_pattern_points( const cv::Mat & img, const BoardPattern & board_pattern, std::vector & points) { if (board_pattern.pattern_type == PatternType::circles_grid) { return cv::findCirclesGrid( img, board_pattern.pattern_size, points, cv::CALIB_CB_SYMMETRIC_GRID); } cv::Mat gray; if (img.channels() == 1) gray = img; else cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY); auto flags = cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE | cv::CALIB_CB_FAST_CHECK; auto success = cv::findChessboardCorners(gray, board_pattern.pattern_size, points, flags); if (!success) return false; cv::cornerSubPix( gray, points, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 30, 1e-3)); return true; } inline std::vector planar_points( const cv::Size & pattern_size, const double center_distance_mm) { std::vector points; points.reserve(static_cast(pattern_size.width * pattern_size.height)); for (int i = 0; i < pattern_size.height; i++) { for (int j = 0; j < pattern_size.width; j++) { points.push_back({static_cast(j * center_distance_mm), static_cast(i * center_distance_mm), 0.0f}); } } return points; } } // namespace calibration #endif // CALIBRATION__BOARD_PATTERN_HPP