Files

119 lines
5.0 KiB
C++

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/utils/filesystem.hpp>
#include <libsgm.h>
#include "sample_common.h"
static const std::string keys =
"{ @left-image-format | <none> | format string for path to input left image }"
"{ @right-image-format | <none> | format string for path to input right image }"
"{ disp_size | 256 | maximum possible disparity value }"
"{ P1 | 10 | penalty on the disparity change by plus or minus 1 }"
"{ P2 | 120 | penalty on the disparity change by more than 1 }"
"{ uniqueness | 0.80 | margin in ratio for best cost function value }"
"{ num_paths | 8 | number of scanlines used in cost aggregation }"
"{ min_disp | -160 | minimum disparity value }"
"{ LR_max_diff | 1 | max allowed difference between L/R disparity }"
"{ census_type | 1 | type of census transform }"
"{ interval | 1 | polling interval in seconds }"
"{ help h | | display this help and exit }";
class ImagePreprocessor {
public:
void preprocess_image_pair(cv::Mat& img_left, cv::Mat& img_right) {
if (img_left.channels() > 1) cv::cvtColor(img_left, img_left, cv::COLOR_BGR2GRAY);
if (img_right.channels() > 1) cv::cvtColor(img_right, img_right, cv::COLOR_BGR2GRAY);
int min_height = std::min(img_left.rows, img_right.rows);
int min_width = std::min(img_left.cols, img_right.cols);
img_left = img_left(cv::Rect(0, 0, min_width, min_height));
img_right = img_right(cv::Rect(0, 0, min_width, min_height));
}
};
bool disparityAlreadyProcessed(int frame_no) {
std::string xml_path = cv::format("output/disparity_%04d.xml", frame_no);
return cv::utils::fs::exists(xml_path);
}
int main(int argc, char* argv[]) {
cv::CommandLineParser parser(argc, argv, keys);
if (parser.has("help")) {
parser.printMessage();
return 0;
}
const std::string format_L = parser.get<cv::String>("@left-image-format");
const std::string format_R = parser.get<cv::String>("@right-image-format");
const int disp_size = parser.get<int>("disp_size");
const int P1 = parser.get<int>("P1");
const int P2 = parser.get<int>("P2");
const float uniqueness = parser.get<float>("uniqueness");
const int num_paths = parser.get<int>("num_paths");
const int min_disp = parser.get<int>("min_disp");
const int LR_max_diff = parser.get<int>("LR_max_diff");
const int interval = parser.get<int>("interval");
const auto census_type = static_cast<sgm::CensusType>(parser.get<int>("census_type"));
if (!parser.check()) {
parser.printErrors();
parser.printMessage();
std::exit(EXIT_FAILURE);
}
if (!cv::utils::fs::exists("output")) {
cv::utils::fs::createDirectory("output");
}
ImagePreprocessor preprocessor;
const sgm::PathType path_type = num_paths == 8 ? sgm::PathType::SCAN_8PATH : sgm::PathType::SCAN_4PATH;
const sgm::StereoSGM::Parameters param(P1, P2, uniqueness, false, path_type, min_disp, LR_max_diff, census_type);
int last_checked = 0;
while (true) {
const std::string left_path = cv::format(format_L.c_str(), last_checked);
const std::string right_path = cv::format(format_R.c_str(), last_checked);
if (cv::utils::fs::exists(left_path) && cv::utils::fs::exists(right_path) && !disparityAlreadyProcessed(last_checked)) {
cv::TickMeter timer;
timer.start();
std::cout << "Processing frame " << last_checked;
cv::Mat I1 = cv::imread(left_path, cv::IMREAD_UNCHANGED);
cv::Mat I2 = cv::imread(right_path, cv::IMREAD_UNCHANGED);
if (I1.empty() || I2.empty()) {
std::cerr << "Error reading images." << std::endl;
break;
}
preprocessor.preprocess_image_pair(I1, I2);
ASSERT_MSG(I1.size() == I2.size() && I1.type() == I2.type(), "Mismatched image size/type.");
ASSERT_MSG(I1.type() == CV_8U || I1.type() == CV_16U, "Images must be CV_8U or CV_16U.");
const int src_depth = I1.type() == CV_8U ? 8 : 16;
const int dst_depth = 16;
sgm::StereoSGM ssgm(I1.cols, I1.rows, disp_size, src_depth, dst_depth, sgm::EXECUTE_INOUT_HOST2HOST, param);
cv::Mat disparity(I1.size(), CV_16S);
ssgm.execute(I1.data, I2.data, disparity.data);
cv::FileStorage fs(cv::format("output/disparity_%04d.xml", last_checked), cv::FileStorage::WRITE);
fs << "disparity" << disparity;
fs.release();
timer.stop();
std::cout << " - " << timer.getTimeSec() << " seconds" << std::endl;
}
last_checked++;
cv::waitKey(interval * 1000); // Sleep for polling interval
}
return 0;
}