37#include <visp3/core/vpConfig.h>
39#if defined(VISP_HAVE_PUGIXML) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_HIGHGUI) && \
40 (((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_CALIB3D)) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_CALIB)))
42#if defined(HAVE_OPENCV_CALIB3D)
43#include <opencv2/calib3d/calib3d.hpp>
44#elif defined(HAVE_OPENCV_CALIB)
45#include <opencv2/calib.hpp>
47#include <opencv2/core/core.hpp>
48#include <opencv2/highgui/highgui.hpp>
49#include <opencv2/imgproc/imgproc.hpp>
51#include <visp3/core/vpIoTools.h>
52#include <visp3/core/vpPixelMeterConversion.h>
53#include <visp3/core/vpPoint.h>
54#include <visp3/core/vpXmlParserCamera.h>
55#if defined(VISP_HAVE_MODULE_GUI)
56#include <visp3/gui/vpDisplayFactory.h>
58#include <visp3/io/vpVideoReader.h>
59#include <visp3/vision/vpPose.h>
61#if defined(ENABLE_VISP_NAMESPACE)
67void calcChessboardCorners(
int width,
int height,
double squareSize, std::vector<vpPoint> &corners)
72 for (
int j = 0;
j <
width;
j++) {
77 corners.push_back(pt);
82void usage(
const char **argv,
int error)
84 std::cout <<
"Synopsis" << std::endl
85 <<
" " << argv[0] <<
" [-w <width>] [-h <height>]"
86 <<
" [--square-size <size>]"
87 <<
" [--input <images filename>]"
88 <<
" [--intrinsic <xml file>]"
89 <<
" [--camera-name <name>]"
90 <<
" [--output <poses filename>]"
91 <<
" [--help, -h]" << std::endl
93 std::cout <<
"Description" << std::endl
94 <<
" Compute the pose of a a chessboard in a sequence of images." << std::endl
96 <<
" -w <width>" << std::endl
97 <<
" Chessboard width." << std::endl
98 <<
" Default: 9" << std::endl
100 <<
" -h <height>" << std::endl
101 <<
" Chessboard height." << std::endl
102 <<
" Default: 6" << std::endl
104 <<
" --square-size <size>" << std::endl
105 <<
" Chessboard square size in [m]." << std::endl
106 <<
" Default: 0.03" << std::endl
108 <<
" --input <images filename>" << std::endl
109 <<
" Generic name of the images to process." << std::endl
110 <<
" Default: empty" << std::endl
111 <<
" Example: \"image-%d.jpg\"" << std::endl
113 <<
" --intrinsic <xml file>" << std::endl
114 <<
" XML file that contains camera intrinsic parameters. " << std::endl
115 <<
" Default: \"camera.xml\"" << std::endl
117 <<
" --camera-name <name>" << std::endl
118 <<
" Camera name in the XML file that contains camera intrinsic parameters." << std::endl
119 <<
" Default: \"Camera\"" << std::endl
121 <<
" --output <poses filename>" << std::endl
122 <<
" Generic name of the yaml files that contains the resulting tag poses." << std::endl
123 <<
" Default: \"pose_cPo_%d.yaml\"" << std::endl
125#if defined(VISP_HAVE_MODULE_GUI)
126 <<
" --no-interactive" << std::endl
127 <<
" To compute the tag poses without interactive validation by the user." << std::endl
130 <<
" --help, -h" << std::endl
131 <<
" Print this helper message." << std::endl
134 std::cout <<
"Example" << std::endl
137 <<
" --input image-%d.jpg" << std::endl
141 std::cout <<
"Error" << std::endl
143 <<
"Unsupported parameter " << argv[
error] << std::endl;
148int main(
int argc,
const char **argv)
150 int opt_chessboard_width = 9, opt_chessboard_height = 6;
151 double opt_chessboard_square_size = 0.03;
152 std::string opt_input_img_files =
"";
153 std::string opt_intrinsic_file =
"camera.xml";
154 std::string opt_camera_name =
"Camera";
155 std::string opt_output_pose_files =
"pose_cPo_%d.yaml";
156 bool opt_interactive =
true;
158 for (
int i = 1;
i < argc;
i++) {
159 if (std::string(argv[i]) ==
"-w" && i + 1 < argc) {
160 opt_chessboard_width = atoi(argv[++i]);
162 else if (std::string(argv[i]) ==
"-h" && i + 1 < argc) {
163 opt_chessboard_height = atoi(argv[++i]);
165 else if (std::string(argv[i]) ==
"--square-size" && i + 1 < argc) {
166 opt_chessboard_square_size = atof(argv[++i]);
168 else if (std::string(argv[i]) ==
"--input" && i + 1 < argc) {
169 opt_input_img_files = std::string(argv[++i]);
171 else if (std::string(argv[i]) ==
"--intrinsic" && i + 1 < argc) {
172 opt_intrinsic_file = std::string(argv[++i]);
174 else if (std::string(argv[i]) ==
"--output" && i + 1 < argc) {
175 opt_output_pose_files = std::string(argv[++i]);
177 else if (std::string(argv[i]) ==
"--camera-name" && i + 1 < argc) {
178 opt_camera_name = std::string(argv[++i]);
180#if defined(VISP_HAVE_MODULE_GUI)
181 else if (std::string(argv[i]) ==
"--no-interactive") {
182 opt_interactive =
false;
185 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
196 std::cout <<
"Camera parameters file " << opt_intrinsic_file <<
" doesn't exist." << std::endl;
197 std::cout <<
"Use --help option to see how to set its location..." << std::endl;
201 if (opt_input_img_files.empty()) {
202 std::cout <<
"Input images location empty." << std::endl;
203 std::cout <<
"Use --help option to see how to set input image location..." << std::endl;
214 std::cout <<
"Parameters:" << std::endl;
215 std::cout <<
" Chessboard" << std::endl;
216 std::cout <<
" Width : " << opt_chessboard_width << std::endl;
217 std::cout <<
" Height : " << opt_chessboard_height << std::endl;
218 std::cout <<
" Square size [m] : " << opt_chessboard_square_size << std::endl;
219 std::cout <<
" Input images location : " << opt_input_img_files << std::endl;
222 std::cout <<
" Camera intrinsics " << std::endl;
223 std::cout <<
" Param file name [.xml]: " << opt_intrinsic_file << std::endl;
224 std::cout <<
" Camera name : " << opt_camera_name << std::endl;
225 std::cout <<
" Output camera poses : " << opt_output_pose_files << std::endl;
226 std::cout <<
" Interactive mode : " << (opt_interactive ?
"yes" :
"no") << std::endl << std::endl;
228#if defined(VISP_HAVE_MODULE_GUI)
229#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
230 std::shared_ptr<vpDisplay> display;
234 if (opt_interactive) {
235#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
246 std::cout <<
"Create output directory: " << output_parent << std::endl;
250 std::vector<vpPoint> corners_pts;
251 calcChessboardCorners(opt_chessboard_width, opt_chessboard_height, opt_chessboard_square_size, corners_pts);
255 if (!opt_intrinsic_file.empty() && !opt_camera_name.empty()) {
258 std::cout <<
"Unable to parse parameters with distortion for camera \"" << opt_camera_name <<
"\" from "
259 << opt_intrinsic_file <<
" file" << std::endl;
260 std::cout <<
"Attempt to find parameters without distortion" << std::endl;
262 if (
parser.parse(cam, opt_intrinsic_file, opt_camera_name,
264 std::cout <<
"Unable to parse parameters without distortion for camera \"" << opt_camera_name <<
"\" from "
265 << opt_intrinsic_file <<
" file" << std::endl;
270 std::cout <<
"Camera parameters used to compute the pose:\n" <<
cam << std::endl;
275 std::cout <<
"Process image: " << reader.
getFrameName() << std::endl;
280#if defined(VISP_HAVE_MODULE_GUI)
284 cv::Size chessboardSize(opt_chessboard_width, opt_chessboard_height);
285 std::vector<cv::Point2f> corners2D;
286 bool found = cv::findChessboardCorners(matImg, chessboardSize, corners2D,
287#
if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
288 cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_FAST_CHECK |
289 cv::CALIB_CB_NORMALIZE_IMAGE);
291 CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FAST_CHECK |
292 CV_CALIB_CB_NORMALIZE_IMAGE);
298 cv::cvtColor(matImg, matImg_gray, cv::COLOR_BGR2GRAY);
299 cv::cornerSubPix(matImg_gray, corners2D, cv::Size(11, 11), cv::Size(-1, -1),
300#
if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
301 cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.1));
303 cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
306 for (
size_t i = 0;
i < corners_pts.size();
i++) {
308 double x = 0.0,
y = 0.0;
310 corners_pts[
i].set_x(x);
311 corners_pts[
i].set_y(y);
317 std::cerr <<
"Problem when computing final pose using VVS" << std::endl;
321 cv::drawChessboardCorners(matImg, chessboardSize, corners2D, found);
328 pose_vec.saveYAML(filename, pose_vec);
331#if defined(VISP_HAVE_MODULE_GUI)
332 if (opt_interactive) {
348 }
while (!quit && !reader.
end());
350#if defined(VISP_HAVE_MODULE_GUI)
351 if (opt_interactive) {
352#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
361 std::cout <<
"Catch an exception: " <<
e.getMessage() << std::endl;
369#if !defined(HAVE_OPENCV_IMGPROC)
370 std::cerr <<
"OpenCV imgproc module is requested to compute the pose of the chessboard." << std::endl;
372#if !defined(HAVE_OPENCV_HIGHGUI)
373 std::cerr <<
"OpenCV highgui module is requested to compute the pose of the chessboard." << std::endl;
375#if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION < 0x050000) && !defined(HAVE_OPENCV_CALIB3D)
376 std::cerr <<
"OpenCV calib3d module is requested to compute the pose of the chessboard." << std::endl;
378#if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x050000) && !defined(HAVE_OPENCV_3D)
379 std::cerr <<
"OpenCV 3d module is requested to compute the pose of the chessboard." << std::endl;
381#if !defined(VISP_HAVE_PUGIXML)
382 std::cout <<
"pugixml built-in 3rdparty is requested to compute the pose of the chessboard." << std::endl;
Generic class defining intrinsic camera parameters.
@ perspectiveProjWithDistortion
Perspective projection with distortion model.
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
static const vpColor none
Class that defines generic functionalities for display.
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color=vpColor::none, unsigned int thickness=1, const vpImagePoint &offset=vpImagePoint(0, 0), const std::string &frameName="", const vpColor &textColor=vpColor::black, const vpImagePoint &textOffset=vpImagePoint(15, 15))
static void setTitle(const vpImage< unsigned char > &I, const std::string &windowtitle)
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Implementation of an homogeneous matrix and operations on such kind of matrices.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
void set_oY(double oY)
Set the point oY coordinate in the object frame.
void set_oZ(double oZ)
Set the point oZ coordinate in the object frame.
void set_oX(double oX)
Set the point oX coordinate in the object frame.
Implementation of a pose vector and operations on poses.
Class used for pose computation from N points (pose from point only). Some of the algorithms implemen...
@ DEMENTHON_LAGRANGE_VIRTUAL_VS
bool computePose(vpPoseMethodType method, vpHomogeneousMatrix &cMo, FuncCheckValidityPose func=nullptr)
void addPoints(const std::vector< vpPoint > &lP)
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
void open(vpImage< vpRGBa > &I) VP_OVERRIDE
void setFileName(const std::string &filename)
long getFirstFrameIndex()
std::string getFrameName() const
long getFrameIndex() const
void acquire(vpImage< vpRGBa > &I) VP_OVERRIDE
XML parser to load and save intrinsic camera parameters.
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.