From 8d8c1fe5a7a0c0d89c8f11b41f8eef6c32c0684f Mon Sep 17 00:00:00 2001
From: Sebastian Hahta <joseha@utu.fi>
Date: Thu, 30 Jul 2020 14:43:12 +0300
Subject: [PATCH] rectification interpolation

---
 .../src/sources/stereovideo/rectification.cpp | 45 +++++++++----------
 .../src/sources/stereovideo/rectification.hpp | 13 ++++--
 .../src/sources/stereovideo/stereovideo.cpp   |  8 ++++
 3 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/components/rgbd-sources/src/sources/stereovideo/rectification.cpp b/components/rgbd-sources/src/sources/stereovideo/rectification.cpp
index 0b59d2ead..213aada07 100644
--- a/components/rgbd-sources/src/sources/stereovideo/rectification.cpp
+++ b/components/rgbd-sources/src/sources/stereovideo/rectification.cpp
@@ -24,13 +24,10 @@ StereoRectification::StereoRectification(nlohmann::json &config, cv::Size image_
 	enabled_(false), valid_(false), interpolation_(cv::INTER_LINEAR),
 	baseline_(0.0) {
 
-}
-
-void StereoRectification::setSize(cv::Size size) {
-	image_resolution_ = size;
-	if (calibrated()) {
-		calculateParameters();
-	}
+	map_l_.first.create(image_resolution_, map_format_);
+	map_l_.second.create(image_resolution_, map_format_);
+	map_r_.first.create(image_resolution_, map_format_);
+	map_r_.second.create(image_resolution_, map_format_);
 }
 
 void StereoRectification::setInterpolation(int interpolation) {
@@ -53,11 +50,11 @@ void StereoRectification::setCalibration(CalibrationData &calib) {
 	if (calib.hasCalibration(Channel::Left) && calib.hasCalibration(Channel::Right)) {
 		calib_left_ = calib.get(Channel::Left);
 		calib_right_ = calib.get(Channel::Right);
-		calculateParameters();
+		updateCalibration_();
 	}
 }
 
-void StereoRectification::calculateParameters() {
+void StereoRectification::updateCalibration_() {
 	using namespace ftl::calibration;
 	// TODO: lock
 	{
@@ -80,34 +77,36 @@ void StereoRectification::calculateParameters() {
 		tmp_r_ = cv::Mat(image_resolution_, CV_8UC4);
 	}
 
-	cv::Mat K_l = calib_left_.intrinsic.matrix(image_resolution_);
-	cv::Mat K_r = calib_right_.intrinsic.matrix(image_resolution_);
-	cv::Mat dc_l = calib_left_.intrinsic.distCoeffs.Mat();
-	cv::Mat dc_r = calib_right_.intrinsic.distCoeffs.Mat();
-
 	// calculate rotation and translation from left to right using calibration
 	cv::Mat T_l = calib_left_.extrinsic.matrix();
 	cv::Mat T_r = calib_right_.extrinsic.matrix();
 	cv::Mat T = T_r * transform::inverse(T_l);
-	cv::Mat R, t;
 
-	transform::getRotationAndTranslation(T, R, t);
-	baseline_ = cv::norm(t);
+	transform::getRotationAndTranslation(T, R_, t_);
+	baseline_ = cv::norm(t_);
 
 	if (baseline_ == 0.0) { return; }
+	valid_ = true;
+	calculateParameters_();
+}
+
+void StereoRectification::calculateParameters_() {
+	if (!valid_) { return; }
+
+	cv::Mat K_l = calib_left_.intrinsic.matrix(image_resolution_);
+	cv::Mat K_r = calib_right_.intrinsic.matrix(image_resolution_);
+	cv::Mat dc_l = calib_left_.intrinsic.distCoeffs.Mat();
+	cv::Mat dc_r = calib_right_.intrinsic.distCoeffs.Mat();
 
 	// calculate rectification parameters
 	cv::stereoRectify(	K_l, dc_l, K_r, dc_r, image_resolution_,
-						R, t, R_l_, R_r_, P_l_, P_r_, Q_, 0, 0);
+						R_, t_, R_l_, R_r_, P_l_, P_r_, Q_, 0, 0);
 
-	// for CPU remap, CV_16SC2 should give best performance
-	// https://docs.opencv.org/master/da/d54/group__imgproc__transform.html
 	cv::initUndistortRectifyMap(K_l, dc_l, R_l_, P_l_, image_resolution_,
-								CV_16SC2, map_l_.first, map_l_.second);
+								map_format_, map_l_.first, map_l_.second);
 	cv::initUndistortRectifyMap(K_r, dc_r, R_r_, P_r_, image_resolution_,
-								CV_16SC2, map_r_.first, map_r_.second);
+								map_format_, map_r_.first, map_r_.second);
 
-	valid_ = true;
 }
 
 void StereoRectification::rectify(cv::InputOutputArray im, Channel c) {
diff --git a/components/rgbd-sources/src/sources/stereovideo/rectification.hpp b/components/rgbd-sources/src/sources/stereovideo/rectification.hpp
index 07ec58052..2e924b7f3 100644
--- a/components/rgbd-sources/src/sources/stereovideo/rectification.hpp
+++ b/components/rgbd-sources/src/sources/stereovideo/rectification.hpp
@@ -29,10 +29,12 @@ class StereoRectification : public ftl::Configurable {
 public:
 	StereoRectification(nlohmann::json &config, cv::Size image_size);
 
-	/** Set OpenCV interpolation mode, see cv::InterpolationFlags */
+	/** Set OpenCV interpolation mode, see cv::InterpolationFlags.
+	 * NOTE: Artifacts possible if modified and rectify() is called in another
+	 * thread (no synchronization)
+	*/
 	void setInterpolation(int interpolation);
 
-	void setSize(cv::Size);
 	/**
 	 * Calculate rectification parameters from given calibration.
 	 */
@@ -62,7 +64,8 @@ public:
 	double doff(cv::Size);
 
 protected:
-	void calculateParameters();
+	void updateCalibration_();   // update calibration and calculate new params
+	void calculateParameters_(); // re-calculate rectification maps and params
 
 private:
 	ftl::calibration::CalibrationData::Calibration calib_left_;
@@ -75,6 +78,8 @@ private:
 	bool valid_;
 	int interpolation_;
 	double baseline_;
+	cv::Mat R_; // rotation left to right
+	cv::Mat t_; // translation left to right
 	cv::Mat Q_;
 	cv::Mat R_l_;
 	cv::Mat R_r_;
@@ -84,6 +89,8 @@ private:
 	// rectification maps for cv::remap(); should be CV_16SC2 if remap done on
 	// CPU and CV_32SC2 for GPU (generated by calculateParameters(), used by
 	// rectify())
+	// https://docs.opencv.org/master/da/d54/group__imgproc__transform.html
+	int map_format_ = CV_16SC2;
 	std::pair<cv::Mat,cv::Mat> map_l_;
 	std::pair<cv::Mat,cv::Mat> map_r_;
 
diff --git a/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp b/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp
index 12da67957..b7f3d6ce3 100644
--- a/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp
+++ b/components/rgbd-sources/src/sources/stereovideo/stereovideo.cpp
@@ -185,6 +185,14 @@ void StereoVideoSource::init(const string &file) {
 		do_update_params_ = true;
 	});
 
+	rectification_->setInterpolation(
+		host_->value("rectify_inter_cubic", false) ? cv::INTER_CUBIC : cv::INTER_LINEAR);
+
+	host_->on("rectify_inter_cubic", [this]() {
+		bool v = host_->value("rectify_inter_cubic", false);
+		rectification_->setInterpolation(v ? cv::INTER_CUBIC : cv::INTER_LINEAR);
+	});
+
 	host_->on("offset_z", [this]() {
 		do_update_params_ = true;
 	});
-- 
GitLab