1
\$\begingroup\$

I am using OpenCV’s findchessboardcornersSB function to find the corners in the image. I am using below code/ header file:

#pragma once #include"opencv2/opencv.hpp" #include<Eigen/core> #include<vector> namespace MAL_Vision_Dushyant { class ChessBoardDetector { public: int CB_Width, CB_Height; cv::Size patternSize; ChessBoardDetector(int Width, int Height) { CB_Width = Width; CB_Height = Height; patternSize = cv::Size(Width, Height); } //ChessBoardDetector(){} void get_CB_Corners(std::string filename, const bool ROI_needed = false, const bool show_img = false, const int resize_factor = 2) { //auto beg1 = std::chrono::high_resolution_clock::now(); cv::Mat src_image = cv::imread(filename); cv::Mat crop_image, gray_img; cv::Rect r; std::vector<cv::Point2f> corners(CB_Width*CB_Height); //crop image so that it fits on the screen. if (ROI_needed) { //select the ROI in the image cv::resize(src_image, src_image, cv::Size(src_image.cols / resize_factor, src_image.rows / resize_factor)); r = cv::selectROI(src_image); //resize the cropped image so that it represents pixel on original image crop_image = src_image(cv::Rect(resize_factor * r.x, resize_factor * r.y, resize_factor * r.width, resize_factor * r.height)); } else { //Use original image size crop_image = src_image.clone(); } //cv::cvtColor(crop_image, crop_image, cv::COLOR_BGR2GRAY); //bool found = cv::findChessboardCorners(src_image, patternSize, corners, cv::CALIB_CB_FAST_CHECK | cv::CALIB_CB_NORMALIZE_IMAGE | cv::CALIB_CB_EXHAUSTIVE); bool found = cv::findChessboardCornersSB(crop_image, patternSize, corners); } }; } 

When I run the get_CB_Corners function without any ROI selection, I am getting the function runtime of 4 + seconds. In my debug console project, I see a lot of OpenCL related lines. I don't know why that is necessary. Also when I run similar code in python, it takes less time than this C++ code block which is very disturbing for this basic function. Below is the main function:

#include"Chess_Board_Detection.h" using namespace std; using namespace cv; int CB_WIDTH = 9; int CB_HEIGHT = 6; int main() { int ang; cout << "Enter angle" << endl; cin >> ang; string input_dir = "C:\\Users\\DushyantPatil\\Documents\\Pose Estimation\\Input Data\\stereo\\images\\"; string test_number = "test1_B\\"; //string prefix = "1_"; string prefix = "1_"; string suffix = "d_6.bmp"; string filename = input_dir + test_number + prefix + to_string(ang) + suffix; MAL_Vision_Dushyant::ChessBoardDetector CB_Detect1(CB_WIDTH, CB_HEIGHT); CB_Detect1.get_CB_Corners(filename, false); } 
\$\endgroup\$
4
  • \$\begingroup\$ Are you compiling in debug mode? Are you linking to a debug version of the OpenCV library? \$\endgroup\$ Commented Jun 27, 2023 at 2:53
  • \$\begingroup\$ Code ran in a debug mode in Visual Studio (im assuming you're using this) runs very differently than code ran in release mode. Have you tried comparing those two times? \$\endgroup\$ Commented Jun 27, 2023 at 3:12
  • \$\begingroup\$ @CrisLuengo, - I am running the code in Visual Studio nDebug mode. But should the difference be that much in release mode? Also when I run this code from terminal in ubuntu, I get the code running in 1 second. Does this have anything to do with openCL and threading? I am not sure how they affect the program though \$\endgroup\$ Commented Jun 27, 2023 at 5:04
  • 5
    \$\begingroup\$ Yes, C++ code in debug mode can be orders of magnitude slower than in release mode. Debug mode disables most optimizations. Make sure you link the release OpenCV library, not the debug one. \$\endgroup\$ Commented Jun 27, 2023 at 7:00

1 Answer 1

3
\$\begingroup\$

The discprency in speed is probably due to the fact that both your code and OpenCV are built in debug mode. Dont worry about OpenCL calls. OpenCV optionally uses OpenCL to boost performance.

General Review

  1. Prefer functions over classes. The class ChessBoardDetector is not needed in this case. Instead you can just create a findChessBoardCorners free function that takes patternSize.
  2. The get_CB_corners is doing too many things. It reads from the filesystem. Then creates a UI element to interactively get and ROI and then it crops the image and finds corners. Split this into different functions.
  3. Dont import the entire namespace at file scope aka using namespace <namespace> is bad. The std and cv namespaces have a lot of functions. By using using namespace std; or using namespace cv. You leave your self open to name collisions.
  4. Prefer std::size_t over int for indices and sizes.
  5. Avoid global variables viz CB_WIDTH and CB_HEIGHT. If you want to use global constants use constexpr
  6. Use better names. Use chessBoard instead of CB. Use cropped_image instead of crop_image.
  7. Mark variables that are not modified as const.
  8. Prefer commandline arguments for getting arguments for a script over std::cin
  9. Prefer auto variableName = Type{parameters} syntax for defining variable. This makes it impossible to have an uninitialized variable.
  10. The output of find corners is not being used anywhere. This makes the code useless.
  11. Dont use pragma once. More details here.
  12. Include everthing you use explicitly. You should include opencv.hpp in main too.

OpenCV Specific Review

  1. From what I can understand, you are downsampling the image then selecting ROI and then resizing the images because the image is too big and the selectROI window does not fit on your screen. To get around this, create a window first
  2. There is no need to default initialize corners. The cv::findChessboardCornersSB will do it for you.

Modified Code

#include <cstddef> #include"opencv2/opencv.hpp" constexpr size_t chessBoardWidth = 9; constexpr size_t chessBoardHeight = 6; int main(int argc, char ** argv) { constexpr char usage[] = "corners [-i] <filepath> ==> where -i enables interactive mode" if (argc < 2){ std::cout << usage; return -1; } bool interactiveMode = false; char * fileName = argv[1]; if (argv[1] == '-i'){ interactiveMode = true; fileName = argv[2]; } auto image = cv::imread(fileName) auto croppedImage = cv2::Mat{}; if(interactiveMode){ cv2::namedWindow("Crop Image", cv::WINDOW_NORMAL); roi = selectROI("Crop Image", image); croppedImage = image(roi); } else { croppedImage = image; } std::vector<cv::Point2f> corners; if(!cv::findChessboardCornersSB(croppedImage, cv2::Size(chessBoardWidth, chessBoardHeight), corners)){ std::cout << "No Corners Found"; return 0; } //DO Something with corners return 0; } 
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.