Skip to content
Snippets Groups Projects
stereovideo_source.cpp 3.47 KiB
Newer Older
Nicolas Pope's avatar
Nicolas Pope committed
#include <glog/logging.h>
#include <ftl/stereovideo_source.hpp>
#include <ftl/configuration.hpp>
#include "calibrate.hpp"
#include "local.hpp"
#include "disparity.hpp"
#include <mutex>
Nicolas Pope's avatar
Nicolas Pope committed

using ftl::Calibrate;
using ftl::LocalSource;
using ftl::rgbd::StereoVideoSource;
using std::string;
using std::mutex;
using std::unique_lock;
Nicolas Pope's avatar
Nicolas Pope committed

StereoVideoSource::StereoVideoSource(nlohmann::json &config, ftl::net::Universe *net)
		: RGBDSource(config, net) {

}

StereoVideoSource::StereoVideoSource(nlohmann::json &config, const string &file)
		: RGBDSource(config), ready_(false) {

	REQUIRED({
Nicolas Pope's avatar
Nicolas Pope committed
		{"feed","Details on source video [object]","object"}
Nicolas Pope's avatar
Nicolas Pope committed
	});
	
	if (ftl::is_video(file)) {
		// Load video file
		LOG(INFO) << "Using video file...";
Nicolas Pope's avatar
Nicolas Pope committed
		//lsrc_ = new LocalSource(file, config["source"]);
		lsrc_ = ftl::create<LocalSource>(this, "feed", file);
Nicolas Pope's avatar
Nicolas Pope committed
	} else if (file != "") {
		auto vid = ftl::locateFile("video.mp4");
		if (!vid) {
Nicolas Pope's avatar
Nicolas Pope committed
			LOG(FATAL) << "No video.mp4 file found in provided paths (" << file << ")";
Nicolas Pope's avatar
Nicolas Pope committed
		} else {
			LOG(INFO) << "Using test directory...";
Nicolas Pope's avatar
Nicolas Pope committed
			//lsrc_ = new LocalSource(*vid, config["source"]);
			lsrc_ = ftl::create<LocalSource>(this, "feed", *vid);
Nicolas Pope's avatar
Nicolas Pope committed
		}
	} else {
		// Use cameras
		LOG(INFO) << "Using cameras...";
Nicolas Pope's avatar
Nicolas Pope committed
		//lsrc_ = new LocalSource(config["source"]);
		lsrc_ = ftl::create<LocalSource>(this, "feed");
Nicolas Pope's avatar
Nicolas Pope committed
	//calib_ = new Calibrate(lsrc_, ftl::resolve(config["calibration"]));
	calib_ = ftl::create<Calibrate>(this, "calibration", lsrc_);

	if (value("calibrate", false)) calib_->recalibrate();
Nicolas Pope's avatar
Nicolas Pope committed
	if (!calib_->isCalibrated()) LOG(WARNING) << "Cameras are not calibrated!";
	else LOG(INFO) << "Calibration initiated.";

	// Generate camera parameters from Q matrix
	cv::Mat q = calib_->getCameraMatrix();
Nicolas Pope's avatar
Nicolas Pope committed
	params_ = {
		// TODO(Nick) Add fx and fy
Nicolas Pope's avatar
Nicolas Pope committed
		q.at<double>(0,0),	// Fx
		q.at<double>(1,1),	// Fy
		-q.at<double>(0,2),	// Cx
		-q.at<double>(1,2),	// Cy
Nicolas Pope's avatar
Nicolas Pope committed
		(unsigned int)lsrc_->width(),  // TODO (Nick)
		(unsigned int)lsrc_->height(),
Nicolas Pope's avatar
Nicolas Pope committed
		0.0f,	// 0m min
		15.0f	// 15m max
	};
	
	// left and right masks (areas outside rectified images)
	// only left mask used
	cv::Mat mask_r(lsrc_->height(), lsrc_->width(), CV_8U, 255);
	cv::Mat mask_l(lsrc_->height(), lsrc_->width(), CV_8U, 255);
	calib_->rectifyStereo(mask_l, mask_r);
	mask_l_ = (mask_l == 0);
	
Nicolas Pope's avatar
Nicolas Pope committed
	disp_ = Disparity::create(this, "disparity");
    if (!disp_) LOG(FATAL) << "Unknown disparity algorithm : " << *get<ftl::config::json_t>("disparity");
Sebastian Hahta's avatar
Sebastian Hahta committed
	disp_->setMask(mask_l_);
Nicolas Pope's avatar
Nicolas Pope committed

	LOG(INFO) << "StereoVideo source ready...";
	ready_ = true;
}

StereoVideoSource::~StereoVideoSource() {
	delete disp_;
	delete calib_;
	delete lsrc_;
}

static void disparityToDepth(const cv::Mat &disparity, cv::Mat &depth, const cv::Mat &q) {
	cv::Matx44d _Q;
    q.convertTo(_Q, CV_64F);

	if (depth.empty()) depth = cv::Mat(disparity.size(), CV_32F);

	for( int y = 0; y < disparity.rows; y++ ) {
		const float *sptr = disparity.ptr<float>(y);
		float *dptr = depth.ptr<float>(y);

		for( int x = 0; x < disparity.cols; x++ ) {
			double d = sptr[x];
			cv::Vec4d homg_pt = _Q*cv::Vec4d(x, y, d, 1.0);
			//dptr[x] = Vec3d(homg_pt.val);
			//dptr[x] /= homg_pt[3];
			dptr[x] = (homg_pt[2] / homg_pt[3]) / 1000.0f; // Depth in meters

			if( fabs(d) <= FLT_EPSILON )
				dptr[x] = 1000.0f;
		}
	}
}

void StereoVideoSource::grab() {
	calib_->rectified(left_, right_);

Nicolas Pope's avatar
Nicolas Pope committed
	cv::Mat disp;
Sebastian Hahta's avatar
Sebastian Hahta committed
	disp_->compute(left_, right_, disp);

	unique_lock<mutex> lk(mutex_);
	left_.copyTo(rgb_);
	disparityToDepth(disp, depth_, calib_->getQ());
}

bool StereoVideoSource::isReady() {
	return ready_;
Nicolas Pope's avatar
Nicolas Pope committed
}