diff --git a/.ci/macos-steps.yaml b/.ci/macos-steps.yaml index d867d975..c12a8893 100644 --- a/.ci/macos-steps.yaml +++ b/.ci/macos-steps.yaml @@ -12,7 +12,7 @@ steps: sudo xcode-select --switch /Applications/Xcode_10.1.app/Contents/Developer unset BOOST_ROOT pip install cython numpy pandas zipp configparser - brew install openblas armadillo boost + brew install openblas armadillo boost opencv git clone --depth 1 https://github.com/mlpack/jenkins-conf.git conf git clone --depth 1 https://github.com/mlpack/mlpack.git displayName: 'Install Build Dependencies' diff --git a/.ci/windows-steps.yaml b/.ci/windows-steps.yaml index 57e1be52..e82ce59f 100644 --- a/.ci/windows-steps.yaml +++ b/.ci/windows-steps.yaml @@ -20,6 +20,7 @@ steps: nuget install boost_date_time-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0 nuget install boost_regex-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0 nuget install OpenBLAS -o $(Agent.ToolsDirectory) + nuget install OpenCV -o $(Agent.ToolsDirectory) mkdir -p $(Agent.ToolsDirectory)/boost_libs cp $(Agent.ToolsDirectory)/boost_program_options-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs diff --git a/CMakeLists.txt b/CMakeLists.txt index d5a32184..5f77218d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,6 +156,8 @@ if (NOT ENSMALLEN_FOUND) endif () endif () +#find_package(OpenCV REQUIRED) + # Unfortunately this configuration variable is necessary and will need to be # updated as time goes on and new versions are released. set(Boost_ADDITIONAL_VERSIONS @@ -196,10 +198,12 @@ set(MODELS_INCLUDE_DIRS ${MLPACK_INCLUDE_DIR} ${ENSMALLEN_INCLUDE_DIR} ${ARMADILLO_INCLUDE_DIR} ${Boost_INCLUDE_DIRS}) +# ${OpenCV_INCLUDE_DIRS}) set(MODELS_LIBRARIES ${MLPACK_LIBRARY} ${ARMADILLO_LIBRARIES} ${Boost_LIBRARIES}) +# ${OpenCV_LIBS}) include_directories(${MODELS_INCLUDE_DIRS}) @@ -217,6 +221,7 @@ set(DIRS utils/ dataloader/ tests/ +# visualization_tools/ ) foreach(dir ${DIRS}) diff --git a/visualization_tools/visualization_tools.hpp b/visualization_tools/visualization_tools.hpp new file mode 100644 index 00000000..7c6a7a71 --- /dev/null +++ b/visualization_tools/visualization_tools.hpp @@ -0,0 +1,108 @@ +/** + * @file visualization_tools.hpp + * @author Kartik Dutt + * + * Visualization tools to visualize detection and segmentation algorithms. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef MODELS_VISUALIZATION_TOOLS_HPP +#define MODELS_VISUALIZATION_TOOLS_HPP + +#include +#include + +/** + * Tools to visualize data and predictions. + */ +class VisualizationTools +{ + public: + /** + * Save and plot bounding boxes on images. + */ + template + static void VisualizeBoundingBoxes( + ImageType& images, + arma::field& boundingBoxes, + const size_t imageWidth = 224, + const size_t imageHeight = 224, + const size_t imageDepth = 3, + const bool cornerRepresentation = true, + const bool plot = false, + const bool saveImages = false, + const std::vector imagePath = std::vector()) + { + if (saveImages) + { + mlpack::Log::Assert(images.n_cols == imagePath.size(), + "Mismatch between number of images," + std::to_string(image.n_cols) +\ + " and image file paths" + to_string(imagePath.size()) + "."); + } + for (size_t i = 0; i < image.n_cols; i++) + { + arma::vec bBoxes = boundingBoxes(0, i); + arma::cube image(imageWidth * imageHeight * imageDepth, 1, 1); + image.slice(0).col(0) = image.col(i); + image.reshape(imageWidth, imageHeight, imageDepth); + cv::mat img = CubeToOpenCV(image); + for (size_t boxIdx = 0; boxIdx < bBoxes.n_elem; boxIdx += 4) + { + cv::Point upperRightPoint, lowerLeftPoint; + if (cornerRepresentation) + { + upperRightPoint = cv::Point(bBoxes(boxIdx * 4), + bBoxes(boxIdx * 4 + 1)); + lowerLeftPoint = cv::Point(bBoxes(boxIdx * 4 + 2), + bBoxes(boxIdx * 4 + 3)); + } + else + { + upperRightPoint = cv::Point(bBoxes(boxIdx * 4), + bBoxes(boxIdx * 4 + 1)); + lowerLeftPoint = cv::Point(bBoxes(boxIdx * 4) + + bBoxes(boxIdx * 4 + 2), bBoxes(boxIdx * 4 + 1) + + bBoxes(boxIdx * 4 + 3)); + } + + cv::rectangle(img, lowerRightPoint, upperRightPoint, + cv::Scalar(rand() % 255, rand() % 255, rand() % 255)); + } + } + + if (plot) + { + cv::imshow("Image", img); + } + + if (saveImages) + { + cv::imwrite(imagePath[i], img); + } + } + + private: + /** + * Convert armadillo cube to opencv matrix. + */ + template + cv::Mat CubeToOpenCVMat(const Mat& input) + { + vector> channels; + for (size_t c = 0; c < input.n_slices; ++c) + { + auto* data = const_cast(input.slice(c).memptr()); + channels.push_back({int(input.n_cols), int(input.n_rows), data}); + } + + cv::Mat dst; + cv::merge(channels, dst); + return dst; + } +}; + +#endif