Skip to content

Commit

Permalink
Make wave_utils not depend on opencv (#237)
Browse files Browse the repository at this point in the history
Part of #234 

- Remove wave_utils dependency on OpenCV
- Move the cv::Mat parser to wave_vision 
- (tacking on) request correct Ceres version
  • Loading branch information
leokoppel authored Nov 1, 2017
1 parent dcc92e1 commit f6ae3fd
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 84 deletions.
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ OPTION(BUILD_BENCHMARKS
# Find all dependencies here, and ensure they have IMPORTED targets

# Require Eigen 3.2.92, also called 3.3 beta-1, since it's in xenial
FIND_PACKAGE(Eigen3 REQUIRED 3.2.92)
FIND_PACKAGE(Eigen3 3.2.92 REQUIRED)
FIND_PACKAGE(Boost 1.54.0 COMPONENTS system filesystem)
FIND_PACKAGE(PCL 1.8 COMPONENTS
common filters registration kdtree search io visualization)
FIND_PACKAGE(kindr)
FIND_PACKAGE(OpenCV 3.2.0 REQUIRED core features2d calib3d imgproc highgui)
FIND_PACKAGE(OpenCV 3.2.0 COMPONENTS core features2d calib3d imgproc highgui)
FIND_PACKAGE(yaml-cpp REQUIRED)
FIND_PACKAGE(Ceres)
FIND_PACKAGE(Ceres 1.12)

# Where dependencies do not provide IMPORTED targets, define them
INCLUDE(cmake/ImportEigen3.cmake)
Expand Down
2 changes: 1 addition & 1 deletion cmake/waveConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ FIND_PACKAGE(PCL 1.8 QUIET)
FIND_PACKAGE(kindr QUIET)
FIND_PACKAGE(OpenCV 3.2.0 QUIET)
FIND_PACKAGE(yaml-cpp QUIET)
FIND_PACKAGE(Ceres QUIET)
FIND_PACKAGE(Ceres 1.12 QUIET)

# Where dependencies do not provide imported targets, define them
INCLUDE(${WAVE_EXTRA_CMAKE_DIR}/ImportEigen3.cmake)
Expand Down
1 change: 0 additions & 1 deletion wave_utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ WAVE_ADD_MODULE(${PROJECT_NAME}
DEPENDS
Eigen3::Eigen
yaml-cpp
opencv_core
SOURCES
src/config.cpp
src/data.cpp
Expand Down
30 changes: 0 additions & 30 deletions wave_utils/include/wave/utils/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@

#include <yaml-cpp/yaml.h>

#include <opencv2/core/core.hpp>

#include "wave/utils/math.hpp"
#include "wave/utils/log.hpp"
#include "wave/utils/file.hpp"
Expand Down Expand Up @@ -220,34 +218,6 @@ template struct convert<wave::Vec3>;
template struct convert<wave::Vec4>;
template struct convert<wave::VecX>;


/** Custom conversion for YAML -> cv::Mat
*
* @note We require the yaml node to have three nested keys in order to parse a
* matrix. They are `rows`, `cols` and `data`.
*
* For example:
* ```yaml
* some_matrix:
* rows: 3
* cols: 3
* data: [1.1, 2.2, 3.3,
* 4.4, 5.5, 6.6,
* 7.7, 8.8, 9.9]
* ```
*
*/
template <>
struct convert<cv::Mat> {
/** Convert YAML node to cv matrix
*
* @throws YAML::InvalidNode if nested keys not found
* @returns true if conversion successful
*/
static bool decode(const Node &node, cv::Mat &out);
};

} // namespace YAML

#endif // WAVE_UTILS_CONFIG_HPP
26 changes: 0 additions & 26 deletions wave_utils/src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,30 +157,4 @@ bool convert<Eigen::Matrix<Scalar, Rows, 1>>::decode(
return true;
}

bool convert<cv::Mat>::decode(const Node &node, cv::Mat &out) {
int rows = node["rows"].as<int>();
int cols = node["cols"].as<int>();
const auto &data = node["data"];

// Check `rows` and `cols` values
if (rows <= 0 || cols <= 0) {
return false;
}

// Check data node is a list of the right length
std::size_t expected_size = rows * cols;
if (!data.IsSequence() || data.size() != expected_size) {
return false;
}

// Copy it to destination
out = cv::Mat{rows, cols, CV_64F};
for (int i = 0, index = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
out.at<double>(i, j) = node["data"][index++].as<double>();
}
}
return true;
}

} // namespace YAML
20 changes: 1 addition & 19 deletions wave_utils/tests/utils/config_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ TEST(Utils_config_ConfigParser, addParam) {
wave::Mat3 mat3;
wave::Mat4 mat4;
wave::MatX matx;
cv::Mat cvmat;

wave::ConfigParser parser;

Expand All @@ -58,9 +57,8 @@ TEST(Utils_config_ConfigParser, addParam) {
parser.addParam("matrix3", &mat3);
parser.addParam("matrix4", &mat4);
parser.addParam("matrix", &matx);
parser.addParam("matrix", &cvmat);

ASSERT_EQ(19, (int) parser.params.size());
ASSERT_EQ(18, (int) parser.params.size());
ASSERT_EQ("bool", parser.params[0]->key);
}

Expand Down Expand Up @@ -215,7 +213,6 @@ TEST(Utils_config_ConfigParser, loadMatrix) {
wave::Mat3 mat3;
wave::Mat4 mat4;
wave::MatX matx;
cv::Mat cvmat;
wave::ConfigParser parser;

// setup
Expand Down Expand Up @@ -265,18 +262,6 @@ TEST(Utils_config_ConfigParser, loadMatrix) {
index++;
}
}

// CV MATRIX
wave::ConfigParam<cv::Mat> cvmat_param{"matrix", &cvmat};
parser.loadParam(cvmat_param);

index = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
ASSERT_FLOAT_EQ((index + 1) * 1.1, cvmat.at<double>(i, j));
index++;
}
}
}

TEST(Utils_config_ConfigParser, load) {
Expand All @@ -301,7 +286,6 @@ TEST(Utils_config_ConfigParser, load) {
wave::Mat3 mat3;
wave::Mat4 mat4;
wave::MatX matx;
cv::Mat cvmat;

wave::ConfigParser parser;

Expand All @@ -326,7 +310,6 @@ TEST(Utils_config_ConfigParser, load) {
parser.addParam("matrix3", &mat3);
parser.addParam("matrix4", &mat4);
parser.addParam("matrix", &matx);
parser.addParam("matrix", &cvmat);

auto res = parser.load(TEST_CONFIG);
EXPECT_EQ(wave::ConfigStatus::OK, res);
Expand All @@ -348,6 +331,5 @@ TEST(Utils_config_ConfigParser, load) {
std::cout << "matrix3: \n" << mat3 << std::endl;
std::cout << "matrix4: \n" << mat4 << std::endl;
std::cout << "matrix: \n" << matx << std::endl;
std::cout << "cvmatrix: \n" << cvmat << std::endl;
std::cout << std::endl;
}
8 changes: 6 additions & 2 deletions wave_vision/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ IF(BUILD_TESTING)
tests/matcher_tests/brute_force_tests.cpp
tests/matcher_tests/flann_tests.cpp
tests/tracker_tests/tracker_tests.cpp
tests/dataset_tests/vo_dataset_tests.cpp
tests/utils_tests.cpp)
tests/dataset_tests/vo_dataset_tests.cpp)
TARGET_LINK_LIBRARIES(${PROJECT_NAME}_tests ${PROJECT_NAME})

WAVE_ADD_TEST(${PROJECT_NAME}_utils_tests
tests/utils_tests.cpp)
TARGET_LINK_LIBRARIES(${PROJECT_NAME}_utils_tests ${PROJECT_NAME})


WAVE_ADD_TEST(${PROJECT_NAME}_viz_tests
tests/viz_tests/detector_viz_tests.cpp
tests/viz_tests/descriptor_viz_tests.cpp
Expand Down
27 changes: 27 additions & 0 deletions wave_vision/include/wave/vision/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,31 @@ std::vector<cv::Mat> readImageSequence(const std::string &images_path);
/** @} group vision */
} // namespace wave

namespace YAML {
/** Custom conversion for YAML -> cv::Mat
*
* @note We require the yaml node to have three nested keys in order to parse a
* matrix. They are `rows`, `cols` and `data`.
*
* For example:
* ```yaml
* some_matrix:
* rows: 3
* cols: 3
* data: [1.1, 2.2, 3.3,
* 4.4, 5.5, 6.6,
* 7.7, 8.8, 9.9]
* ```
*/
template <>
struct convert<cv::Mat> {
/** Convert YAML node to cv matrix
*
* @throws YAML::InvalidNode if nested keys not found
* @returns true if conversion successful
*/
static bool decode(const Node &node, cv::Mat &out);
};
} // namespace YAML

#endif // WAVE_VISION_COMMON_HPP
29 changes: 29 additions & 0 deletions wave_vision/src/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,33 @@ std::vector<cv::Mat> readImageSequence(const std::string &path) {

return image_sequence;
}

} // namespace wave

namespace YAML {
bool convert<cv::Mat>::decode(const Node &node, cv::Mat &out) {
int rows = node["rows"].as<int>();
int cols = node["cols"].as<int>();
const auto &data = node["data"];

// Check `rows` and `cols` values
if (rows <= 0 || cols <= 0) {
return false;
}

// Check data node is a list of the right length
std::size_t expected_size = rows * cols;
if (!data.IsSequence() || data.size() != expected_size) {
return false;
}

// Copy it to destination
out = cv::Mat{rows, cols, CV_64F};
for (int i = 0, index = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
out.at<double>(i, j) = node["data"][index++].as<double>();
}
}
return true;
}
} // namespace YAML
6 changes: 6 additions & 0 deletions wave_vision/tests/data/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
test_matrix:
rows: 3
cols: 4
data: [1.1, 2.2, 3.3, 4.4,
5.5, 6.6, 7.7, 8.8,
9.9, 11.0, 12.1, 13.2]
40 changes: 38 additions & 2 deletions wave_vision/tests/utils_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@

namespace wave {

const std::string IMG_FOLDER_PATH =
"tests/data/tracker_test_sequence/frame0057.jpg";
const auto IMG_FOLDER_PATH = "tests/data/tracker_test_sequence/frame0057.jpg";

const auto TEST_CONFIG_FILE = "tests/data/config.yaml";

TEST(VisionCommon, focal_length) {
double f = focal_length(60, 640);
Expand Down Expand Up @@ -197,4 +198,39 @@ TEST_F(PinholeProjectTest, projectKnownPoint) {
EXPECT_PRED2(VectorsNear, expected, meas);
}

TEST(VisionYamlConfig, loadCvMatParam) {
wave::ConfigParser parser;
cv::Mat cvmat;

// setup
parser.root = YAML::LoadFile(TEST_CONFIG_FILE);
parser.config_loaded = true;

// CV MATRIX
wave::ConfigParam<cv::Mat> cvmat_param{"test_matrix", &cvmat};
parser.loadParam(cvmat_param);


for (int i = 0, index = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
ASSERT_FLOAT_EQ((index + 1) * 1.1, cvmat.at<double>(i, j));
index++;
}
}
}

TEST(VisionYamlConfig, cvMatWithConfigParser) {
cv::Mat cvmat;
wave::ConfigParser parser;
parser.addParam("test_matrix", &cvmat);
parser.load(TEST_CONFIG_FILE);

for (int i = 0, index = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
ASSERT_FLOAT_EQ((index + 1) * 1.1, cvmat.at<double>(i, j));
index++;
}
}
}

} // namespace wave

0 comments on commit f6ae3fd

Please sign in to comment.