29 #include <opencv2/core/version.hpp>
31 #if CV_MAJOR_VERSION >= 3
32 # include <opencv2/imgcodecs.hpp>
34 # include <opencv2/highgui/highgui.hpp>
37 #include <opencv2/calib3d/calib3d.hpp>
38 #include <opencv2/imgproc/imgproc.hpp>
51 #define CHECK_STATUS(STMT) \
54 VPIStatus status = (STMT); \
55 if (status != VPI_SUCCESS) \
57 char buffer[VPI_MAX_STATUS_MESSAGE_LENGTH]; \
58 vpiGetLastStatusMessage(buffer, sizeof(buffer)); \
59 std::ostringstream ss; \
60 ss << vpiStatusGetName(status) << ": " << buffer; \
61 throw std::runtime_error(ss.str()); \
65 static void PrintUsage(
const char *progname, std::ostream &out)
67 out <<
"Usage: " << progname <<
" <-c W,H> [-s win] <image1> [image2] [image3] ...\n"
69 <<
" W,H\tcheckerboard with WxH squares\n"
70 <<
" win\tsearch window width around checkerboard vertex used\n"
71 <<
"\tin refinement, default is 0 (disable refinement)\n"
72 <<
" imageN\tinput images taken with a fisheye lens camera" << std::endl;
75 static char *my_basename(
char *path)
78 char *name = strrchr(path,
'\\');
80 char *name = strrchr(path,
'/');
96 std::vector<const char *> images;
99 static Params ParseParameters(
int argc,
char *argv[])
105 for (
int i = 1; i < argc; ++i)
107 if (argv[i][0] ==
'-')
109 if (strlen(argv[i] + 1) == 1)
114 PrintUsage(my_basename(argv[0]), std::cout);
120 throw std::invalid_argument(
"Option -c must be followed by checkerboard width and height");
123 if (sscanf(argv[++i],
"%d,%d", &cbSize.width, &cbSize.height) != 2)
125 throw std::invalid_argument(
"Error parsing checkerboard information");
130 params.vtxCount.width = cbSize.width - 1;
131 params.vtxCount.height = cbSize.height - 1;
137 throw std::invalid_argument(
"Option -s must be followed by search window size");
139 if (sscanf(argv[++i],
"%d", ¶ms.searchWinSize) != 1)
141 throw std::invalid_argument(
"Error parsing search window size");
143 if (params.searchWinSize < 0)
145 throw std::invalid_argument(
"Search window size must be >= 0");
150 throw std::invalid_argument(std::string(
"Option -") + (argv[i] + 1) +
" not recognized");
155 throw std::invalid_argument(std::string(
"Option -") + (argv[i] + 1) +
" not recognized");
160 params.images.push_back(argv[i]);
164 if (params.images.empty())
166 throw std::invalid_argument(
"At least one image must be defined");
169 if (cbSize.width <= 3 || cbSize.height <= 3)
171 throw std::invalid_argument(
"Checkerboard size must have at least 3x3 squares");
174 if (params.searchWinSize == 1)
176 throw std::invalid_argument(
"Search window size must be 0 (default) or >= 2");
182 int main(
int argc,
char *argv[])
191 VPIImage tmpIn = NULL, tmpOut = NULL;
199 Params params = ParseParameters(argc, argv);
200 if (params.images.empty())
206 std::vector<std::vector<cv::Point2f>> corners2D;
209 cv::Size imgSize = {};
211 for (
unsigned i = 0; i < params.images.size(); ++i)
214 cv::Mat img = cv::imread(params.images[i]);
217 throw std::runtime_error(
"Can't read " + std::string(params.images[i]));
220 if (imgSize == cv::Size{})
222 imgSize = img.size();
224 else if (imgSize != img.size())
226 throw std::runtime_error(
"All images must have same size");
232 std::vector<cv::Point2f> cbVertices;
234 if (findChessboardCorners(img, params.vtxCount, cbVertices,
235 cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE))
238 if (params.searchWinSize >= 2)
241 cvtColor(img, gray, cv::COLOR_BGR2GRAY);
243 cornerSubPix(gray, cbVertices, cv::Size(params.searchWinSize / 2, params.searchWinSize / 2),
245 cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.0001));
249 corners2D.push_back(std::move(cbVertices));
253 std::cerr <<
"Warning: checkerboard pattern not found in image " << params.images[i] << std::endl;
260 std::vector<cv::Point3f> initialCheckerboard3DVertices;
261 for (
int i = 0; i < params.vtxCount.height; ++i)
263 for (
int j = 0; j < params.vtxCount.width; ++j)
267 initialCheckerboard3DVertices.emplace_back(
static_cast<float>(j),
static_cast<float>(i), 0.0f);
272 std::vector<std::vector<cv::Point3f>> corners3D(corners2D.size(), initialCheckerboard3DVertices);
275 using Mat3 = cv::Matx<double, 3, 3>;
276 Mat3 camMatrix = Mat3::eye();
279 std::vector<double> coeffs(4);
283 int flags = cv::fisheye::CALIB_FIX_SKEW;
287 cv::Mat rvecs, tvecs;
288 double rms = cv::fisheye::calibrate(corners3D, corners2D, imgSize, camMatrix, coeffs, rvecs, tvecs, flags);
289 printf(
"rms error: %lf\n", rms);
293 printf(
"Fisheye coefficients: %lf %lf %lf %lf\n", coeffs[0], coeffs[1], coeffs[2], coeffs[3]);
295 printf(
"Camera matrix:\n");
296 printf(
"[%lf %lf %lf; %lf %lf %lf; %lf %lf %lf]\n", camMatrix(0, 0), camMatrix(0, 1), camMatrix(0, 2),
297 camMatrix(1, 0), camMatrix(1, 1), camMatrix(1, 2), camMatrix(2, 0), camMatrix(2, 1), camMatrix(2, 2));
314 distModel.
k1 = coeffs[0];
315 distModel.
k2 = coeffs[1];
316 distModel.
k3 = coeffs[2];
317 distModel.
k4 = coeffs[3];
321 for (
int i = 0; i < 2; ++i)
323 for (
int j = 0; j < 3; ++j)
325 K[i][j] = camMatrix(i, j);
331 X[0][0] = X[1][1] = X[2][2] = 1;
352 for (
unsigned i = 0; i < params.images.size(); ++i)
355 cvImage = cv::imread(params.images[i]);
356 assert(!cvImage.empty());
385 snprintf(buf,
sizeof(buf),
"undistort_%03d.jpg", i);
386 imwrite(buf, cvImage);
389 catch (std::exception &e)
391 std::cerr <<
"Error: " << e.what() << std::endl;
392 PrintUsage(my_basename(argv[0]), std::cerr);
Functions and structures for dealing with VPI images.
Declares functions to generate warp maps based on common lens distortion models.
Functions for handling OpenCV interoperability with VPI.
Declares functions that implement the Remap algorithm.
Declaration of VPI status codes handling functions.
Declares functions dealing with VPI streams.
void vpiImageDestroy(VPIImage img)
Destroy an image instance.
struct VPIImageImpl * VPIImage
A handle to an image.
VPIStatus vpiImageCreate(int32_t width, int32_t height, VPIImageFormat fmt, uint64_t flags, VPIImage *img)
Create an empty image instance with the specified flags.
VPIFisheyeMapping mapping
Mapping between pixel angle and pixel distance to image center.
VPIStatus vpiWarpMapGenerateFromFisheyeLensDistortionModel(const VPICameraIntrinsic Kin, const VPICameraExtrinsic X, const VPICameraIntrinsic Kout, const VPIFisheyeLensDistortionModel *distModel, VPIWarpMap *warpMap)
Generates a mapping that corrects image distortions caused by fisheye lenses.
float VPICameraExtrinsic[3][4]
Camera extrinsic matrix.
float VPICameraIntrinsic[2][3]
Camera intrinsic matrix.
@ VPI_FISHEYE_EQUIDISTANT
Specifies the equidistant fisheye mapping.
Holds coefficients for fisheye lens distortion model.
VPIStatus vpiImageCreateWrapperOpenCVMat(const cv::Mat &mat, VPIImageFormat fmt, uint64_t flags, VPIImage *img)
Wraps a cv::Mat in an VPIImage with the given image format.
VPIStatus vpiImageSetWrappedOpenCVMat(VPIImage img, const cv::Mat &mat)
Redefines the wrapped cv::Mat of an existing VPIImage wrapper.
struct VPIPayloadImpl * VPIPayload
A handle to an algorithm payload.
void vpiPayloadDestroy(VPIPayload payload)
Deallocates the payload object and all associated resources.
VPIStatus vpiSubmitRemap(VPIStream stream, uint64_t backend, VPIPayload payload, VPIImage input, VPIImage output, VPIInterpolationType interp, VPIBorderExtension border, uint64_t flags)
Submits a Remap operation to the stream.
VPIStatus vpiCreateRemap(uint64_t backends, const VPIWarpMap *warpMap, VPIPayload *payload)
Create a payload for Remap algorithm.
struct VPIStreamImpl * VPIStream
A handle to a stream.
VPIStatus vpiStreamSync(VPIStream stream)
Blocks the calling thread until all submitted commands in this stream queue are done (queue is empty)...
void vpiStreamDestroy(VPIStream stream)
Destroy a stream instance and deallocate all HW resources.
VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
Create a stream instance.
@ VPI_BACKEND_CUDA
CUDA backend.
@ VPI_BORDER_ZERO
All pixels outside the image are considered to be zero.
@ VPI_INTERP_CATMULL_ROM
Catmull-Rom cubic interpolation.
int8_t numHorizRegions
Number of regions horizontally.
VPIWarpGrid grid
Warp grid control point structure definition.
int16_t horizInterval[VPI_WARPGRID_MAX_HORIZ_REGIONS_COUNT]
Horizontal spacing between control points within a given region.
int8_t numVertRegions
Number of regions vertically.
int16_t vertInterval[VPI_WARPGRID_MAX_VERT_REGIONS_COUNT]
Vertical spacing between control points within a given region.
int16_t regionWidth[VPI_WARPGRID_MAX_HORIZ_REGIONS_COUNT]
Width of each region.
int16_t regionHeight[VPI_WARPGRID_MAX_VERT_REGIONS_COUNT]
Height of each region.
void vpiWarpMapFreeData(VPIWarpMap *warpMap)
Deallocates the warp map control points allocated by vpiWarpMapAllocData.
VPIStatus vpiWarpMapAllocData(VPIWarpMap *warpMap)
Allocates the warp map's control point array for a given warp grid.
Defines the mapping between input and output images' pixels.