Camera tracking: libmv distortion API now also uses camera intrinsics structure

instead of passing all the parameters to every function.

Makes it much easier to tweak distortion model.
This commit is contained in:
Sergey Sharybin 2012-12-10 16:38:28 +00:00
parent ec870eb214
commit 5137b5a146
3 changed files with 144 additions and 106 deletions

@ -564,6 +564,9 @@ static void cameraIntrinsicsFromOptions(libmv::CameraIntrinsics *camera_intrinsi
camera_intrinsics->SetRadialDistortion(camera_intrinsics_options->k1,
camera_intrinsics_options->k2,
camera_intrinsics_options->k3);
camera_intrinsics->SetImageSize(camera_intrinsics_options->image_width,
camera_intrinsics_options->image_height);
}
static libmv::Tracks getNormalizedTracks(libmv::Tracks *tracks, libmv::CameraIntrinsics *camera_intrinsics)
@ -897,17 +900,13 @@ struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libm
return (struct libmv_CameraIntrinsics *)&libmv_Reconstruction->intrinsics;
}
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(double focal_length, double principal_x, double principal_y,
double k1, double k2, double k3, int width, int height)
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options)
{
libmv::CameraIntrinsics *intrinsics= new libmv::CameraIntrinsics();
libmv::CameraIntrinsics *camera_intrinsics = new libmv::CameraIntrinsics();
intrinsics->SetFocalLength(focal_length, focal_length);
intrinsics->SetPrincipalPoint(principal_x, principal_y);
intrinsics->SetRadialDistortion(k1, k2, k3);
intrinsics->SetImageSize(width, height);
cameraIntrinsicsFromOptions(camera_intrinsics, libmv_camera_intrinsics_options);
return (struct libmv_CameraIntrinsics *) intrinsics;
return (struct libmv_CameraIntrinsics *) camera_intrinsics;
}
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmvIntrinsics)
@ -925,40 +924,63 @@ void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmvIntrinsic
delete intrinsics;
}
void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics, double focal_length,
double principal_x, double principal_y, double k1, double k2, double k3, int width, int height)
void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmv_intrinsics,
libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options)
{
libmv::CameraIntrinsics *intrinsics = (libmv::CameraIntrinsics *) libmvIntrinsics;
libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics;
if (intrinsics->focal_length() != focal_length)
intrinsics->SetFocalLength(focal_length, focal_length);
double focal_length = libmv_camera_intrinsics_options->focal_length;
double principal_x = libmv_camera_intrinsics_options->principal_point_x;
double principal_y = libmv_camera_intrinsics_options->principal_point_y;
double k1 = libmv_camera_intrinsics_options->k1;
double k2 = libmv_camera_intrinsics_options->k2;
double k3 = libmv_camera_intrinsics_options->k3;
int image_width = libmv_camera_intrinsics_options->image_width;
int image_height = libmv_camera_intrinsics_options->image_height;
if (intrinsics->principal_point_x() != principal_x || intrinsics->principal_point_y() != principal_y)
intrinsics->SetPrincipalPoint(principal_x, principal_y);
/* try avoid unnecessary updates so pre-computed distortion grids are not freed */
if (intrinsics->k1() != k1 || intrinsics->k2() != k2 || intrinsics->k3() != k3)
intrinsics->SetRadialDistortion(k1, k2, k3);
if (camera_intrinsics->focal_length() != focal_length)
camera_intrinsics->SetFocalLength(focal_length, focal_length);
if (intrinsics->image_width() != width || intrinsics->image_height() != height)
intrinsics->SetImageSize(width, height);
if (camera_intrinsics->principal_point_x() != principal_x ||
camera_intrinsics->principal_point_y() != principal_y)
{
camera_intrinsics->SetPrincipalPoint(principal_x, principal_y);
}
if (camera_intrinsics->k1() != k1 ||
camera_intrinsics->k2() != k2 ||
camera_intrinsics->k3() != k3)
{
camera_intrinsics->SetRadialDistortion(k1, k2, k3);
}
if (camera_intrinsics->image_width() != image_width ||
camera_intrinsics->image_height() != image_height)
{
camera_intrinsics->SetImageSize(image_width, image_height);
}
}
void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmvIntrinsics, double *focal_length,
double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height) {
libmv::CameraIntrinsics *intrinsics= (libmv::CameraIntrinsics *) libmvIntrinsics;
*focal_length = intrinsics->focal_length();
*principal_x = intrinsics->principal_point_x();
*principal_y = intrinsics->principal_point_y();
*k1 = intrinsics->k1();
*k2 = intrinsics->k2();
void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmv_intrinsics, double *focal_length,
double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height)
{
libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics;
*focal_length = camera_intrinsics->focal_length();
*principal_x = camera_intrinsics->principal_point_x();
*principal_y = camera_intrinsics->principal_point_y();
*k1 = camera_intrinsics->k1();
*k2 = camera_intrinsics->k2();
}
void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics,
void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmv_intrinsics,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels)
{
libmv::CameraIntrinsics *intrinsics = (libmv::CameraIntrinsics *) libmvIntrinsics;
libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics;
intrinsics->Undistort(src, dst, width, height, overscan, channels);
camera_intrinsics->Undistort(src, dst, width, height, overscan, channels);
}
void libmv_CameraIntrinsicsUndistortFloat(struct libmv_CameraIntrinsics *libmvIntrinsics,
@ -986,85 +1008,77 @@ void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmvIntr
/* ************ distortion ************ */
void libmv_undistortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels)
void libmv_undistortByte(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
unsigned char *src, unsigned char *dst, int width, int height,
float overscan, int channels)
{
libmv::CameraIntrinsics intrinsics;
libmv::CameraIntrinsics camera_intrinsics;
intrinsics.SetFocalLength(focal_length, focal_length);
intrinsics.SetPrincipalPoint(principal_x, principal_y);
intrinsics.SetRadialDistortion(k1, k2, k3);
cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options);
intrinsics.Undistort(src, dst, width, height, overscan, channels);
camera_intrinsics.Undistort(src, dst, width, height, overscan, channels);
}
void libmv_undistortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
float *src, float *dst, int width, int height, float overscan, int channels)
void libmv_undistortFloat(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
float *src, float *dst, int width, int height,
float overscan, int channels)
{
libmv::CameraIntrinsics intrinsics;
libmv::CameraIntrinsics camera_intrinsics;
intrinsics.SetFocalLength(focal_length, focal_length);
intrinsics.SetPrincipalPoint(principal_x, principal_y);
intrinsics.SetRadialDistortion(k1, k2, k3);
cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options);
intrinsics.Undistort(src, dst, width, height, overscan, channels);
camera_intrinsics.Undistort(src, dst, width, height, overscan, channels);
}
void libmv_distortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels)
void libmv_distortByte(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
unsigned char *src, unsigned char *dst, int width, int height,
float overscan, int channels)
{
libmv::CameraIntrinsics intrinsics;
libmv::CameraIntrinsics camera_intrinsics;
intrinsics.SetFocalLength(focal_length, focal_length);
intrinsics.SetPrincipalPoint(principal_x, principal_y);
intrinsics.SetRadialDistortion(k1, k2, k3);
cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options);
intrinsics.Distort(src, dst, width, height, overscan, channels);
camera_intrinsics.Distort(src, dst, width, height, overscan, channels);
}
void libmv_distortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
float *src, float *dst, int width, int height, float overscan, int channels)
void libmv_distortFloat(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
float *src, float *dst, int width, int height,
float overscan, int channels)
{
libmv::CameraIntrinsics intrinsics;
libmv::CameraIntrinsics camera_intrinsics;
intrinsics.SetFocalLength(focal_length, focal_length);
intrinsics.SetPrincipalPoint(principal_x, principal_y);
intrinsics.SetRadialDistortion(k1, k2, k3);
cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options);
intrinsics.Distort(src, dst, width, height, overscan, channels);
camera_intrinsics.Distort(src, dst, width, height, overscan, channels);
}
/* ************ utils ************ */
void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
double x, double y, double *x1, double *y1)
void libmv_applyCameraIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
double x, double y, double *x1, double *y1)
{
libmv::CameraIntrinsics intrinsics;
libmv::CameraIntrinsics camera_intrinsics;
intrinsics.SetFocalLength(focal_length, focal_length);
intrinsics.SetPrincipalPoint(principal_x, principal_y);
intrinsics.SetRadialDistortion(k1, k2, k3);
cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options);
if(focal_length) {
if (libmv_camera_intrinsics_options->focal_length) {
/* do a lens undistortion if focal length is non-zero only */
intrinsics.ApplyIntrinsics(x, y, x1, y1);
camera_intrinsics.ApplyIntrinsics(x, y, x1, y1);
}
}
void libmv_InvertIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
double x, double y, double *x1, double *y1)
void libmv_InvertIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
double x, double y, double *x1, double *y1)
{
libmv::CameraIntrinsics intrinsics;
libmv::CameraIntrinsics camera_intrinsics;
intrinsics.SetFocalLength(focal_length, focal_length);
intrinsics.SetPrincipalPoint(principal_x, principal_y);
intrinsics.SetRadialDistortion(k1, k2, k3);
cameraIntrinsicsFromOptions(&camera_intrinsics, libmv_camera_intrinsics_options);
if(focal_length) {
if (libmv_camera_intrinsics_options->focal_length) {
/* do a lens distortion if focal length is non-zero only */
intrinsics.InvertIntrinsics(x, y, x1, y1);
camera_intrinsics.InvertIntrinsics(x, y, x1, y1);
}
}

@ -97,6 +97,7 @@ typedef struct libmv_cameraIntrinsicsOptions {
double principal_point_x, principal_point_y;
double k1, k2, k3;
double p1, p2;
int image_width, image_height;
} libmv_cameraIntrinsicsOptions;
typedef struct libmv_reconstructionOptions {
@ -139,46 +140,45 @@ void libmv_destroyFeatures(struct libmv_Features *libmv_features);
/* camera intrinsics */
struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libmv_Reconstruction *libmv_Reconstruction);
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(double focal_length, double principal_x, double principal_y,
double k1, double k2, double k3, int width, int height);
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options);
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmvIntrinsics);
struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmv_intrinsics);
void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmvIntrinsics);
void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmv_intrinsics);
void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmvIntrinsics, double focal_length,
double principal_x, double principal_y, double k1, double k2, double k3, int width, int height);
void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmv_intrinsics,
libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options);
void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmvIntrinsics, double *focal_length,
void libmv_CameraIntrinsicsExtract(struct libmv_CameraIntrinsics *libmv_intrinsics, double *focal_length,
double *principal_x, double *principal_y, double *k1, double *k2, double *k3, int *width, int *height);
void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics,
void libmv_CameraIntrinsicsUndistortByte(struct libmv_CameraIntrinsics *libmv_intrinsics,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
void libmv_CameraIntrinsicsUndistortFloat(struct libmv_CameraIntrinsics *libmvIntrinsics,
void libmv_CameraIntrinsicsUndistortFloat(struct libmv_CameraIntrinsics *libmv_intrinsics,
float *src, float *dst, int width, int height, float overscan, int channels);
void libmv_CameraIntrinsicsDistortByte(struct libmv_CameraIntrinsics *libmvIntrinsics,
void libmv_CameraIntrinsicsDistortByte(struct libmv_CameraIntrinsics *libmv_intrinsics,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmvIntrinsics,
void libmv_CameraIntrinsicsDistortFloat(struct libmv_CameraIntrinsics *libmv_intrinsics,
float *src, float *dst, int width, int height, float overscan, int channels);
/* dsitortion */
void libmv_undistortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
void libmv_undistortByte(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
void libmv_undistortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
void libmv_undistortFloat(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
float *src, float *dst, int width, int height, float overscan, int channels);
void libmv_distortByte(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
void libmv_distortByte(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
unsigned char *src, unsigned char *dst, int width, int height, float overscan, int channels);
void libmv_distortFloat(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
void libmv_distortFloat(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
float *src, float *dst, int width, int height, float overscan, int channels);
/* utils */
void libmv_applyCameraIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
void libmv_applyCameraIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
double x, double y, double *x1, double *y1);
void libmv_InvertIntrinsics(double focal_length, double principal_x, double principal_y, double k1, double k2, double k3,
void libmv_InvertIntrinsics(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options,
double x, double y, double *x1, double *y1);
/* point clouds */

@ -1426,6 +1426,27 @@ void BKE_tracking_camera_get_reconstructed_interpolate(MovieTracking *tracking,
/*********************** Distortion/Undistortion *************************/
#ifdef WITH_LIBMV
static void cameraIntrinscisOptionsFromTracking(libmv_cameraIntrinsicsOptions *camera_intrinsics_options,
MovieTracking *tracking, int calibration_width, int calibration_height)
{
MovieTrackingCamera *camera = &tracking->camera;
float aspy = 1.0f / tracking->camera.pixel_aspect;
camera_intrinsics_options->focal_length = camera->focal;
camera_intrinsics_options->principal_point_x = camera->principal[0];
camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy;
camera_intrinsics_options->k1 = camera->k1;
camera_intrinsics_options->k2 = camera->k2;
camera_intrinsics_options->k3 = camera->k3;
camera_intrinsics_options->image_width = calibration_width;
camera_intrinsics_options->image_height = (double) calibration_height * aspy;
}
#endif
MovieDistortion *BKE_tracking_distortion_new(void)
{
MovieDistortion *distortion;
@ -1438,21 +1459,17 @@ MovieDistortion *BKE_tracking_distortion_new(void)
void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking,
int calibration_width, int calibration_height)
{
MovieTrackingCamera *camera = &tracking->camera;
float aspy = 1.0f / tracking->camera.pixel_aspect;
#ifdef WITH_LIBMV
libmv_cameraIntrinsicsOptions camera_intrinsics_options;
cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking,
calibration_width, calibration_height);
if (!distortion->intrinsics) {
distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal,
camera->principal[0], camera->principal[1] * aspy,
camera->k1, camera->k2, camera->k3,
calibration_width, calibration_height * aspy);
distortion->intrinsics = libmv_CameraIntrinsicsNew(&camera_intrinsics_options);
}
else {
libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
camera->principal[0], camera->principal[1] * aspy,
camera->k1, camera->k2, camera->k3,
calibration_width, calibration_height * aspy);
libmv_CameraIntrinsicsUpdate(distortion->intrinsics, &camera_intrinsics_options);
}
#else
(void) distortion;
@ -1540,15 +1557,17 @@ void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r
MovieTrackingCamera *camera = &tracking->camera;
#ifdef WITH_LIBMV
libmv_cameraIntrinsicsOptions camera_intrinsics_options;
double x, y;
float aspy = 1.0f / tracking->camera.pixel_aspect;
cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
/* normalize coords */
x = (co[0] - camera->principal[0]) / camera->focal;
y = (co[1] - camera->principal[1] * aspy) / camera->focal;
libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
camera->k1, camera->k2, camera->k3, x, y, &x, &y);
libmv_applyCameraIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
/* result is in image coords already */
r_co[0] = x;
@ -1565,11 +1584,13 @@ void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float
MovieTrackingCamera *camera = &tracking->camera;
#ifdef WITH_LIBMV
libmv_cameraIntrinsicsOptions camera_intrinsics_options;
double x = co[0], y = co[1];
float aspy = 1.0f / tracking->camera.pixel_aspect;
libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
camera->k1, camera->k2, camera->k3, x, y, &x, &y);
cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
libmv_InvertIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
r_co[0] = x * camera->focal + camera->principal[0];
r_co[1] = y * camera->focal + camera->principal[1] * aspy;
@ -2944,6 +2965,9 @@ static void camraIntrincicsOptionsFromContext(libmv_cameraIntrinsicsOptions *cam
camera_intrinsics_options->k1 = context->k1;
camera_intrinsics_options->k2 = context->k2;
camera_intrinsics_options->k3 = context->k3;
camera_intrinsics_options->image_width = 0;
camera_intrinsics_options->image_height = 0;
}
static void reconstructionOptionsFromContext(libmv_reconstructionOptions *reconstruction_options,