29 #include <opencv2/core/version.hpp>
31 #if CV_MAJOR_VERSION >= 3
32 # include <opencv2/imgcodecs.hpp>
34 # include <opencv2/highgui/highgui.hpp>
38 #if CV_VERSION_MAJOR * 100 + CV_VERSION_MINOR >= 410
39 # error "OpenCV >= 4.10 isn't supported"
42 #include <opencv2/calib3d/calib3d.hpp>
43 #include <opencv2/imgproc/imgproc.hpp>
56 #define CHECK_STATUS(STMT) \
59 VPIStatus status = (STMT); \
60 if (status != VPI_SUCCESS) \
62 char buffer[VPI_MAX_STATUS_MESSAGE_LENGTH]; \
63 vpiGetLastStatusMessage(buffer, sizeof(buffer)); \
64 std::ostringstream ss; \
65 ss << vpiStatusGetName(status) << ": " << buffer; \
66 throw std::runtime_error(ss.str()); \
70 static void PrintUsage(
const char *progname, std::ostream &out)
72 out <<
"Usage: " << progname <<
" <-c W,H> [-s win] <image1> [image2] [image3] ...\n"
74 <<
" W,H\tcheckerboard with WxH squares\n"
75 <<
" win\tsearch window width around checkerboard vertex used\n"
76 <<
"\tin refinement, default is 0 (disable refinement)\n"
77 <<
" imageN\tinput images taken with a fisheye lens camera" << std::endl;
80 static char *my_basename(
char *path)
83 char *name = strrchr(path,
'\\');
85 char *name = strrchr(path,
'/');
101 std::vector<const char *> images;
104 static Params ParseParameters(
int argc,
char *argv[])
110 for (
int i = 1; i < argc; ++i)
112 if (argv[i][0] ==
'-')
114 if (strlen(argv[i] + 1) == 1)
119 PrintUsage(my_basename(argv[0]), std::cout);
125 throw std::invalid_argument(
"Option -c must be followed by checkerboard width and height");
128 if (sscanf(argv[++i],
"%d,%d", &cbSize.width, &cbSize.height) != 2)
130 throw std::invalid_argument(
"Error parsing checkerboard information");
135 params.vtxCount.width = cbSize.width - 1;
136 params.vtxCount.height = cbSize.height - 1;
142 throw std::invalid_argument(
"Option -s must be followed by search window size");
144 if (sscanf(argv[++i],
"%d", ¶ms.searchWinSize) != 1)
146 throw std::invalid_argument(
"Error parsing search window size");
148 if (params.searchWinSize < 0)
150 throw std::invalid_argument(
"Search window size must be >= 0");
155 throw std::invalid_argument(std::string(
"Option -") + (argv[i] + 1) +
" not recognized");
160 throw std::invalid_argument(std::string(
"Option -") + (argv[i] + 1) +
" not recognized");
165 params.images.push_back(argv[i]);
169 if (params.images.empty())
171 throw std::invalid_argument(
"At least one image must be defined");
174 if (cbSize.width <= 3 || cbSize.height <= 3)
176 throw std::invalid_argument(
"Checkerboard size must have at least 3x3 squares");
179 if (params.searchWinSize == 1)
181 throw std::invalid_argument(
"Search window size must be 0 (default) or >= 2");
187 int main(
int argc,
char *argv[])
196 VPIImage tmpIn = NULL, tmpOut = NULL;
204 Params params = ParseParameters(argc, argv);
205 if (params.images.empty())
211 std::vector<std::vector<cv::Point2f>> corners2D;
214 cv::Size imgSize = {};
216 for (
unsigned i = 0; i < params.images.size(); ++i)
219 cv::Mat img = cv::imread(params.images[i]);
222 throw std::runtime_error(
"Can't read " + std::string(params.images[i]));
225 if (imgSize == cv::Size{})
227 imgSize = img.size();
229 else if (imgSize != img.size())
231 throw std::runtime_error(
"All images must have same size");
237 std::vector<cv::Point2f> cbVertices;
239 if (findChessboardCorners(img, params.vtxCount, cbVertices,
240 cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE))
243 if (params.searchWinSize >= 2)
246 cvtColor(img, gray, cv::COLOR_BGR2GRAY);
248 cornerSubPix(gray, cbVertices, cv::Size(params.searchWinSize / 2, params.searchWinSize / 2),
250 cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.0001));
254 corners2D.push_back(std::move(cbVertices));
258 std::cerr <<
"Warning: checkerboard pattern not found in image " << params.images[i] << std::endl;
265 std::vector<cv::Point3f> initialCheckerboard3DVertices;
266 for (
int i = 0; i < params.vtxCount.height; ++i)
268 for (
int j = 0; j < params.vtxCount.width; ++j)
272 initialCheckerboard3DVertices.emplace_back(
static_cast<float>(j),
static_cast<float>(i), 0.0f);
277 std::vector<std::vector<cv::Point3f>> corners3D(corners2D.size(), initialCheckerboard3DVertices);
280 using Mat3 = cv::Matx<double, 3, 3>;
281 Mat3 camMatrix = Mat3::eye();
284 std::vector<double> coeffs(4);
288 int flags = cv::fisheye::CALIB_FIX_SKEW;
292 cv::Mat rvecs, tvecs;
293 double rms = cv::fisheye::calibrate(corners3D, corners2D, imgSize, camMatrix, coeffs, rvecs, tvecs, flags);
294 printf(
"rms error: %lf\n", rms);
298 printf(
"Fisheye coefficients: %lf %lf %lf %lf\n", coeffs[0], coeffs[1], coeffs[2], coeffs[3]);
300 printf(
"Camera matrix:\n");
301 printf(
"[%lf %lf %lf; %lf %lf %lf; %lf %lf %lf]\n", camMatrix(0, 0), camMatrix(0, 1), camMatrix(0, 2),
302 camMatrix(1, 0), camMatrix(1, 1), camMatrix(1, 2), camMatrix(2, 0), camMatrix(2, 1), camMatrix(2, 2));
319 distModel.
k1 = coeffs[0];
320 distModel.
k2 = coeffs[1];
321 distModel.
k3 = coeffs[2];
322 distModel.
k4 = coeffs[3];
326 for (
int i = 0; i < 2; ++i)
328 for (
int j = 0; j < 3; ++j)
330 K[i][j] = camMatrix(i, j);
336 X[0][0] = X[1][1] = X[2][2] = 1;
357 for (
unsigned i = 0; i < params.images.size(); ++i)
360 cvImage = cv::imread(params.images[i]);
361 assert(!cvImage.empty());
390 snprintf(buf,
sizeof(buf),
"undistort_%03d.jpg", i);
391 imwrite(buf, cvImage);
394 catch (std::exception &e)
396 std::cerr <<
"Error: " << e.what() << std::endl;
397 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.