diff --git a/modules/calib3d/perf/perf_calibratecamera.cpp b/modules/calib3d/perf/perf_calibratecamera.cpp index 94d3ba9cb2..95f7f07042 100644 --- a/modules/calib3d/perf/perf_calibratecamera.cpp +++ b/modules/calib3d/perf/perf_calibratecamera.cpp @@ -5,12 +5,16 @@ #include "opencv2/core/utils/filesystem.hpp" +//#define SAVE_IMAGE_POINTS + namespace opencv_test { -static std::vector loadBulkImages(size_t max_images) +#ifdef SAVE_IMAGE_POINTS + +static std::vector loadBulkImages(size_t max_images) { const std::string data_dir = findDataDirectory("perf/calib3d/bulk_n500", false); - std::vector image_paths; + std::vector image_paths; cv::utils::fs::glob(data_dir, "*.png", image_paths, false, false); if (image_paths.empty()) cv::utils::fs::glob(data_dir, "*.jpg", image_paths, false, false); @@ -23,55 +27,115 @@ static std::vector loadBulkImages(size_t max_images) return image_paths; } -static std::vector buildObjectPoints(const Size& pattern_size, float square_size) +static std::vector> buildImagePoints(const std::vector& image_paths, const cv::Size pattern_size) { - std::vector object_points; - object_points.reserve(pattern_size.area()); - for (int y = 0; y < pattern_size.height; ++y) - for (int x = 0; x < pattern_size.width; ++x) - object_points.push_back(Point3f(x * square_size, y * square_size, 0.f)); - return object_points; -} - -PERF_TEST(CalibrateCamera, DISABLED_BulkImages_N500) -{ - applyTestTag(CV_TEST_TAG_LONG, CV_TEST_TAG_SIZE_HD); - - const Size pattern_size(6, 8); - const size_t max_images = 500; - - std::vector image_paths = loadBulkImages(max_images); - std::vector object_pattern = buildObjectPoints(pattern_size, 1.0f); - - std::vector > image_points; - std::vector > object_points; + std::vector> image_points; image_points.reserve(image_paths.size()); - object_points.reserve(image_paths.size()); - Size image_size; for (const auto& path : image_paths) { Mat gray = imread(path, IMREAD_GRAYSCALE); - ASSERT_FALSE(gray.empty()) << "Can't read image: " << path; - if (image_size.empty()) - image_size = gray.size(); - else - ASSERT_EQ(gray.size(), image_size) << "Mismatched image size: " << path; + if (gray.empty()) + { + printf("Can't read image: %s\n", path.c_str()); + return std::vector>(); + } std::vector corners; bool found = findChessboardCorners( gray, pattern_size, corners, CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE); - ASSERT_TRUE(found) << "Chessboard not found: " << path; - cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1), - TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1)); - - image_points.push_back(corners); - object_points.push_back(object_pattern); + if (found) + { + cornerSubPix(gray, corners, Size(11, 11), Size(-1, -1), + TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 30, 0.1)); + image_points.push_back(corners); + } } + return image_points; +} + +static void saveImagePoints(const std::vector>& image_points) +{ + const std::string points_file = "bulk_n500.yaml"; + cv::FileStorage fs(points_file, cv::FileStorage::WRITE | cv::FileStorage::FORMAT_YAML); + if (!fs.isOpened()) + { + printf("Cannot open yaml config \"%s\" for output\n", points_file.c_str()); + } + fs << "count" << (int)image_points.size(); + for (int i = 0; i < (int)image_points.size(); i++) + { + fs << cv::format("frame_%d", i) << image_points[i]; + } + + fs.release(); +} + +#else + +static std::vector> loadImagePoints() +{ + const std::string points_file = findDataFile("perf/calib3d/bulk_n500.yaml"); + cv::FileStorage fs(points_file, cv::FileStorage::READ); + if (!fs.isOpened()) + { + printf("Cannot open yaml config \"%s\" for output\n", points_file.c_str()); + return std::vector>(); + } + int count = fs["count"]; + std::vector> image_points(count); + + for (int i = 0; i < (int)image_points.size(); i++) + { + fs[cv::format("frame_%d", i)] >> image_points[i]; + } + + fs.release(); + + return image_points; +} + +#endif + +static std::vector> buildObjectPoints(const Size& pattern_size, float square_size, size_t count) +{ + std::vector board; + board.reserve(pattern_size.area()); + + for (int y = 0; y < pattern_size.height; ++y) + for (int x = 0; x < pattern_size.width; ++x) + board.push_back(Point3f(x * square_size, y * square_size, 0.f)); + + std::vector > object_points; + object_points.reserve(count); + for (size_t i = 0; i < count; i++) + object_points.push_back(board); + + return object_points; +} + +PERF_TEST(CalibrateCamera, BulkImages_N500) +{ + // NOTE: The images archive is published at https://dl.opencv.org/data/bulk_n500.zip + applyTestTag(CV_TEST_TAG_LONG); + + const cv::Size pattern_size(6, 8); + const cv::Size image_size(1280, 720); + +#ifdef SAVE_IMAGE_POINTS + std::vector image_paths = loadBulkImages(500); + std::vector> image_points = buildImagePoints(image_paths, pattern_size); ASSERT_FALSE(image_points.empty()); + saveImagePoints(image_points); +#else + std::vector> image_points = loadImagePoints(); + ASSERT_FALSE(image_points.empty()); +#endif + + std::vector > object_points = buildObjectPoints(pattern_size, 1.0f, image_points.size()); Mat camera_matrix = Mat::eye(3, 3, CV_64F); Mat dist_coeffs = Mat::zeros(8, 1, CV_64F); @@ -93,8 +157,8 @@ PERF_TEST(CalibrateCamera, DISABLED_BulkImages_N500) camera_matrix, dist_coeffs, rvecs, tvecs, 0); } + EXPECT_NEAR(rms, 1.768263, 1e-4); SANITY_CHECK_NOTHING(); - EXPECT_GT(rms, 0.0); } } // namespace opencv_test