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>
53 #define CHECK_STATUS(STMT) \
56 VPIStatus status = (STMT); \
57 if (status != VPI_SUCCESS) \
59 char buffer[VPI_MAX_STATUS_MESSAGE_LENGTH]; \
60 vpiGetLastStatusMessage(buffer, sizeof(buffer)); \
61 std::ostringstream ss; \
62 ss << vpiStatusGetName(status) << ": " << buffer; \
63 throw std::runtime_error(ss.str()); \
67 static void PrintUsage(
const char *progname, std::ostream &out)
69 out <<
"Usage: " << progname <<
" <-c W,H> [-s win] <image1> [image2] [image3] ...\n"
71 <<
" W,H\tcheckerboard with WxH squares\n"
72 <<
" win\tsearch window width around checkerboard vertex used\n"
73 <<
"\tin refinement, default is 0 (disable refinement)\n"
74 <<
" imageN\tinput images taken with a fisheye lens camera" << std::endl;
81 std::vector<const char *> images;
84 static Params ParseParameters(
int argc,
char *argv[])
92 while ((opt = getopt(argc, argv,
"hc:s:")) != -1)
97 PrintUsage(basename(argv[0]), std::cout);
101 if (sscanf(optarg,
"%d,%d", &cbSize.width, &cbSize.height) != 2)
103 throw std::invalid_argument(
"Error parsing checkerboard information");
108 params.vtxCount.width = cbSize.width - 1;
109 params.vtxCount.height = cbSize.height - 1;
113 if (sscanf(optarg,
"%d", ¶ms.searchWinSize) != 1)
115 throw std::invalid_argument(
"Error parseing search window size");
117 if (params.searchWinSize < 0)
119 throw std::invalid_argument(
"Search window size must be >= 0");
123 throw std::invalid_argument(std::string(
"Option -") + (
char)optopt +
" not recognized");
127 for (
int i = optind; i < argc; ++i)
129 params.images.push_back(argv[i]);
132 if (params.images.empty())
134 throw std::invalid_argument(
"At least one image must be defined");
137 if (cbSize.width <= 3 || cbSize.height <= 3)
139 throw std::invalid_argument(
"Checkerboard size must have at least 3x3 squares");
142 if (params.searchWinSize == 1)
144 throw std::invalid_argument(
"Search window size must be 0 (default) or >= 2");
150 int main(
int argc,
char *argv[])
159 VPIImage tmpIn = NULL, tmpOut = NULL;
167 Params params = ParseParameters(argc, argv);
168 if (params.images.empty())
174 std::vector<std::vector<cv::Point2f>> corners2D;
177 cv::Size imgSize = {};
179 for (
unsigned i = 0; i < params.images.size(); ++i)
182 cv::Mat img = cv::imread(params.images[i]);
185 throw std::runtime_error(
"Can't read " + std::string(params.images[i]));
188 if (imgSize == cv::Size{})
190 imgSize = img.size();
192 else if (imgSize != img.size())
194 throw std::runtime_error(
"All images must have same size");
200 std::vector<cv::Point2f> cbVertices;
202 if (findChessboardCorners(img, params.vtxCount, cbVertices,
203 cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE))
206 if (params.searchWinSize >= 2)
209 cvtColor(img, gray, cv::COLOR_BGR2GRAY);
211 cornerSubPix(gray, cbVertices, cv::Size(params.searchWinSize / 2, params.searchWinSize / 2),
213 cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.0001));
217 corners2D.push_back(std::move(cbVertices));
221 std::cerr <<
"Warning: checkerboard pattern not found in image " << params.images[i] << std::endl;
228 std::vector<cv::Point3f> initialCheckerboard3DVertices;
229 for (
int i = 0; i < params.vtxCount.height; ++i)
231 for (
int j = 0; j < params.vtxCount.width; ++j)
235 initialCheckerboard3DVertices.emplace_back(j, i, 0);
240 std::vector<std::vector<cv::Point3f>> corners3D(corners2D.size(), initialCheckerboard3DVertices);
243 using Mat3 = cv::Matx<double, 3, 3>;
244 Mat3 camMatrix = Mat3::eye();
247 std::vector<double> coeffs(4);
251 int flags = cv::fisheye::CALIB_FIX_SKEW;
255 cv::Mat rvecs, tvecs;
256 double rms = cv::fisheye::calibrate(corners3D, corners2D, imgSize, camMatrix, coeffs, rvecs, tvecs, flags);
257 printf(
"rms error: %lf\n", rms);
261 printf(
"Fisheye coefficients: %lf %lf %lf %lf\n", coeffs[0], coeffs[1], coeffs[2], coeffs[3]);
263 printf(
"Camera matrix:\n");
264 printf(
"[%lf %lf %lf; %lf %lf %lf; %lf %lf %lf]\n", camMatrix(0, 0), camMatrix(0, 1), camMatrix(0, 2),
265 camMatrix(1, 0), camMatrix(1, 1), camMatrix(1, 2), camMatrix(2, 0), camMatrix(2, 1), camMatrix(2, 2));
282 distModel.
k1 = coeffs[0];
283 distModel.
k2 = coeffs[1];
284 distModel.
k3 = coeffs[2];
285 distModel.
k4 = coeffs[3];
289 for (
int i = 0; i < 2; ++i)
291 for (
int j = 0; j < 3; ++j)
293 K[i][j] = camMatrix(i, j);
299 X[0][0] = X[1][1] = X[2][2] = 1;
320 for (
unsigned i = 0; i < params.images.size(); ++i)
323 cvImage = cv::imread(params.images[i]);
324 assert(!cvImage.empty());
353 snprintf(buf,
sizeof(buf),
"undistort_%03d.jpg", i);
354 imwrite(buf, cvImage);
357 catch (std::exception &e)
359 std::cerr <<
"Error: " << e.what() << std::endl;
360 PrintUsage(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, uint32_t flags, VPIImage *img)
Create an empty image instance with the specified flags.
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 vpiImageSetWrappedOpenCVMat(VPIImage img, const cv::Mat &mat)
Redefines the wrapped cv::Mat of an existing VPIImage wrapper.
VPIStatus vpiImageCreateOpenCVMatWrapper(const cv::Mat &mat, VPIImageFormat fmt, uint32_t flags, VPIImage *img)
Wraps a cv::Mat in an VPIImage with the given image format.
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, uint32_t backend, VPIPayload payload, VPIImage input, VPIImage output, VPIInterpolationType interp, VPIBorderExtension border, uint32_t flags)
Submits the Remap operation to the stream associated with the payload.
VPIStatus vpiCreateRemap(uint32_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(uint32_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.