Skip to content
Snippets Groups Projects
stereovideo.cpp 3.5 KiB
Newer Older
Nicolas Pope's avatar
Nicolas Pope committed
#include <loguru.hpp>
#include "stereovideo.hpp"
Nicolas Pope's avatar
Nicolas Pope committed
#include <ftl/configuration.hpp>
#include "calibrate.hpp"
#include "local.hpp"
#include "disparity.hpp"
#include <mutex>
Nicolas Pope's avatar
Nicolas Pope committed

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

StereoVideoSource::StereoVideoSource(ftl::rgbd::Source *host)
		: ftl::rgbd::detail::Source(host), ready_(false) {
Nicolas Pope's avatar
Nicolas Pope committed
	init("");
StereoVideoSource::StereoVideoSource(ftl::rgbd::Source *host, const string &file)
		: ftl::rgbd::detail::Source(host), ready_(false) {
Nicolas Pope's avatar
Nicolas Pope committed

Nicolas Pope's avatar
Nicolas Pope committed
	init(file);
}

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

void StereoVideoSource::init(const string &file) {
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>(host_, "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>(host_, "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>(host_, "feed");
Nicolas Pope's avatar
Nicolas Pope committed
	//calib_ = new Calibrate(lsrc_, ftl::resolve(config["calibration"]));
	calib_ = ftl::create<Calibrate>(host_, "calibration", lsrc_);
	if (host_->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_ = {
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
		(unsigned int)lsrc_->width(),
Nicolas Pope's avatar
Nicolas Pope committed
		(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);
	
	disp_ = Disparity::create(host_, "disparity");
    if (!disp_) LOG(FATAL) << "Unknown disparity algorithm : " << *host_->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;
}

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];
Nicolas Pope's avatar
Nicolas Pope committed
			dptr[x] = (float)(homg_pt[2] / homg_pt[3]) / 1000.0f; // Depth in meters
Nicolas Pope's avatar
Nicolas Pope committed

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

bool 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());
	return true;
}

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