From 6dc4ea34e44ae77125918ab9eda0fcfe7d9f0b3c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 15 Mar 2013 11:59:46 +0000 Subject: Multi-threaded frame calculation for movie clip proxies This commit implements multi-threaded calculation of frames when building proxies. Both scaling and undistortion steps are now threaded. Frames and proxy resolution are still handled one-by-one, saving files after every single step. So if HDD is not so fast, this commit could have not so much benefit. Internal changes: - Added IMB_scaleImBuf_threaded which scales given image buffer in multiple threads and uses bilinear filtering. - libmv's camera intrinsics now have SetThreads() method which is used to specify how many OpenMP threads to use for buffer distortion/undistortion. And yeah, this code is using OpenMP for threading. - Reshuffled a bit libmv-capi calls and added function BKE_tracking_distortion_set_threads to specify number of threads used by intrinscis. --- extern/libmv/libmv-capi.cpp | 14 +++++++ extern/libmv/libmv-capi.h | 4 ++ .../libmv/simple_pipeline/camera_intrinsics.cc | 47 +++++++++++++--------- .../libmv/simple_pipeline/camera_intrinsics.h | 5 +++ 4 files changed, 51 insertions(+), 19 deletions(-) (limited to 'extern') diff --git a/extern/libmv/libmv-capi.cpp b/extern/libmv/libmv-capi.cpp index a85c3268b16..eccf6fb7cb6 100644 --- a/extern/libmv/libmv-capi.cpp +++ b/extern/libmv/libmv-capi.cpp @@ -821,6 +821,13 @@ struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libm return (struct libmv_CameraIntrinsics *)&libmv_Reconstruction->intrinsics; } +struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNewEmpty(void) +{ + libmv::CameraIntrinsics *camera_intrinsics = new libmv::CameraIntrinsics(); + + return (struct libmv_CameraIntrinsics *) camera_intrinsics; +} + struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options) { libmv::CameraIntrinsics *camera_intrinsics = new libmv::CameraIntrinsics(); @@ -884,6 +891,13 @@ void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmv_intrinsic } } +void libmv_CameraIntrinsicsSetThreads(struct libmv_CameraIntrinsics *libmv_intrinsics, int threads) +{ + libmv::CameraIntrinsics *camera_intrinsics = (libmv::CameraIntrinsics *) libmv_intrinsics; + + camera_intrinsics->SetThreads(threads); +} + 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) { diff --git a/extern/libmv/libmv-capi.h b/extern/libmv/libmv-capi.h index c90322c56c5..c3debe45fd1 100644 --- a/extern/libmv/libmv-capi.h +++ b/extern/libmv/libmv-capi.h @@ -132,6 +132,8 @@ void libmv_destroyFeatures(struct libmv_Features *libmv_features); /* camera intrinsics */ struct libmv_CameraIntrinsics *libmv_ReconstructionExtractIntrinsics(struct libmv_Reconstruction *libmv_Reconstruction); +struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNewEmpty(void); + struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsNew(libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options); struct libmv_CameraIntrinsics *libmv_CameraIntrinsicsCopy(struct libmv_CameraIntrinsics *libmv_intrinsics); @@ -141,6 +143,8 @@ void libmv_CameraIntrinsicsDestroy(struct libmv_CameraIntrinsics *libmv_intrinsi void libmv_CameraIntrinsicsUpdate(struct libmv_CameraIntrinsics *libmv_intrinsics, libmv_cameraIntrinsicsOptions *libmv_camera_intrinsics_options); +void libmv_CameraIntrinsicsSetThreads(struct libmv_CameraIntrinsics *libmv_intrinsics, int threads); + 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); diff --git a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.cc b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.cc index 658f65c1367..543fddedd0c 100644 --- a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.cc +++ b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.cc @@ -62,7 +62,8 @@ CameraIntrinsics::CameraIntrinsics() p1_(0), p2_(0), distort_(0), - undistort_(0) {} + undistort_(0), + threads_(1) {} CameraIntrinsics::CameraIntrinsics(const CameraIntrinsics &from) : K_(from.K_), @@ -72,7 +73,8 @@ CameraIntrinsics::CameraIntrinsics(const CameraIntrinsics &from) k2_(from.k2_), k3_(from.k3_), p1_(from.p1_), - p2_(from.p2_) + p2_(from.p2_), + threads_(from.threads_) { distort_ = copyGrid(from.distort_); undistort_ = copyGrid(from.undistort_); @@ -120,6 +122,11 @@ void CameraIntrinsics::SetTangentialDistortion(double p1, double p2) { FreeLookupGrid(); } +void CameraIntrinsics::SetThreads(int threads) +{ + threads_ = threads; +} + void CameraIntrinsics::ApplyIntrinsics(double normalized_x, double normalized_y, double *image_x, @@ -188,6 +195,7 @@ void CameraIntrinsics::ComputeLookupGrid(Grid* grid, int width, int height, doub double aspx = (double)w / image_width_; double aspy = (double)h / image_height_; + #pragma omp parallel for schedule(dynamic) num_threads(threads_) if (threads_ > 1 && height > 100) for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { double src_x = (x - 0.5 * overscan * w) / aspx, src_y = (y - 0.5 * overscan * h) / aspy; @@ -214,7 +222,8 @@ void CameraIntrinsics::ComputeLookupGrid(Grid* grid, int width, int height, doub // TODO(MatthiasF): cubic B-Spline image sampling, bilinear lookup template static void Warp(const Grid* grid, const T* src, T* dst, - int width, int height) { + int width, int height, int threads) { + #pragma omp parallel for schedule(dynamic) num_threads(threads) if (threads > 1 && height > 100) for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { Offset offset = grid->offset[y*width+x]; @@ -306,37 +315,37 @@ void CameraIntrinsics::CheckUndistortLookupGrid(int width, int height, double ov void CameraIntrinsics::Distort(const float* src, float* dst, int width, int height, double overscan, int channels) { CheckDistortLookupGrid(width, height, overscan); - if(channels==1) Warp(distort_,src,dst,width,height); - else if(channels==2) Warp(distort_,src,dst,width,height); - else if(channels==3) Warp(distort_,src,dst,width,height); - else if(channels==4) Warp(distort_,src,dst,width,height); + if(channels==1) Warp(distort_,src,dst,width,height,threads_); + else if(channels==2) Warp(distort_,src,dst,width,height,threads_); + else if(channels==3) Warp(distort_,src,dst,width,height,threads_); + else if(channels==4) Warp(distort_,src,dst,width,height,threads_); //else assert("channels must be between 1 and 4"); } void CameraIntrinsics::Distort(const unsigned char* src, unsigned char* dst, int width, int height, double overscan, int channels) { CheckDistortLookupGrid(width, height, overscan); - if(channels==1) Warp(distort_,src,dst,width,height); - else if(channels==2) Warp(distort_,src,dst,width,height); - else if(channels==3) Warp(distort_,src,dst,width,height); - else if(channels==4) Warp(distort_,src,dst,width,height); + if(channels==1) Warp(distort_,src,dst,width,height,threads_); + else if(channels==2) Warp(distort_,src,dst,width,height,threads_); + else if(channels==3) Warp(distort_,src,dst,width,height,threads_); + else if(channels==4) Warp(distort_,src,dst,width,height,threads_); //else assert("channels must be between 1 and 4"); } void CameraIntrinsics::Undistort(const float* src, float* dst, int width, int height, double overscan, int channels) { CheckUndistortLookupGrid(width, height, overscan); - if(channels==1) Warp(undistort_,src,dst,width,height); - else if(channels==2) Warp(undistort_,src,dst,width,height); - else if(channels==3) Warp(undistort_,src,dst,width,height); - else if(channels==4) Warp(undistort_,src,dst,width,height); + if(channels==1) Warp(undistort_,src,dst,width,height,threads_); + else if(channels==2) Warp(undistort_,src,dst,width,height,threads_); + else if(channels==3) Warp(undistort_,src,dst,width,height,threads_); + else if(channels==4) Warp(undistort_,src,dst,width,height,threads_); //else assert("channels must be between 1 and 4"); } void CameraIntrinsics::Undistort(const unsigned char* src, unsigned char* dst, int width, int height, double overscan, int channels) { CheckUndistortLookupGrid(width, height, overscan); - if(channels==1) Warp(undistort_,src,dst,width,height); - else if(channels==2) Warp(undistort_,src,dst,width,height); - else if(channels==3) Warp(undistort_,src,dst,width,height); - else if(channels==4) Warp(undistort_,src,dst,width,height); + if(channels==1) Warp(undistort_,src,dst,width,height,threads_); + else if(channels==2) Warp(undistort_,src,dst,width,height,threads_); + else if(channels==3) Warp(undistort_,src,dst,width,height,threads_); + else if(channels==4) Warp(undistort_,src,dst,width,height,threads_); //else assert("channels must be between 1 and 4"); } diff --git a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h index b51b28a4bfb..632922c38ff 100644 --- a/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h +++ b/extern/libmv/libmv/simple_pipeline/camera_intrinsics.h @@ -68,6 +68,9 @@ class CameraIntrinsics { void SetTangentialDistortion(double p1, double p2); + /// Set number of threads using for buffer distortion/undistortion + void SetThreads(int threads); + /*! Apply camera intrinsics to the normalized point to get image coordinates. @@ -153,6 +156,8 @@ class CameraIntrinsics { struct Grid *distort_; struct Grid *undistort_; + + int threads_; }; /// A human-readable representation of the camera intrinsic parameters. -- cgit v1.2.3