diff --git a/CMakeLists.txt b/CMakeLists.txt index 202cce428eddcb057eb2348f9d716c53f9347cf8..212333e0085ef308ca62ba4841dec23d8ee81f1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,12 @@ if (NOT UUID_FOUND) message(ERROR "UUID library is required") endif() +find_program(CPPCHECK_FOUND cppcheck) +if (CPPCHECK_FOUND) + message(STATUS "Found cppcheck: will perform source checks") + set(CMAKE_CXX_CPPCHECK "cppcheck" "--enable=style" "--suppress=*:*catch.hpp" "--suppress=*:*json.hpp") +endif() + include_directories(${PROJECT_SOURCE_DIR}/common/cpp/include) check_language(CUDA) diff --git a/cv-node/src/algorithms/fixstars_sgm.cpp b/cv-node/src/algorithms/fixstars_sgm.cpp index 6300162e2fb691110bf00e5f63a9f55136b72ff0..334f8c20e817322233c64d2e8edee25f326b4281 100644 --- a/cv-node/src/algorithms/fixstars_sgm.cpp +++ b/cv-node/src/algorithms/fixstars_sgm.cpp @@ -1,8 +1,10 @@ +/* Copyright 2019 Nicolas Pope */ + #include <ftl/algorithms/fixstars_sgm.hpp> #include <glog/logging.h> using ftl::algorithms::FixstarsSGM; -using namespace cv; +using cv::Mat; static ftl::Disparity::Register fixstarssgm("libsgm", FixstarsSGM::create); @@ -13,27 +15,25 @@ FixstarsSGM::FixstarsSGM(nlohmann::json &config) : Disparity(config) { void FixstarsSGM::compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp) { Mat left_disp; Mat right_disp; - + Mat lbw, rbw; cv::cvtColor(l, lbw, cv::COLOR_BGR2GRAY); cv::cvtColor(r, rbw, cv::COLOR_BGR2GRAY); - + if (!ssgm_) { - ssgm_ = new sgm::StereoSGM(l.cols, l.rows, max_disp_, 8, 16, sgm::EXECUTE_INOUT_HOST2HOST, + ssgm_ = new sgm::StereoSGM(l.cols, l.rows, max_disp_, 8, 16, + sgm::EXECUTE_INOUT_HOST2HOST, sgm::StereoSGM::Parameters(10,120,0.95f,true)); } - - //disp = Mat(); - - //if (disp.cols != l.cols || disp.rows != l.rows) { - disp = Mat(cv::Size(l.cols, l.rows), CV_16UC1); - //} - + + disp = Mat(cv::Size(l.cols, l.rows), CV_16UC1); + auto start = std::chrono::high_resolution_clock::now(); ssgm_->execute(lbw.data, rbw.data, disp.data); - std::chrono::duration<double> elapsed = std::chrono::high_resolution_clock::now() - start; + std::chrono::duration<double> elapsed = + std::chrono::high_resolution_clock::now() - start; LOG(INFO) << "CUDA sgm in " << elapsed.count() << "s"; - + disp.convertTo(disp, CV_32F, 1.0f/16.0f); } diff --git a/cv-node/src/algorithms/rtcensus.cpp b/cv-node/src/algorithms/rtcensus.cpp index 83937836c6f892b59672fedb1cf42072d426c40b..c0c98eb19c3c0c5ed1b6ef93e1411c1cda3805d5 100644 --- a/cv-node/src/algorithms/rtcensus.cpp +++ b/cv-node/src/algorithms/rtcensus.cpp @@ -1,4 +1,6 @@ /* Created by Nicolas Pope and Sebastian Hahta + * + * Copyright 2019 Nicolas Pope * * Implementation of algorithm presented in article(s): * @@ -14,12 +16,14 @@ #include <ftl/algorithms/rtcensus.hpp> + +#include <cmath> +#include <glog/logging.h> + #include <vector> #include <tuple> #include <bitset> -#include <cmath> #include <chrono> -#include <glog/logging.h> using ftl::algorithms::RTCensus; using std::vector; @@ -34,25 +38,25 @@ using std::bitset; static ftl::Disparity::Register rtcensus("rtcensus", RTCensus::create); /* (8) and (16) */ -#define XHI(P1,P2) ((P1 <= P2) ? 0 : 1) +#define XHI(P1, P2) ((P1 <= P2) ? 0 : 1) /* (14) and (15), based on (9) */ static vector<uint64_t> sparse_census_16x16(const Mat &arr) { vector<uint64_t> result; - result.resize(arr.cols*arr.rows,0); + result.resize(arr.cols*arr.rows, 0); /* Loops adapted to avoid edge out-of-bounds checks */ - for (size_t v=7; v<arr.rows-7; v++) { - for (size_t u=7; u<arr.cols-7; u++) { + for (size_t v=7; v < arr.rows-7; v++) { + for (size_t u=7; u < arr.cols-7; u++) { uint64_t r = 0; /* 16x16 sparse kernel to 8x8 mask (64 bits) */ - for (int n=-7; n<=7; n+=2) { + for (int n=-7; n <= 7; n+=2) { auto u_ = u + n; - for (int m=-7; m<=7; m+=2) { + for (int m=-7; m <= 7; m+=2) { auto v_ = v + m; r <<= 1; - r |= XHI(arr.at<uint8_t>(v,u), arr.at<uint8_t>(v_,u_)); + r |= XHI(arr.at<uint8_t>(v, u), arr.at<uint8_t>(v_, u_)); } } @@ -67,37 +71,38 @@ static vector<uint64_t> sparse_census_16x16(const Mat &arr) { * (19) note: M and N not the same as in (17), see also (8) in [2]. * DSI: Disparity Space Image. LTR/RTL matching can be with sign +1/-1 */ -static void dsi_ca(vector<uint16_t> &result, const vector<uint64_t> &census_R, const vector<uint64_t> &census_L, size_t w, size_t h, size_t d_start, size_t d_stop, int sign=1) { - // TODO Add asserts - assert( census_R.size() == w*h); - assert( census_L.size() == w*h); - assert( d_stop-d_start > 0 ); +static void dsi_ca(vector<uint16_t> &result, const vector<uint64_t> &census_R, + const vector<uint64_t> &census_L, size_t w, size_t h, size_t d_start, + size_t d_stop, int sign = 1) { + // TODO(nick) Add asserts + assert(census_R.size() == w*h); + assert(census_L.size() == w*h); + assert(d_stop-d_start > 0); auto ds = d_stop - d_start; // Number of disparities to check result.resize(census_R.size()*ds, 0); // Change bounds depending upon disparity direction - const size_t eu = (sign>0) ? w-2-ds : w-2; + const size_t eu = (sign > 0) ? w-2-ds : w-2; // Adapt bounds to avoid out-of-bounds checks - for (size_t v=2; v<h-2; v++) { - for (size_t u=(sign>0)?2:ds+2; u<eu; u++) { + for (size_t v=2; v < h-2; v++) { + for (size_t u=(sign > 0) ? 2 : ds+2; u < eu; u++) { const size_t ix = v*w*ds+u*ds; // 5x5 window size - for (int n=-2; n<=2; n++) { + for (int n=-2; n <= 2; n++) { const auto u_ = u + n; - for (int m=-2; m<=2; m++) { + for (int m=-2; m <= 2; m++) { const auto v_ = (v + m)*w; auto r = census_R[u_+v_]; - - for (size_t d=0; d<ds; d++) { + + for (size_t d=0; d < ds; d++) { const auto d_ = d * sign; auto l = census_L[v_+(u_+d_)]; result[ix+d] += bitset<64>(r^l).count(); // Hamming distance } } - } } } @@ -110,7 +115,7 @@ static void dsi_ca(vector<uint16_t> &result, const vector<uint64_t> &census_R, c static size_t arrmin(vector<uint16_t> &a, size_t ix, size_t len) { uint32_t m = UINT32_MAX; size_t mi = 0; - for (size_t i=ix; i<ix+len; i++) { + for (size_t i=ix; i < ix+len; i++) { if (a[i] < m) { m = a[i]; mi = i; @@ -123,39 +128,41 @@ static size_t arrmin(vector<uint16_t> &a, size_t ix, size_t len) { * WTA + subpixel disparity (parabilic fitting) (20) * TODO remove need to pass tuples (see CUDA version) */ -static inline double fit_parabola(tuple<size_t,uint16_t> p, tuple<size_t,uint16_t> pl, tuple<size_t,uint16_t> pr) { +static inline double fit_parabola(tuple<size_t, uint16_t> p, + tuple<size_t, uint16_t> pl, tuple<size_t, uint16_t> pr) { double a = get<1>(pr) - get<1>(pl); double b = 2 * (2 * get<1>(p) - get<1>(pl) - get<1>(pr)); return static_cast<double>(get<0>(p)) + (a / b); } static cv::Mat d_sub(vector<uint16_t> &dsi, size_t w, size_t h, size_t ds) { - Mat result = Mat::zeros(Size(w,h), CV_64FC1); - - assert( dsi.size() == w*h*ds ); + Mat result = Mat::zeros(Size(w, h), CV_64FC1); + + assert(dsi.size() == w*h*ds); - for (size_t v=0; v<h; v++) { + for (size_t v=0; v < h; v++) { const size_t vwds = v * w * ds; - for (size_t u=0; u<w; u++) { + for (size_t u=0; u < w; u++) { const size_t uds = u*ds; auto d_min = arrmin(dsi, vwds+uds, ds); double d_sub; - if (d_min == 0 || d_min == ds-1) d_sub = d_min; - else { - // TODO Remove use of tuples + if (d_min == 0 || d_min == ds-1) { + d_sub = d_min; + } else { + // TODO(nick) Remove use of tuples auto p = make_tuple(d_min, dsi[d_min+vwds+uds]); auto pl = make_tuple(d_min-1, dsi[d_min-1+vwds+uds]); auto pr = make_tuple(d_min+1, dsi[d_min+1+vwds+uds]); - d_sub = fit_parabola(p,pl,pr); + d_sub = fit_parabola(p, pl, pr); } - result.at<double>(v,u) = d_sub; + result.at<double>(v, u) = d_sub; } } - // TODO Parameter pass not return + // TODO(nick) Parameter pass not return return result; } @@ -165,20 +172,23 @@ static cv::Mat d_sub(vector<uint16_t> &dsi, size_t w, size_t h, size_t ds) { static cv::Mat consistency(cv::Mat &d_sub_r, cv::Mat &d_sub_l) { size_t w = d_sub_r.cols; size_t h = d_sub_r.rows; - Mat result = Mat::zeros(Size(w,h), CV_32FC1); - - for (size_t v=0; v<h; v++) { - for (size_t u=0; u<w; u++) { - auto a = (int)(d_sub_l.at<double>(v,u)); + Mat result = Mat::zeros(Size(w, h), CV_32FC1); + + for (size_t v=0; v < h; v++) { + for (size_t u=0; u < w; u++) { + auto a = static_cast<int>(d_sub_l.at<double>(v, u)); if (u-a < 0) continue; - - auto b = d_sub_r.at<double>(v,u-a); - - if (std::abs(a-b) <= 1.0) result.at<float>(v,u) = std::abs((a+b)/2); - else result.at<float>(v,u) = 0.0f; + + auto b = d_sub_r.at<double>(v, u-a); + + if (std::abs(a-b) <= 1.0) { + result.at<float>(v, u) = std::abs((a+b)/2); + } else { + result.at<float>(v, u) = 0.0f; + } } } - + return result; } @@ -186,7 +196,7 @@ RTCensus::RTCensus(nlohmann::json &config) : Disparity(config), gamma_(0.0f), tau_(0.0f), - use_cuda_(config.value("use_cuda",true)), + use_cuda_(config.value("use_cuda", true)), alternate_(false) {} /* @@ -195,33 +205,34 @@ RTCensus::RTCensus(nlohmann::json &config) void RTCensus::compute(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp) { #if defined HAVE_CUDA if (use_cuda_) { - computeCUDA(l,r,disp); + computeCUDA(l, r, disp); } else { - computeCPU(l,r,disp); + computeCPU(l, r, disp); } - #else // !HAVE_CUDA - computeCPU(l,r,disp); + #else // !HAVE_CUDA + computeCPU(l, r, disp); #endif } void RTCensus::computeCPU(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp) { size_t d_min = min_disp_; size_t d_max = max_disp_; - + Mat lbw, rbw; - cv::cvtColor(l, lbw, cv::COLOR_BGR2GRAY); + cv::cvtColor(l, lbw, cv::COLOR_BGR2GRAY); cv::cvtColor(r, rbw, cv::COLOR_BGR2GRAY); auto start = std::chrono::high_resolution_clock::now(); auto census_R = sparse_census_16x16(rbw); auto census_L = sparse_census_16x16(lbw); - std::chrono::duration<double> elapsed = std::chrono::high_resolution_clock::now() - start; + std::chrono::duration<double> elapsed = + std::chrono::high_resolution_clock::now() - start; LOG(INFO) << "Census in " << elapsed.count() << "s"; start = std::chrono::high_resolution_clock::now(); - vector<uint16_t> dsi_ca_R,dsi_ca_L; - dsi_ca(dsi_ca_R,census_R, census_L, l.cols, l.rows, d_min, d_max); - dsi_ca(dsi_ca_L,census_L, census_R, l.cols, l.rows, d_min, d_max, -1); + vector<uint16_t> dsi_ca_R, dsi_ca_L; + dsi_ca(dsi_ca_R, census_R, census_L, l.cols, l.rows, d_min, d_max); + dsi_ca(dsi_ca_L, census_L, census_R, l.cols, l.rows, d_min, d_max, -1); elapsed = std::chrono::high_resolution_clock::now() - start; LOG(INFO) << "DSI in " << elapsed.count() << "s"; @@ -231,48 +242,53 @@ void RTCensus::computeCPU(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp) { disp = consistency(disp_R, disp_L); - // TODO confidence and texture filtering + // TODO(nick) confidence and texture filtering } #if defined HAVE_CUDA -using namespace cv::cuda; -using namespace cv; +using cv::cuda::PtrStepSz; +using cv::cuda::GpuMat; #include <vector_types.h> namespace ftl { namespace gpu { -void rtcensus_call(const PtrStepSz<uchar4> &l, const PtrStepSz<uchar4> &r, const PtrStepSz<float> &disp, size_t num_disp, const int &s=0); +void rtcensus_call(const PtrStepSz<uchar4> &l, const PtrStepSz<uchar4> &r, + const PtrStepSz<float> &disp, size_t num_disp, const int &s = 0); }} void RTCensus::computeCUDA(const cv::Mat &l, const cv::Mat &r, cv::Mat &disp) { // Initialise gpu memory here because we need image size - if (disp_.empty()) disp_ = cuda::GpuMat(l.size(), CV_32FC1); - if (left_.empty()) left_ = cuda::GpuMat(l.size(), CV_8UC4); - if (left2_.empty()) left2_ = cuda::GpuMat(l.size(), CV_8UC4); - if (right_.empty()) right_ = cuda::GpuMat(l.size(), CV_8UC4); - + if (disp_.empty()) disp_ = GpuMat(l.size(), CV_32FC1); + if (left_.empty()) left_ = GpuMat(l.size(), CV_8UC4); + if (left2_.empty()) left2_ = GpuMat(l.size(), CV_8UC4); + if (right_.empty()) right_ = GpuMat(l.size(), CV_8UC4); + Mat lhsv, rhsv; - cv::cvtColor(l, lhsv, COLOR_BGR2HSV); - cv::cvtColor(r, rhsv, COLOR_BGR2HSV); - int from_to[] = {0,0,1,1,2,2,-1,3}; + cv::cvtColor(l, lhsv, cv::COLOR_BGR2HSV); + cv::cvtColor(r, rhsv, cv::COLOR_BGR2HSV); + int from_to[] = {0, 0, 1, 1, 2, 2, -1, 3}; Mat hsval(lhsv.size(), CV_8UC4); Mat hsvar(rhsv.size(), CV_8UC4); mixChannels(&lhsv, 1, &hsval, 1, from_to, 4); mixChannels(&rhsv, 1, &hsvar, 1, from_to, 4); - + // Send images to GPU - if (alternate_) left_.upload(hsval); - else left2_.upload(hsval); + if (alternate_) { + left_.upload(hsval); + } else { + left2_.upload(hsval); + } right_.upload(hsvar); auto start = std::chrono::high_resolution_clock::now(); ftl::gpu::rtcensus_call((alternate_)?left_:left2_, right_, disp_, max_disp_); - std::chrono::duration<double> elapsed = std::chrono::high_resolution_clock::now() - start; + std::chrono::duration<double> elapsed = + std::chrono::high_resolution_clock::now() - start; LOG(INFO) << "CUDA census in " << elapsed.count() << "s"; - + alternate_ = !alternate_; - + // Read disparity from GPU disp_.download(disp); } diff --git a/cv-node/src/calibrate.cpp b/cv-node/src/calibrate.cpp index 269cf2c1ae84ae19459a9ebf86aa3ccb109d7839..46dadb8ab33f574fd1ce7df941f5293ea1270378 100644 --- a/cv-node/src/calibrate.cpp +++ b/cv-node/src/calibrate.cpp @@ -1,3 +1,10 @@ +/* + * Copyright 2019 Nicolas Pope + */ + +#include <glog/logging.h> +#include <ftl/config.h> + #include <iostream> #include <sstream> #include <string> @@ -5,7 +12,6 @@ #include <cstdio> #include <ftl/calibrate.hpp> -#include <ftl/config.h> #include <opencv2/core.hpp> #include <opencv2/core/utility.hpp> @@ -15,56 +21,69 @@ #include <opencv2/videoio.hpp> #include <opencv2/highgui.hpp> -#include <glog/logging.h> - -using namespace cv; -using namespace std; - using ftl::Calibrate; - - -void Calibrate::Settings::write(FileStorage& fs) const //Write serialization for this class -{ +using cv::FileStorage; +using cv::CALIB_FIX_PRINCIPAL_POINT; +using cv::CALIB_ZERO_TANGENT_DIST; +using cv::CALIB_FIX_ASPECT_RATIO; +using cv::CALIB_FIX_K1; +using cv::CALIB_FIX_K2; +using cv::CALIB_FIX_K3; +using cv::CALIB_FIX_K4; +using cv::CALIB_FIX_K5; +using cv::CALIB_ZERO_DISPARITY; +using cv::CALIB_USE_INTRINSIC_GUESS; +using cv::CALIB_SAME_FOCAL_LENGTH; +using cv::CALIB_RATIONAL_MODEL; +using cv::CALIB_CB_ADAPTIVE_THRESH; +using cv::CALIB_CB_NORMALIZE_IMAGE; +using cv::CALIB_CB_FAST_CHECK; +using cv::CALIB_USE_LU; +using cv::NORM_L2; +using cv::INTER_LINEAR; +using cv::COLOR_BGR2GRAY; +using cv::FileNode; +using cv::FileNodeIterator; +using cv::Mat; +using cv::Size; +using cv::Point2f; +using cv::Point3f; +using cv::Matx33d; +using cv::Scalar; +using cv::Rect; +using cv::TermCriteria; +using cv::waitKey; +using std::string; +using std::vector; + +void Calibrate::Settings::write(FileStorage& fs) const { fs << "{" - << "BoardSize_Width" << boardSize.width - << "BoardSize_Height" << boardSize.height - << "Square_Size" << squareSize - << "Calibrate_Pattern" << patternToUse - << "Calibrate_NrOfFrameToUse" << nrFrames - << "Calibrate_FixAspectRatio" << aspectRatio - << "Calibrate_AssumeZeroTangentialDistortion" << calibZeroTangentDist - << "Calibrate_FixPrincipalPointAtTheCenter" << calibFixPrincipalPoint - - << "Write_DetectedFeaturePoints" << writePoints - << "Write_extrinsicParameters" << writeExtrinsics - << "Write_gridPoints" << writeGrid - //<< "Write_outputFileName" << outputFileName - - //<< "Show_UndistortedImage" << showUndistorsed - - << "Input_FlipAroundHorizontalAxis" << flipVertical - << "Input_Delay" << delay - //<< "Input" << input - << "}"; + << "BoardSize_Width" << boardSize.width + << "BoardSize_Height" << boardSize.height + << "Square_Size" << squareSize + << "Calibrate_Pattern" << patternToUse + << "Calibrate_NrOfFrameToUse" << nrFrames + << "Calibrate_FixAspectRatio" << aspectRatio + << "Calibrate_AssumeZeroTangentialDistortion" << calibZeroTangentDist + << "Calibrate_FixPrincipalPointAtTheCenter" << calibFixPrincipalPoint + << "Write_DetectedFeaturePoints" << writePoints + << "Write_extrinsicParameters" << writeExtrinsics + << "Write_gridPoints" << writeGrid + << "Input_FlipAroundHorizontalAxis" << flipVertical + << "Input_Delay" << delay + << "}"; } -void Calibrate::Settings::read(const nlohmann::json& node) //Read serialization for this class -{ + +void Calibrate::Settings::read(const nlohmann::json& node) { boardSize.width = node["board_size"][0]; boardSize.height = node["board_size"][1]; - //node["Calibrate_Pattern"] >> patternToUse; squareSize = node["square_size"]; nrFrames = node["num_frames"]; aspectRatio = node["fix_aspect_ratio"]; - //node["Write_DetectedFeaturePoints"] >> writePoints; - //node["Write_extrinsicParameters"] >> writeExtrinsics; - //node["Write_gridPoints"] >> writeGrid; - //node["Write_outputFileName"] >> outputFileName; calibZeroTangentDist = node["assume_zero_tangential_distortion"]; calibFixPrincipalPoint = node["fix_principal_point_at_center"]; useFisheye = node["use_fisheye_model"]; flipVertical = node["flip_vertical"]; - //node["Show_UndistortedImage"] >> showUndistorsed; - //node["Input"] >> input; delay = node["frame_delay"]; fixK1 = node["fix_k1"]; fixK2 = node["fix_k2"]; @@ -74,59 +93,51 @@ void Calibrate::Settings::read(const nlohmann::json& node) validate(); } -void Calibrate::Settings::validate() -{ + +void Calibrate::Settings::validate() { goodInput = true; - if (boardSize.width <= 0 || boardSize.height <= 0) - { - LOG(ERROR) << "Invalid Board size: " << boardSize.width << " " << boardSize.height; + if (boardSize.width <= 0 || boardSize.height <= 0) { + LOG(ERROR) << "Invalid Board size: " << boardSize.width << " " << + boardSize.height; goodInput = false; } - if (squareSize <= 10e-6) - { + + if (squareSize <= 10e-6) { LOG(ERROR) << "Invalid square size " << squareSize; goodInput = false; } - if (nrFrames <= 0) - { + + if (nrFrames <= 0) { LOG(ERROR) << "Invalid number of frames " << nrFrames; goodInput = false; } flag = 0; - if(calibFixPrincipalPoint) flag |= CALIB_FIX_PRINCIPAL_POINT; - if(calibZeroTangentDist) flag |= CALIB_ZERO_TANGENT_DIST; - if(aspectRatio) flag |= CALIB_FIX_ASPECT_RATIO; - if(fixK1) flag |= CALIB_FIX_K1; - if(fixK2) flag |= CALIB_FIX_K2; - if(fixK3) flag |= CALIB_FIX_K3; - if(fixK4) flag |= CALIB_FIX_K4; - if(fixK5) flag |= CALIB_FIX_K5; + if (calibFixPrincipalPoint) flag |= CALIB_FIX_PRINCIPAL_POINT; + if (calibZeroTangentDist) flag |= CALIB_ZERO_TANGENT_DIST; + if (aspectRatio) flag |= CALIB_FIX_ASPECT_RATIO; + if (fixK1) flag |= CALIB_FIX_K1; + if (fixK2) flag |= CALIB_FIX_K2; + if (fixK3) flag |= CALIB_FIX_K3; + if (fixK4) flag |= CALIB_FIX_K4; + if (fixK5) flag |= CALIB_FIX_K5; if (useFisheye) { // the fisheye model has its own enum, so overwrite the flags - flag = fisheye::CALIB_FIX_SKEW | fisheye::CALIB_RECOMPUTE_EXTRINSIC; - if(fixK1) flag |= fisheye::CALIB_FIX_K1; - if(fixK2) flag |= fisheye::CALIB_FIX_K2; - if(fixK3) flag |= fisheye::CALIB_FIX_K3; - if(fixK4) flag |= fisheye::CALIB_FIX_K4; - if (calibFixPrincipalPoint) flag |= fisheye::CALIB_FIX_PRINCIPAL_POINT; + flag = cv::fisheye::CALIB_FIX_SKEW | + cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC; + if (fixK1) flag |= cv::fisheye::CALIB_FIX_K1; + if (fixK2) flag |= cv::fisheye::CALIB_FIX_K2; + if (fixK3) flag |= cv::fisheye::CALIB_FIX_K3; + if (fixK4) flag |= cv::fisheye::CALIB_FIX_K4; + if (calibFixPrincipalPoint) + flag |= cv::fisheye::CALIB_FIX_PRINCIPAL_POINT; } - /*calibrationPattern = NOT_EXISTING; - if (!patternToUse.compare("CHESSBOARD")) calibrationPattern = CHESSBOARD; - if (!patternToUse.compare("CIRCLES_GRID")) calibrationPattern = CIRCLES_GRID; - if (!patternToUse.compare("ASYMMETRIC_CIRCLES_GRID")) calibrationPattern = ASYMMETRIC_CIRCLES_GRID; - if (calibrationPattern == NOT_EXISTING) - { - LOG(ERROR) << " Camera calibration mode does not exist: " << patternToUse; - goodInput = false; - }*/ atImageList = 0; - } -Mat Calibrate::_nextImage(size_t cam) -{ + +Mat Calibrate::_nextImage(size_t cam) { Mat result; if (cam == 0) { local_->left(result); @@ -136,26 +147,26 @@ Mat Calibrate::_nextImage(size_t cam) return result; } -bool Calibrate::Settings::readStringList( const string& filename, vector<string>& l ) -{ +bool Calibrate::Settings::readStringList(const string& filename, + vector<string>& l) { l.clear(); FileStorage fs(filename, FileStorage::READ); - if( !fs.isOpened() ) + if ( !fs.isOpened() ) return false; FileNode n = fs.getFirstTopLevelNode(); - if( n.type() != FileNode::SEQ ) + if ( n.type() != FileNode::SEQ ) return false; FileNodeIterator it = n.begin(), it_end = n.end(); - for( ; it != it_end; ++it ) + for ( ; it != it_end; ++it ) l.push_back((string)*it); return true; } -bool Calibrate::Settings::isListOfImages( const string& filename) -{ +bool Calibrate::Settings::isListOfImages(const string& filename) { string s(filename); // Look for file extension - if( s.find(".xml") == string::npos && s.find(".yaml") == string::npos && s.find(".yml") == string::npos ) + if ( s.find(".xml") == string::npos && s.find(".yaml") == string::npos && + s.find(".yml") == string::npos ) return false; else return true; @@ -163,8 +174,10 @@ bool Calibrate::Settings::isListOfImages( const string& filename) enum { DETECTION = 0, CAPTURING = 1, CALIBRATED = 2 }; -bool runCalibration(Calibrate::Settings& s, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, - vector<vector<Point2f> > imagePoints, float grid_width, bool release_object); +bool runCalibration(const Calibrate::Settings& s, Size imageSize, + Mat& cameraMatrix, Mat& distCoeffs, + vector<vector<Point2f> > imagePoints, float grid_width, + bool release_object); Calibrate::Calibrate(ftl::LocalSource *s, nlohmann::json &config) : local_(s) { @@ -174,23 +187,20 @@ Calibrate::Calibrate(ftl::LocalSource *s, nlohmann::json &config) : local_(s) { LOG(ERROR) << "Could not open the configuration file: \"" << cal << "\""; return; }*/ - //fs["Settings"] >> settings_; + // fs["Settings"] >> settings_; settings_.read(config); - //fs.release(); - - if (!settings_.goodInput) - { + // fs.release(); + + if (!settings_.goodInput) { LOG(ERROR) << "Invalid input detected. Application stopping."; return; } - + map1_.resize(2); map2_.resize(2); - - // TODO Load existing calibration if available... - + calibrated_ = _loadCalibration(); - + if (calibrated_) { LOG(INFO) << "Calibration loaded from file"; } @@ -198,17 +208,16 @@ Calibrate::Calibrate(ftl::LocalSource *s, nlohmann::json &config) : local_(s) { bool Calibrate::_loadCalibration() { // Capture one frame to get size; - Mat l,r; - local_->get(l,r); + Mat l, r; + local_->get(l, r); Size img_size = l.size(); float scale = 1.0f; Rect roi1, roi2; - + // reading intrinsic parameters FileStorage fs(FTL_LOCAL_CONFIG_ROOT "/intrinsics.yml", FileStorage::READ); - if(!fs.isOpened()) - { + if (!fs.isOpened()) { LOG(WARNING) << "Calibration file not found"; return false; } @@ -223,8 +232,7 @@ bool Calibrate::_loadCalibration() { M2 *= scale; fs.open(FTL_LOCAL_CONFIG_ROOT "/extrinsics.yml", FileStorage::READ); - if(!fs.isOpened()) - { + if (!fs.isOpened()) { LOG(WARNING) << "Calibration file not found"; return false; } @@ -238,66 +246,65 @@ bool Calibrate::_loadCalibration() { fs["P2"] >> P2; fs["Q"] >> Q_; - stereoRectify( M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q_, CALIB_ZERO_DISPARITY, -1, img_size, &roi1, &roi2 ); + stereoRectify(M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q_, + CALIB_ZERO_DISPARITY, -1, img_size, &roi1, &roi2); Mat map11, map12, map21, map22; - initUndistortRectifyMap(M1, D1, R1, P1, img_size, CV_16SC2, map1_[0], map2_[0]); - initUndistortRectifyMap(M2, D2, R2, P2, img_size, CV_16SC2, map1_[1], map2_[1]); + initUndistortRectifyMap(M1, D1, R1, P1, img_size, CV_16SC2, + map1_[0], map2_[0]); + initUndistortRectifyMap(M2, D2, R2, P2, img_size, CV_16SC2, + map1_[1], map2_[1]); return true; } bool Calibrate::recalibrate() { - vector<vector<Point2f> > imagePoints[2]; + vector<vector<Point2f>> imagePoints[2]; Mat cameraMatrix[2], distCoeffs[2]; Size imageSize[2]; - - // TODO Ensure both left+right use same frames - + bool r = _recalibrate(imagePoints, cameraMatrix, distCoeffs, imageSize); - //if (local_->isStereo()) r &= _recalibrate(1, imagePoints[1], cameraMatrix[1], distCoeffs[1], imageSize[1]); - + if (r) calibrated_ = true; - + if (r && local_->isStereo()) { int nimages = static_cast<int>(imagePoints[0].size()); auto squareSize = settings_.squareSize; vector<vector<Point3f>> objectPoints; objectPoints.resize(nimages); - for(auto i = 0; i < nimages; i++ ) - { - for(auto j = 0; j < settings_.boardSize.height; j++ ) - for(auto k = 0; k < settings_.boardSize.width; k++ ) - objectPoints[i].push_back(Point3f(k*squareSize, j*squareSize, 0)); + for (auto i = 0; i < nimages; i++) { + for (auto j = 0; j < settings_.boardSize.height; j++) + for (auto k = 0; k < settings_.boardSize.width; k++) + objectPoints[i].push_back(Point3f(k*squareSize, + j*squareSize, 0)); } - + Mat R, T, E, F; - + LOG(INFO) << "Running stereo calibration..."; - + double rms = stereoCalibrate(objectPoints, imagePoints[0], imagePoints[1], - cameraMatrix[0], distCoeffs[0], - cameraMatrix[1], distCoeffs[1], - imageSize[0], R, T, E, F, - CALIB_FIX_ASPECT_RATIO + - CALIB_ZERO_TANGENT_DIST + - CALIB_USE_INTRINSIC_GUESS + - CALIB_SAME_FOCAL_LENGTH + - CALIB_RATIONAL_MODEL + - CALIB_FIX_K3 + CALIB_FIX_K4 + CALIB_FIX_K5, - TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 100, 1e-5) ); + cameraMatrix[0], distCoeffs[0], + cameraMatrix[1], distCoeffs[1], + imageSize[0], R, T, E, F, + CALIB_FIX_ASPECT_RATIO + + CALIB_ZERO_TANGENT_DIST + + CALIB_USE_INTRINSIC_GUESS + + CALIB_SAME_FOCAL_LENGTH + + CALIB_RATIONAL_MODEL + + CALIB_FIX_K3 + CALIB_FIX_K4 + CALIB_FIX_K5, + TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 100, 1e-5)); LOG(INFO) << "... done with RMS error=" << rms; - + // save intrinsic parameters FileStorage fs(FTL_LOCAL_CONFIG_ROOT "/intrinsics.yml", FileStorage::WRITE); - if( fs.isOpened() ) - { + if (fs.isOpened()) { fs << "M1" << cameraMatrix[0] << "D1" << distCoeffs[0] << "M2" << cameraMatrix[1] << "D2" << distCoeffs[1]; fs.release(); - } - else + } else { LOG(ERROR) << "Error: can not save the intrinsic parameters"; + } Mat R1, R2, P1, P2; Rect validRoi[2]; @@ -305,89 +312,87 @@ bool Calibrate::recalibrate() { stereoRectify(cameraMatrix[0], distCoeffs[0], cameraMatrix[1], distCoeffs[1], imageSize[0], R, T, R1, R2, P1, P2, Q_, - CALIB_ZERO_DISPARITY, 1, imageSize[0], &validRoi[0], &validRoi[1]); + CALIB_ZERO_DISPARITY, 1, imageSize[0], + &validRoi[0], &validRoi[1]); fs.open(FTL_LOCAL_CONFIG_ROOT "/extrinsics.yml", FileStorage::WRITE); - if( fs.isOpened() ) - { - fs << "R" << R << "T" << T << "R1" << R1 << "R2" << R2 << "P1" << P1 << "P2" << P2 << "Q" << Q_; + if (fs.isOpened()) { + fs << "R" << R << "T" << T << "R1" << R1 << "R2" << R2 << "P1" << + P1 << "P2" << P2 << "Q" << Q_; fs.release(); - } - else + } else { LOG(ERROR) << "Error: can not save the extrinsic parameters"; - - - //Precompute maps for cv::remap() - initUndistortRectifyMap(cameraMatrix[0], distCoeffs[0], R1, P1, imageSize[0], CV_16SC2, map1_[0], map2_[0]); - initUndistortRectifyMap(cameraMatrix[1], distCoeffs[1], R2, P2, imageSize[0], CV_16SC2, map1_[1], map2_[1]); + } + + // Precompute maps for cv::remap() + initUndistortRectifyMap(cameraMatrix[0], distCoeffs[0], R1, P1, + imageSize[0], CV_16SC2, map1_[0], map2_[0]); + initUndistortRectifyMap(cameraMatrix[1], distCoeffs[1], R2, P2, + imageSize[0], CV_16SC2, map1_[1], map2_[1]); } else { int cam = 0; - if (settings_.useFisheye) - { + if (settings_.useFisheye) { Mat newCamMat; - fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix[cam], distCoeffs[cam], imageSize[cam], - Matx33d::eye(), newCamMat, 1); - fisheye::initUndistortRectifyMap(cameraMatrix[cam], distCoeffs[cam], Matx33d::eye(), newCamMat, imageSize[cam], - CV_16SC2, map1_[cam], map2_[cam]); - } - else - { + cv::fisheye::estimateNewCameraMatrixForUndistortRectify( + cameraMatrix[cam], distCoeffs[cam], imageSize[cam], + Matx33d::eye(), newCamMat, 1); + cv::fisheye::initUndistortRectifyMap( + cameraMatrix[cam], distCoeffs[cam], Matx33d::eye(), + newCamMat, imageSize[cam], + CV_16SC2, map1_[cam], map2_[cam]); + } else { initUndistortRectifyMap( cameraMatrix[cam], distCoeffs[cam], Mat(), - getOptimalNewCameraMatrix(cameraMatrix[cam], distCoeffs[cam], imageSize[cam], 1, imageSize[cam], 0), imageSize[cam], - CV_16SC2, map1_[cam], map2_[cam]); + getOptimalNewCameraMatrix(cameraMatrix[cam], distCoeffs[cam], + imageSize[cam], 1, imageSize[cam], 0), + imageSize[cam], CV_16SC2, map1_[cam], map2_[cam]); } } - + return r; } bool Calibrate::_recalibrate(vector<vector<Point2f>> *imagePoints, Mat *cameraMatrix, Mat *distCoeffs, Size *imageSize) { - int winSize = 11; //parser.get<int>("winSize"); + int winSize = 11; // parser.get<int>("winSize"); float grid_width = settings_.squareSize * (settings_.boardSize.width - 1); bool release_object = false; - //vector<vector<Point2f> > imagePoints; - //Mat cameraMatrix, distCoeffs; - //Size imageSize; + // vector<vector<Point2f> > imagePoints; + // Mat cameraMatrix, distCoeffs; + // Size imageSize; int mode = CAPTURING; double prevTimestamp = 0.0; - const Scalar RED(0,0,255), GREEN(0,255,0); - + const Scalar RED(0, 0, 255), GREEN(0, 255, 0); + int chessBoardFlags = CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE; - if(!settings_.useFisheye) { + if (!settings_.useFisheye) { // fast check erroneously fails with high distortions like fisheye chessBoardFlags |= CALIB_CB_FAST_CHECK; } - - //! [get_input] - for(;;) - { - Mat view[2]; - //bool blinkOutput = false; - local_->get(view[0],view[1]); - - //view = _nextImage(cam); + for (;;) { + Mat view[2]; + local_->get(view[0], view[1]); LOG(INFO) << "Grabbing calibration image..."; - - if (view[0].empty() || (local_->isStereo() && view[1].empty()) || imagePoints[0].size() >= (size_t)settings_.nrFrames) { + + if (view[0].empty() || (local_->isStereo() && view[1].empty()) || + imagePoints[0].size() >= (size_t)settings_.nrFrames) { settings_.outputFileName = FTL_LOCAL_CONFIG_ROOT "/cam0.xml"; bool r = runCalibration(settings_, imageSize[0], cameraMatrix[0], distCoeffs[0], imagePoints[0], grid_width, release_object); - + if (local_->isStereo()) { settings_.outputFileName = FTL_LOCAL_CONFIG_ROOT "/cam1.xml"; r &= runCalibration(settings_, imageSize[1], cameraMatrix[1], distCoeffs[1], imagePoints[1], grid_width, release_object); } - + if (!r && view[0].empty()) { LOG(ERROR) << "Not enough frames to calibrate"; return false; @@ -395,59 +400,60 @@ bool Calibrate::_recalibrate(vector<vector<Point2f>> *imagePoints, LOG(INFO) << "Calibration successful"; break; } - } imageSize[0] = view[0].size(); // Format input image. imageSize[1] = view[1].size(); - //if( settings_.flipVertical ) flip( view[cam], view[cam], 0 ); + // if( settings_.flipVertical ) flip( view[cam], view[cam], 0 ); - //! [find_pattern] vector<Point2f> pointBuf[2]; - - bool found1,found2; - - found1 = findChessboardCorners( view[0], settings_.boardSize, pointBuf[0], chessBoardFlags); - found2 = !local_->isStereo() || findChessboardCorners( view[1], settings_.boardSize, pointBuf[1], chessBoardFlags); - - if (found1 && found2 && local_->getTimestamp()-prevTimestamp > settings_.delay) // If done with success, - { + bool found1, found2; + found1 = findChessboardCorners(view[0], settings_.boardSize, + pointBuf[0], chessBoardFlags); + found2 = !local_->isStereo() || findChessboardCorners(view[1], + settings_.boardSize, pointBuf[1], chessBoardFlags); + + if (found1 && found2 && + local_->getTimestamp()-prevTimestamp > settings_.delay) { prevTimestamp = local_->getTimestamp(); - // improve the found corners' coordinate accuracy for chessboard - Mat viewGray; - cvtColor(view[0], viewGray, COLOR_BGR2GRAY); - cornerSubPix( viewGray, pointBuf[0], Size(winSize,winSize), - Size(-1,-1), TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 30, 0.0001 )); + // improve the found corners' coordinate accuracy for chessboard + Mat viewGray; + cvtColor(view[0], viewGray, COLOR_BGR2GRAY); + cornerSubPix(viewGray, pointBuf[0], Size(winSize, winSize), + Size(-1, -1), TermCriteria( + TermCriteria::EPS+TermCriteria::COUNT, 30, 0.0001)); imagePoints[0].push_back(pointBuf[0]); - - if (local_->isStereo()) { + + if (local_->isStereo()) { cvtColor(view[1], viewGray, COLOR_BGR2GRAY); - cornerSubPix( viewGray, pointBuf[1], Size(winSize,winSize), - Size(-1,-1), TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 30, 0.0001 )); + cornerSubPix(viewGray, pointBuf[1], Size(winSize, winSize), + Size(-1, -1), TermCriteria( + TermCriteria::EPS+TermCriteria::COUNT, 30, 0.0001)); imagePoints[1].push_back(pointBuf[1]); } - // Draw the corners. - drawChessboardCorners( view[0], settings_.boardSize, Mat(pointBuf[0]), found1 ); - if (local_->isStereo()) drawChessboardCorners( view[1], settings_.boardSize, Mat(pointBuf[1]), found2 ); + drawChessboardCorners(view[0], settings_.boardSize, + Mat(pointBuf[0]), found1); + if (local_->isStereo()) drawChessboardCorners(view[1], + settings_.boardSize, Mat(pointBuf[1]), found2); } else { LOG(WARNING) << "No calibration pattern found"; } imshow("Left", view[0]); if (local_->isStereo()) imshow("Right", view[1]); - char key = (char)waitKey(50); + char key = static_cast<char>(waitKey(50)); - if( key == 27 ) + if (key == 27) break; } - + return true; } bool Calibrate::undistort(cv::Mat &l, cv::Mat &r) { - local_->get(l,r); + local_->get(l, r); if (!calibrated_) return false; if (l.empty()) return false; remap(l, l, map1_[0], map2_[0], INTER_LINEAR); @@ -456,7 +462,7 @@ bool Calibrate::undistort(cv::Mat &l, cv::Mat &r) { } bool Calibrate::rectified(cv::Mat &l, cv::Mat &r) { - return undistort(l,r); + return undistort(l, r); } bool Calibrate::isCalibrated() { @@ -464,32 +470,29 @@ bool Calibrate::isCalibrated() { } //! [compute_errors] -static double computeReprojectionErrors( const vector<vector<Point3f> >& objectPoints, - const vector<vector<Point2f> >& imagePoints, - const vector<Mat>& rvecs, const vector<Mat>& tvecs, - const Mat& cameraMatrix , const Mat& distCoeffs, - vector<float>& perViewErrors, bool fisheye) -{ +static double computeReprojectionErrors( + const vector<vector<Point3f> >& objectPoints, + const vector<vector<Point2f> >& imagePoints, + const vector<Mat>& rvecs, const vector<Mat>& tvecs, + const Mat& cameraMatrix , const Mat& distCoeffs, + vector<float>& perViewErrors, bool fisheye) { vector<Point2f> imagePoints2; size_t totalPoints = 0; double totalErr = 0, err; perViewErrors.resize(objectPoints.size()); - for(size_t i = 0; i < objectPoints.size(); ++i ) - { - if (fisheye) - { - fisheye::projectPoints(objectPoints[i], imagePoints2, rvecs[i], tvecs[i], cameraMatrix, - distCoeffs); - } - else - { - projectPoints(objectPoints[i], rvecs[i], tvecs[i], cameraMatrix, distCoeffs, imagePoints2); + for (size_t i = 0; i < objectPoints.size(); ++i) { + if (fisheye) { + cv::fisheye::projectPoints(objectPoints[i], imagePoints2, rvecs[i], + tvecs[i], cameraMatrix, distCoeffs); + } else { + projectPoints(objectPoints[i], rvecs[i], tvecs[i], cameraMatrix, + distCoeffs, imagePoints2); } err = norm(imagePoints[i], imagePoints2, NORM_L2); size_t n = objectPoints[i].size(); - perViewErrors[i] = (float) std::sqrt(err*err/n); + perViewErrors[i] = static_cast<float>(std::sqrt(err*err/n)); totalErr += err*err; totalPoints += n; } @@ -498,40 +501,38 @@ static double computeReprojectionErrors( const vector<vector<Point3f> >& objectP } //! [compute_errors] //! [board_corners] -static void calcBoardCornerPositions(Size boardSize, float squareSize, vector<Point3f>& corners, - Calibrate::Settings::Pattern patternType /*= Settings::CHESSBOARD*/) -{ +static void calcBoardCornerPositions(Size boardSize, float squareSize, + vector<Point3f>& corners, Calibrate::Settings::Pattern patternType) { corners.clear(); - switch(patternType) - { + switch (patternType) { case Calibrate::Settings::CHESSBOARD: case Calibrate::Settings::CIRCLES_GRID: - for( int i = 0; i < boardSize.height; ++i ) - for( int j = 0; j < boardSize.width; ++j ) + for (int i = 0; i < boardSize.height; ++i) + for (int j = 0; j < boardSize.width; ++j) corners.push_back(Point3f(j*squareSize, i*squareSize, 0)); break; case Calibrate::Settings::ASYMMETRIC_CIRCLES_GRID: - for( int i = 0; i < boardSize.height; i++ ) - for( int j = 0; j < boardSize.width; j++ ) - corners.push_back(Point3f((2*j + i % 2)*squareSize, i*squareSize, 0)); + for (int i = 0; i < boardSize.height; i++) + for (int j = 0; j < boardSize.width; j++) + corners.push_back(Point3f((2*j + i % 2)*squareSize, + i*squareSize, 0)); break; default: break; } } //! [board_corners] -static bool _runCalibration( Calibrate::Settings& s, Size& imageSize, Mat& cameraMatrix, Mat& distCoeffs, - vector<vector<Point2f> > imagePoints, vector<Mat>& rvecs, vector<Mat>& tvecs, - vector<float>& reprojErrs, double& totalAvgErr, vector<Point3f>& newObjPoints, - float grid_width, bool release_object) -{ - //! [fixed_aspect] +static bool _runCalibration(const Calibrate::Settings& s, Size& imageSize, + Mat& cameraMatrix, Mat& distCoeffs, + vector<vector<Point2f> > imagePoints, vector<Mat>& rvecs, + vector<Mat>& tvecs, vector<float>& reprojErrs, double& totalAvgErr, + vector<Point3f>& newObjPoints, float grid_width, bool release_object) { cameraMatrix = Mat::eye(3, 3, CV_64F); - if( s.flag & CALIB_FIX_ASPECT_RATIO ) - cameraMatrix.at<double>(0,0) = s.aspectRatio; - //! [fixed_aspect] + if (s.flag & CALIB_FIX_ASPECT_RATIO) + cameraMatrix.at<double>(0, 0) = s.aspectRatio; + if (s.useFisheye) { distCoeffs = Mat::zeros(4, 1, CV_64F); } else { @@ -539,23 +540,25 @@ static bool _runCalibration( Calibrate::Settings& s, Size& imageSize, Mat& camer } vector<vector<Point3f> > objectPoints(1); - calcBoardCornerPositions(s.boardSize, s.squareSize, objectPoints[0], Calibrate::Settings::CHESSBOARD); - objectPoints[0][s.boardSize.width - 1].x = objectPoints[0][0].x + grid_width; + calcBoardCornerPositions(s.boardSize, s.squareSize, objectPoints[0], + Calibrate::Settings::CHESSBOARD); + objectPoints[0][s.boardSize.width - 1].x = objectPoints[0][0].x + + grid_width; newObjPoints = objectPoints[0]; - objectPoints.resize(imagePoints.size(),objectPoints[0]); + objectPoints.resize(imagePoints.size(), objectPoints[0]); - //Find intrinsic and extrinsic camera parameters + // Find intrinsic and extrinsic camera parameters double rms; if (s.useFisheye) { Mat _rvecs, _tvecs; - rms = fisheye::calibrate(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, _rvecs, - _tvecs, s.flag); + rms = cv::fisheye::calibrate(objectPoints, imagePoints, imageSize, + cameraMatrix, distCoeffs, _rvecs, _tvecs, s.flag); rvecs.reserve(_rvecs.rows); tvecs.reserve(_tvecs.rows); - for(int i = 0; i < int(objectPoints.size()); i++){ + for (int i = 0; i < static_cast<int>(objectPoints.size()); i++) { rvecs.push_back(_rvecs.row(i)); tvecs.push_back(_tvecs.row(i)); } @@ -563,46 +566,37 @@ static bool _runCalibration( Calibrate::Settings& s, Size& imageSize, Mat& camer int iFixedPoint = -1; if (release_object) iFixedPoint = s.boardSize.width - 1; - //rms = calibrateCameraRO(objectPoints, imagePoints, imageSize, iFixedPoint, - // cameraMatrix, distCoeffs, rvecs, tvecs, newObjPoints, - // s.flag | CALIB_USE_LU); - + rms = calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, s.flag | CALIB_USE_LU); } - /*if (release_object) { - cout << "New board corners: " << endl; - cout << newObjPoints[0] << endl; - cout << newObjPoints[s.boardSize.width - 1] << endl; - cout << newObjPoints[s.boardSize.width * (s.boardSize.height - 1)] << endl; - cout << newObjPoints.back() << endl; - }*/ - LOG(INFO) << "Re-projection error reported by calibrateCamera: "<< rms; bool ok = checkRange(cameraMatrix) && checkRange(distCoeffs); objectPoints.clear(); objectPoints.resize(imagePoints.size(), newObjPoints); - totalAvgErr = computeReprojectionErrors(objectPoints, imagePoints, rvecs, tvecs, cameraMatrix, - distCoeffs, reprojErrs, s.useFisheye); + totalAvgErr = computeReprojectionErrors(objectPoints, imagePoints, rvecs, + tvecs, cameraMatrix, distCoeffs, reprojErrs, s.useFisheye); return ok; } //! [run_and_save] -bool runCalibration(Calibrate::Settings& s, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, - vector<vector<Point2f> > imagePoints, float grid_width, bool release_object) -{ +bool runCalibration(const Calibrate::Settings& s, Size imageSize, + Mat& cameraMatrix, Mat& distCoeffs, + vector<vector<Point2f> > imagePoints, float grid_width, + bool release_object) { vector<Mat> rvecs, tvecs; vector<float> reprojErrs; double totalAvgErr = 0; vector<Point3f> newObjPoints; - bool ok = _runCalibration(s, imageSize, cameraMatrix, distCoeffs, imagePoints, rvecs, tvecs, reprojErrs, - totalAvgErr, newObjPoints, grid_width, release_object); + bool ok = _runCalibration(s, imageSize, cameraMatrix, distCoeffs, + imagePoints, rvecs, tvecs, reprojErrs, totalAvgErr, newObjPoints, + grid_width, release_object); LOG(INFO) << (ok ? "Calibration succeeded" : "Calibration failed") << ". avg re projection error = " << totalAvgErr; diff --git a/cv-node/src/disparity.cpp b/cv-node/src/disparity.cpp index 82d437f461e5bfb25446863a0ac017d9cf2f71c8..a29d6dc3c4987da4f9c2bf819b17f763b71846b1 100644 --- a/cv-node/src/disparity.cpp +++ b/cv-node/src/disparity.cpp @@ -1,8 +1,13 @@ +/* + * Copyright 2019 Nicolas Pope + */ + #include <ftl/disparity.hpp> using ftl::Disparity; -std::map<std::string,std::function<Disparity*(nlohmann::json&)>> Disparity::algorithms__; +std::map<std::string, std::function<Disparity*(nlohmann::json&)>> + Disparity::algorithms__; Disparity::Disparity(nlohmann::json &config) : config_(config), @@ -14,7 +19,8 @@ Disparity *Disparity::create(nlohmann::json &config) { return algorithms__[config["algorithm"]](config); } -void Disparity::_register(const std::string &n, std::function<Disparity*(nlohmann::json&)> f) { +void Disparity::_register(const std::string &n, + std::function<Disparity*(nlohmann::json&)> f) { algorithms__[n] = f; } diff --git a/cv-node/src/display.cpp b/cv-node/src/display.cpp index 9884560ffac44969b57ddebd3e7328eff65b4b95..4889b8026b83a0dde90eb7e2bb1b06d7d411dbb8 100644 --- a/cv-node/src/display.cpp +++ b/cv-node/src/display.cpp @@ -1,22 +1,29 @@ -#include <ftl/display.hpp> +/* + * Copyright 2019 Nicolas Pope + */ + #include <glog/logging.h> +#include <ftl/display.hpp> + using ftl::Display; using ftl::Calibrate; -using namespace cv; +using cv::Mat; +using cv::Vec3f; -Display::Display(const Calibrate &cal, nlohmann::json &config) : calibrate_(cal), config_(config) { +Display::Display(const Calibrate &cal, nlohmann::json &config) : + calibrate_(cal), config_(config) { #if defined HAVE_VIZ window_ = new cv::viz::Viz3d("FTL"); window_->setBackgroundColor(cv::viz::Color::white()); - #endif // HAVE_VIZ + #endif // HAVE_VIZ active_ = true; } Display::~Display() { #if defined HAVE_VIZ delete window_; - #endif // HAVE_VIZ + #endif // HAVE_VIZ } bool Display::render(const cv::Mat &rgb, const cv::Mat &depth) { @@ -25,28 +32,28 @@ bool Display::render(const cv::Mat &rgb, const cv::Mat &depth) { if (config_["points"]) { #if defined HAVE_VIZ cv::Mat Q_32F; - calibrate_.getQ().convertTo(Q_32F,CV_32F); - cv::Mat_<cv::Vec3f> XYZ(depth.rows,depth.cols); // Output point cloud + calibrate_.getQ().convertTo(Q_32F, CV_32F); + cv::Mat_<cv::Vec3f> XYZ(depth.rows, depth.cols); // Output point cloud reprojectImageTo3D(depth+20.0f, XYZ, Q_32F, true); - + // Remove all invalid pixels from point cloud - XYZ.setTo(Vec3f(NAN,NAN,NAN), depth == 0.0f); - - cv::viz::WCloud cloud_widget = cv::viz::WCloud( XYZ, rgb ); - cloud_widget.setRenderingProperty( cv::viz::POINT_SIZE, 2 ); - - window_->showWidget( "coosys", viz::WCoordinateSystem() ); - window_->showWidget( "Depth", cloud_widget ); + XYZ.setTo(Vec3f(NAN, NAN, NAN), depth == 0.0f); + + cv::viz::WCloud cloud_widget = cv::viz::WCloud(XYZ, rgb); + cloud_widget.setRenderingProperty(cv::viz::POINT_SIZE, 2); - window_->spinOnce( 1, true ); + window_->showWidget("coosys", cv::viz::WCoordinateSystem()); + window_->showWidget("Depth", cloud_widget); - #else // HAVE_VIZ + window_->spinOnce(1, true); + + #else // HAVE_VIZ LOG(ERROR) << "Need OpenCV Viz module to display points"; - #endif // HAVE_VIZ + #endif // HAVE_VIZ } - + if (config_["depth"]) { /*Mat depth32F = (focal * (float)l.cols * base_line) / depth; normalize(depth32F, depth32F, 0, 255, NORM_MINMAX, CV_8U); @@ -56,15 +63,12 @@ bool Display::render(const cv::Mat &rgb, const cv::Mat &depth) { active_ = false; }*/ } else if (config_["disparity"]) { - //if (disparity32F.type() == CV_32FC1) { - //disparity32F = disparity32F / (float)config["disparity"]["maximum"]; - depth.convertTo(idepth,CV_8U,255.0f / 208.0f); //(float)config_["maximum"]); - //} - //normalize(disparity32F, disparity32F, 0, 255, NORM_MINMAX, CV_8U); + depth.convertTo(idepth, CV_8U, 255.0f / 208.0f); // TODO(nick) + applyColorMap(idepth, idepth, cv::COLORMAP_JET); cv::imshow("Disparity", idepth); - if(cv::waitKey(10) == 27){ - //exit if ESC is pressed + if(cv::waitKey(10) == 27) { + // exit if ESC is pressed active_ = false; } } diff --git a/cv-node/src/local.cpp b/cv-node/src/local.cpp index 3bd14954716a0e28ef9e27e016a7cf5c5ca8ad90..cb7ee6484148d7c7f5cf917a46db512f4cf1d20a 100644 --- a/cv-node/src/local.cpp +++ b/cv-node/src/local.cpp @@ -1,27 +1,37 @@ -#include <ftl/local.hpp> +/* + * Copyright 2019 Nicolas Pope + */ + +#include <glog/logging.h> -#include <opencv2/core.hpp> -#include <opencv2/opencv.hpp> #include <string> #include <chrono> -#include <glog/logging.h> + +#include <ftl/local.hpp> +#include <opencv2/core.hpp> +#include <opencv2/opencv.hpp> using ftl::LocalSource; using cv::Mat; using cv::VideoCapture; using cv::Rect; using std::string; -using namespace std::chrono; +using std::chrono::duration_cast; +using std::chrono::duration; +using std::chrono::high_resolution_clock; LocalSource::LocalSource(nlohmann::json &config) : timestamp_(0.0), flip_(config["flip"]), nostereo_(config["nostereo"]), - downsize_(config.value("scale",1.0f)) { + downsize_(config.value("scale", 1.0f)) { // Use cameras camera_a_ = new VideoCapture((flip_) ? 1 : 0); - if (!nostereo_) camera_b_ = new VideoCapture((flip_) ? 0 : 1); - else camera_b_ = nullptr; + if (!nostereo_) { + camera_b_ = new VideoCapture((flip_) ? 0 : 1); + } else { + camera_b_ = nullptr; + } if (!camera_a_->isOpened()) { delete camera_a_; @@ -46,24 +56,24 @@ LocalSource::LocalSource(const string &vid, nlohmann::json &config) : timestamp_(0.0), flip_(config["flip"]), nostereo_(config["nostereo"]), - downsize_(config.value("scale",1.0f)) { + downsize_(config.value("scale", 1.0f)) { if (vid == "") { LOG(FATAL) << "No video file specified"; camera_a_ = nullptr; camera_b_ = nullptr; return; } - + camera_a_ = new VideoCapture(vid.c_str()); camera_b_ = nullptr; - + if (!camera_a_->isOpened()) { delete camera_a_; camera_a_ = nullptr; LOG(FATAL) << "Unable to load video file"; return; } - + // Read first frame to determine stereo Mat frame; if (!camera_a_->read(frame)) { @@ -81,12 +91,12 @@ LocalSource::LocalSource(const string &vid, nlohmann::json &config) bool LocalSource::left(cv::Mat &l) { if (!camera_a_) return false; - + if (!camera_a_->grab()) { LOG(ERROR) << "Unable to grab from camera A"; return false; } - + // Record timestamp timestamp_ = duration_cast<duration<double>>( high_resolution_clock::now().time_since_epoch()).count(); @@ -102,15 +112,15 @@ bool LocalSource::left(cv::Mat &l) { LOG(ERROR) << "Unable to read frame from video"; return false; } - + int resx = frame.cols / 2; if (flip_) { - l = Mat(frame, Rect(resx,0,frame.cols-resx,frame.rows)); + l = Mat(frame, Rect(resx, 0, frame.cols-resx, frame.rows)); } else { - l = Mat(frame, Rect(0,0,resx,frame.rows)); + l = Mat(frame, Rect(0, 0, resx, frame.rows)); } } - + return true; } @@ -123,7 +133,7 @@ bool LocalSource::right(cv::Mat &r) { LOG(ERROR) << "Unable to grab from camera B"; return false; } - + // Record timestamp timestamp_ = duration_cast<duration<double>>( high_resolution_clock::now().time_since_epoch()).count(); @@ -140,21 +150,21 @@ bool LocalSource::right(cv::Mat &r) { LOG(ERROR) << "Unable to read frame from video"; return false; } - + int resx = frame.cols / 2; if (flip_) { - r = Mat(frame, Rect(0,0,resx,frame.rows)); + r = Mat(frame, Rect(0, 0, resx, frame.rows)); } else { - r = Mat(frame, Rect(resx,0,frame.cols-resx,frame.rows)); + r = Mat(frame, Rect(resx, 0, frame.cols-resx, frame.rows)); } } - + return true; } bool LocalSource::get(cv::Mat &l, cv::Mat &r) { if (!camera_a_) return false; - + if (!camera_a_->grab()) { LOG(ERROR) << "Unable to grab from camera A"; return false; @@ -163,7 +173,7 @@ bool LocalSource::get(cv::Mat &l, cv::Mat &r) { LOG(ERROR) << "Unable to grab from camera B"; return false; } - + // Record timestamp timestamp_ = duration_cast<duration<double>>( high_resolution_clock::now().time_since_epoch()).count(); @@ -183,29 +193,31 @@ bool LocalSource::get(cv::Mat &l, cv::Mat &r) { LOG(ERROR) << "Unable to read frame from video"; return false; } - + int resx = frame.cols / 2; if (flip_) { - r = Mat(frame, Rect(0,0,resx,frame.rows)); - l = Mat(frame, Rect(resx,0,frame.cols-resx,frame.rows)); + r = Mat(frame, Rect(0, 0, resx, frame.rows)); + l = Mat(frame, Rect(resx, 0, frame.cols-resx, frame.rows)); } else { - l = Mat(frame, Rect(0,0,resx,frame.rows)); - r = Mat(frame, Rect(resx,0,frame.cols-resx,frame.rows)); + l = Mat(frame, Rect(0, 0, resx, frame.rows)); + r = Mat(frame, Rect(resx, 0, frame.cols-resx, frame.rows)); } } - + if (downsize_ != 1.0f) { - cv::resize(l, l, cv::Size(l.cols * downsize_,l.rows * downsize_), 0, 0, cv::INTER_LINEAR); - cv::resize(r, r, cv::Size(r.cols * downsize_,r.rows * downsize_), 0, 0, cv::INTER_LINEAR); + cv::resize(l, l, cv::Size(l.cols * downsize_, l.rows * downsize_), + 0, 0, cv::INTER_LINEAR); + cv::resize(r, r, cv::Size(r.cols * downsize_, r.rows * downsize_), + 0, 0, cv::INTER_LINEAR); } - + return true; } double LocalSource::getTimestamp() const { return timestamp_; } - + bool LocalSource::isStereo() const { return stereo_ && !nostereo_; } diff --git a/cv-node/src/main.cpp b/cv-node/src/main.cpp index 0eb2dc6f2d430082884f6f51d7e5bd26fe8de0ca..d336bcae82e7e3932250e0c6321aaae1f6fb989b 100644 --- a/cv-node/src/main.cpp +++ b/cv-node/src/main.cpp @@ -1,3 +1,14 @@ +/* + * Copyright 2019 Nicolas Pope + */ + +#include <glog/logging.h> +#include <ftl/config.h> + +#include <string> +#include <map> +#include <vector> + #include <opencv2/opencv.hpp> #include <ftl/local.hpp> #include <ftl/synched.hpp> @@ -5,7 +16,6 @@ #include <ftl/disparity.hpp> #include <ftl/middlebury.hpp> #include <ftl/display.hpp> -#include <ftl/config.h> #include <nlohmann/json.hpp> #include "opencv2/imgproc.hpp" @@ -13,20 +23,17 @@ #include "opencv2/highgui.hpp" #include "opencv2/core/utility.hpp" -#include <glog/logging.h> - -#include <string> -#include <map> -#include <vector> - -using namespace ftl; +using ftl::Calibrate; +using ftl::LocalSource; +using ftl::Display; +using ftl::Disparity; +using ftl::SyncSource; using std::string; using std::vector; using std::map; using cv::Mat; using json = nlohmann::json; using std::ifstream; -using namespace cv; // Store loaded configuration static json config; @@ -35,7 +42,7 @@ static json config; * Find and load a JSON configuration file */ static bool findConfiguration(const string &file) { - // TODO Check other locations + // TODO(nick) Check other locations ifstream i((file != "") ? file : FTL_LOCAL_CONFIG_ROOT "/config.json"); if (!i.is_open()) return false; i >> config; @@ -45,24 +52,24 @@ static bool findConfiguration(const string &file) { /** * Generate a map from command line option to value */ -map<string,string> read_options(char ***argv, int *argc) { - map<string,string> opts; - +map<string, string> read_options(char ***argv, int *argc) { + map<string, string> opts; + while (*argc > 0) { string cmd((*argv)[0]); if (cmd[0] != '-') break; - + size_t p; if ((p = cmd.find("=")) == string::npos) { opts[cmd.substr(2)] = "true"; } else { - opts[cmd.substr(2,p-2)] = cmd.substr(p+1); + opts[cmd.substr(2, p-2)] = cmd.substr(p+1); } - + (*argc)--; (*argv)++; } - + return opts; } @@ -70,19 +77,19 @@ map<string,string> read_options(char ***argv, int *argc) { * Put command line options into json config. If config element does not exist * or is of a different type then report an error. */ -static void process_options(const map<string,string> &opts) { +static void process_options(const map<string, string> &opts) { for (auto opt : opts) { if (opt.first == "config") continue; - + if (opt.first == "version") { std::cout << "FTL Vision Node - v" << FTL_VERSION << std::endl; std::cout << FTL_VERSION_LONG << std::endl; exit(0); } - + try { auto ptr = json::json_pointer("/"+opt.first); - // TODO Allow strings without quotes + // TODO(nick) Allow strings without quotes auto v = json::parse(opt.second); if (v.type() != config.at(ptr).type()) { LOG(ERROR) << "Incorrect type for argument " << opt.first; @@ -96,8 +103,8 @@ static void process_options(const map<string,string> &opts) { } static void run(const string &file) { - // TODO Initiate the network - + // TODO(nick) Initiate the network + LocalSource *lsrc; if (file != "") { // Load video file @@ -106,60 +113,57 @@ static void run(const string &file) { // Use cameras lsrc = new LocalSource(config["source"]); } - - auto sync = new SyncSource(); // TODO Pass protocol object + + auto sync = new SyncSource(); // TODO(nick) Pass protocol object // Add any remote channels - /*for (auto c : OPTION_channels) { + /* for (auto c : OPTION_channels) { sync->addChannel(c); - }*/ - + } */ + // Perform or load calibration intrinsics + extrinsics Calibrate calibrate(lsrc, config["calibration"]); if (config["calibrate"]) calibrate.recalibrate(); if (!calibrate.isCalibrated()) LOG(WARNING) << "Cameras are not calibrated!"; - + // Choose and configure disparity algorithm auto disparity = Disparity::create(config["disparity"]); - + Mat l, r, disparity32F, depth32F, lbw, rbw; - + Display display(calibrate, config["display"]); - + while (display.active()) { // Read calibrated images. - calibrate.rectified(l,r); - + calibrate.rectified(l, r); + // Feed into sync buffer and network forward - sync->feed(LEFT, l,lsrc->getTimestamp()); - sync->feed(RIGHT, r,lsrc->getTimestamp()); - + sync->feed(ftl::LEFT, l, lsrc->getTimestamp()); + sync->feed(ftl::RIGHT, r, lsrc->getTimestamp()); + // Read back from buffer - sync->get(LEFT,l); - sync->get(RIGHT,r); - - disparity->compute(l,r,disparity32F); - - // Clip the left edge - //Rect rect((int)config["disparity"]["maximum"],7,disparity32F.cols-(int)config["disparity"]["maximum"],disparity32F.rows-14); + sync->get(ftl::LEFT, l); + sync->get(ftl::RIGHT, r); + + disparity->compute(l, r, disparity32F); // Send RGB+Depth images for local rendering display.render(l, disparity32F); - //streamer.send(l, disparity32F); + // streamer.send(l, disparity32F); } } int main(int argc, char **argv) { argc--; argv++; - + // Process Arguments auto options = read_options(&argv, &argc); if (!findConfiguration(options["config"])) { LOG(FATAL) << "Could not find any configuration!"; } process_options(options); - + // Choose normal or middlebury modes if (config["middlebury"]["dataset"] == "") { run((argc > 0) ? argv[0] : ""); diff --git a/cv-node/src/sync.cpp b/cv-node/src/sync.cpp index f57e5164696aa44cf13501082834fd9b8f7d13e5..8d1671a3fba63e10310bf5e0f6e9f69d06e8c97b 100644 --- a/cv-node/src/sync.cpp +++ b/cv-node/src/sync.cpp @@ -1,3 +1,7 @@ +/* + * Copyright 2019 Nicolas Pope + */ + #include <ftl/synched.hpp> using ftl::SyncSource; @@ -7,9 +11,8 @@ SyncSource::SyncSource() { channels_.push_back(Mat()); channels_.push_back(Mat()); } - -void SyncSource::addChannel(const std::string &c) { +void SyncSource::addChannel(const std::string &c) { } void SyncSource::feed(int channel, cv::Mat &m, double ts) { diff --git a/net/cpp/include/ftl/net/listener.hpp b/net/cpp/include/ftl/net/listener.hpp index e24d4fda04339b7e18a71caeb3bfc3fbc42dfa8f..4d86df5c210ccbdf73b255bf31c885d2863f535a 100644 --- a/net/cpp/include/ftl/net/listener.hpp +++ b/net/cpp/include/ftl/net/listener.hpp @@ -21,8 +21,8 @@ class Protocol; class Listener { public: - Listener(const char *uri); - Listener(int sfd) : descriptor_(sfd) {} + explicit Listener(const char *uri); + explicit Listener(int sfd) : descriptor_(sfd), default_proto_(nullptr) {} virtual ~Listener(); bool isListening() { return descriptor_ >= 0; } diff --git a/net/cpp/include/ftl/net/protocol.hpp b/net/cpp/include/ftl/net/protocol.hpp index 8679bb4a27d2f90c9c846124e9f9737efd06d4b8..9e49358a4ccdde7377228f06b79c2345b20b2662 100644 --- a/net/cpp/include/ftl/net/protocol.hpp +++ b/net/cpp/include/ftl/net/protocol.hpp @@ -49,7 +49,7 @@ class Protocol { friend class Socket; public: - Protocol(const std::string &id); + explicit Protocol(const std::string &id); ~Protocol(); /** diff --git a/net/cpp/include/ftl/net/socket.hpp b/net/cpp/include/ftl/net/socket.hpp index c9d05e7e6504e366bb150f814ad2d6c264462049..f87f4c782d07813458ed08de9bda9afe9784b060 100644 --- a/net/cpp/include/ftl/net/socket.hpp +++ b/net/cpp/include/ftl/net/socket.hpp @@ -35,7 +35,7 @@ struct virtual_caller { template <typename T> struct caller : virtual_caller { - caller(std::function<void(const T&)> f) : f_(f) {}; + explicit caller(std::function<void(const T&)> &f) : f_(f) {}; void operator()(msgpack::object &o) { T r = o.as<T>(); f_(r); }; std::function<void(const T&)> f_; }; @@ -54,8 +54,8 @@ class Socket { public: friend bool ::_run(bool blocking, bool nodelay); public: - Socket(const char *uri); - Socket(int s); + explicit Socket(const char *uri); + explicit Socket(int s); ~Socket(); int close(); @@ -120,9 +120,9 @@ class Socket { size_t size() const { return header_->size-4; } - void onError(std::function<void(Socket&, int err, const char *msg)> f) {} - void onConnect(std::function<void(Socket&)> f); - void onDisconnect(std::function<void(Socket&)> f) {} + void onError(std::function<void(Socket&, int err, const char *msg)> &f) {} + void onConnect(std::function<void(Socket&)> &f); + void onDisconnect(std::function<void(Socket&)> &f) {} protected: bool data(); // Process one message from socket @@ -232,7 +232,7 @@ template <typename... ARGS> int Socket::_send(const std::string &t, ARGS... args) { send_vec_.push_back({const_cast<char*>(t.data()),t.size()}); header_w_->size += t.size(); - return t.size()+_send(args...); + return _send(args...)+t.size(); } template <typename... ARGS> @@ -246,7 +246,7 @@ template <typename T, typename... ARGS> int Socket::_send(const std::vector<T> &t, ARGS... args) { send_vec_.push_back({const_cast<char*>(t.data()),t.size()}); header_w_->size += t.size(); - return t.size()+_send(args...); + return _send(args...)+t.size(); } template <typename... Types, typename... ARGS> diff --git a/net/cpp/include/ftl/uri.hpp b/net/cpp/include/ftl/uri.hpp index 6da23f07dea076757df716773f579afb3fd9b02f..dbbb47dab00cd609849e8fefb2601cb1bb68394b 100644 --- a/net/cpp/include/ftl/uri.hpp +++ b/net/cpp/include/ftl/uri.hpp @@ -11,7 +11,7 @@ namespace ftl { class URI { public: - URI(uri_t puri) { + explicit URI(uri_t puri) { UriUriA uri; #ifdef HAVE_URIPARSESINGLE diff --git a/net/cpp/src/net.cpp b/net/cpp/src/net.cpp index 1ef7a8d368a49c142111b2a9728cbd459e60d9d2..478f336ee21ea127ee0ad9fb10c786f8dca9e636 100644 --- a/net/cpp/src/net.cpp +++ b/net/cpp/src/net.cpp @@ -101,8 +101,6 @@ void ftl::net::stop() { bool _run(bool blocking, bool nodelay) { timeval block; - int n; - int selres = 1; //if (ssock == INVALID_SOCKET) return 1; @@ -110,7 +108,8 @@ bool _run(bool blocking, bool nodelay) { bool repeat = nodelay; while (active || repeat) { - n = setDescriptors(); + int n = setDescriptors(); + int selres = 1; //Wait for a network event or timeout in 3 seconds block.tv_sec = (repeat) ? 0 : 3; diff --git a/net/cpp/src/socket.cpp b/net/cpp/src/socket.cpp index 94a2909c7e781cbef1c1731299c936a0bad67be9..1d1cadbf3dc55ce22f0f28d8c33fe920db26bdc4 100644 --- a/net/cpp/src/socket.cpp +++ b/net/cpp/src/socket.cpp @@ -373,7 +373,7 @@ void Socket::_dispatchReturn(const std::string &d) { } } -void Socket::onConnect(std::function<void(Socket&)> f) { +void Socket::onConnect(std::function<void(Socket&)> &f) { if (connected_) { f(*this); } else { diff --git a/net/cpp/test/socket_unit.cpp b/net/cpp/test/socket_unit.cpp index a71bdac2b677735c1322cbc09e8e331c48b527e6..881da27a96a6d61464450262a5d8c5e4b669a1a2 100644 --- a/net/cpp/test/socket_unit.cpp +++ b/net/cpp/test/socket_unit.cpp @@ -141,7 +141,7 @@ TEST_CASE("Socket::call()", "[rpc]") { int res = s.call<int>("test1"); - REQUIRE( res == 66 ); + REQUIRE( (res == 66) ); } SECTION("one argument call") { @@ -160,7 +160,7 @@ TEST_CASE("Socket::call()", "[rpc]") { int res = s.call<int>("test1", 78); - REQUIRE( res == 43 ); + REQUIRE( (res == 43) ); } waithandler = nullptr; @@ -181,7 +181,7 @@ TEST_CASE("Socket receive RPC", "[rpc]") { fake_send(0, FTL_PROTOCOL_RPC, buf.str()); s.mock_data(); // Force it to read the fake send... - REQUIRE( last_rpc == buf.str() ); + REQUIRE( (last_rpc == buf.str()) ); } SECTION("one argument call") { @@ -194,7 +194,7 @@ TEST_CASE("Socket receive RPC", "[rpc]") { fake_send(0, FTL_PROTOCOL_RPC, buf.str()); s.mock_data(); // Force it to read the fake send... - REQUIRE( last_rpc == buf.str() ); + REQUIRE( (last_rpc == buf.str()) ); } } @@ -211,10 +211,10 @@ TEST_CASE("Socket::operator>>()", "[io]") { i[1] = 0; s.mock_data(); // Force a message read, but no protocol... - REQUIRE( s.size() == 2*sizeof(int) ); + REQUIRE( (s.size() == 2*sizeof(int)) ); s >> i; - REQUIRE( i[0] == 99 ); - REQUIRE( i[1] == 101 ); + REQUIRE( (i[0] == 99) ); + REQUIRE( (i[1] == 101) ); } } @@ -225,43 +225,43 @@ TEST_CASE("Socket::send()", "[io]") { int i = 607; s.send(100,i); - REQUIRE( get_service(0) == 100 ); - REQUIRE( get_size(0) == sizeof(int) ); - REQUIRE( get_value<int>(0) == 607 ); + REQUIRE( (get_service(0) == 100) ); + REQUIRE( (get_size(0) == sizeof(int)) ); + REQUIRE( (get_value<int>(0) == 607) ); } SECTION("send a string") { std::string str("hello world"); s.send(100,str); - REQUIRE( get_service(0) == 100 ); - REQUIRE( get_size(0) == str.size() ); - REQUIRE( get_value<std::string>(0) == "hello world" ); + REQUIRE( (get_service(0) == 100) ); + REQUIRE( (get_size(0) == str.size()) ); + REQUIRE( (get_value<std::string>(0) == "hello world") ); } SECTION("send const char* string") { s.send(100,"hello world"); - REQUIRE( get_service(0) == 100 ); - REQUIRE( get_size(0) == 11 ); - REQUIRE( get_value<std::string>(0) == "hello world" ); + REQUIRE( (get_service(0) == 100) ); + REQUIRE( (get_size(0) == 11) ); + REQUIRE( (get_value<std::string>(0) == "hello world") ); } SECTION("send const char* array") { s.send(100,ftl::net::array{"hello world",10}); - REQUIRE( get_service(0) == 100 ); - REQUIRE( get_size(0) == 10 ); - REQUIRE( get_value<std::string>(0) == "hello worl" ); + REQUIRE( (get_service(0) == 100) ); + REQUIRE( (get_size(0) == 10) ); + REQUIRE( (get_value<std::string>(0) == "hello worl") ); } SECTION("send a tuple") { auto tup = std::make_tuple(55,66,true,6.7); s.send(100,tup); - REQUIRE( get_service(0) == 100 ); - REQUIRE( get_size(0) == sizeof(tup) ); - REQUIRE( get_value<decltype(tup)>(0) == tup ); + REQUIRE( (get_service(0) == 100) ); + REQUIRE( (get_size(0) == sizeof(tup)) ); + REQUIRE( (get_value<decltype(tup)>(0) == tup) ); } SECTION("send multiple strings") { @@ -269,9 +269,9 @@ TEST_CASE("Socket::send()", "[io]") { std::string str2("world"); s.send(100,str,str2); - REQUIRE( get_service(0) == 100 ); - REQUIRE( get_size(0) == str.size()+str2.size() ); - REQUIRE( get_value<std::string>(0) == "hello world" ); + REQUIRE( (get_service(0) == 100) ); + REQUIRE( (get_size(0) == str.size()+str2.size()) ); + REQUIRE( (get_value<std::string>(0) == "hello world") ); } } @@ -285,9 +285,9 @@ TEST_CASE("Socket::read()", "[io]") { i = 0; s.mock_data(); // Force a message read, but no protocol... - REQUIRE( s.size() == sizeof(int) ); - REQUIRE( s.read(i) == sizeof(int) ); - REQUIRE( i == 99 ); + REQUIRE( (s.size() == sizeof(int)) ); + REQUIRE( (s.read(i) == sizeof(int)) ); + REQUIRE( (i == 99) ); } SECTION("read two ints") { @@ -300,10 +300,10 @@ TEST_CASE("Socket::read()", "[io]") { i[1] = 0; s.mock_data(); // Force a message read, but no protocol... - REQUIRE( s.size() == 2*sizeof(int) ); - REQUIRE( s.read(&i,2) == 2*sizeof(int) ); - REQUIRE( i[0] == 99 ); - REQUIRE( i[1] == 101 ); + REQUIRE( (s.size() == 2*sizeof(int)) ); + REQUIRE( (s.read(&i,2) == 2*sizeof(int)) ); + REQUIRE( (i[0] == 99) ); + REQUIRE( (i[1] == 101) ); } SECTION("multiple reads") { @@ -316,10 +316,10 @@ TEST_CASE("Socket::read()", "[io]") { i[1] = 0; s.mock_data(); // Force a message read, but no protocol... - REQUIRE( s.read(&i[0],1) == sizeof(int) ); - REQUIRE( i[0] == 99 ); - REQUIRE( s.read(&i[1],1) == sizeof(int) ); - REQUIRE( i[1] == 101 ); + REQUIRE( (s.read(&i[0],1) == sizeof(int)) ); + REQUIRE( (i[0] == 99) ); + REQUIRE( (s.read(&i[1],1) == sizeof(int)) ); + REQUIRE( (i[1] == 101) ); } SECTION("read a string") { @@ -328,9 +328,9 @@ TEST_CASE("Socket::read()", "[io]") { s.mock_data(); // Force a message read, but no protocol... - REQUIRE( s.size() == 11 ); - REQUIRE( s.read(str) == 11 ); - REQUIRE( str == "hello world" ); + REQUIRE( (s.size() == 11) ); + REQUIRE( (s.read(str) == 11) ); + REQUIRE( (str == "hello world") ); } SECTION("read into existing string") { @@ -341,10 +341,10 @@ TEST_CASE("Socket::read()", "[io]") { s.mock_data(); // Force a message read, but no protocol... - REQUIRE( s.size() == 11 ); - REQUIRE( s.read(str) == 11 ); - REQUIRE( str == "hello world" ); - REQUIRE( str.data() == ptr ); + REQUIRE( (s.size() == 11) ); + REQUIRE( (s.read(str) == 11) ); + REQUIRE( (str == "hello world") ); + REQUIRE( (str.data() == ptr) ); } SECTION("read too much data") { @@ -354,9 +354,9 @@ TEST_CASE("Socket::read()", "[io]") { i = 0; s.mock_data(); // Force a message read, but no protocol... - REQUIRE( s.size() == sizeof(int) ); - REQUIRE( s.read(&i,2) == sizeof(int) ); - REQUIRE( i == 99 ); + REQUIRE( (s.size() == sizeof(int)) ); + REQUIRE( (s.read(&i,2) == sizeof(int)) ); + REQUIRE( (i == 99) ); } }