Reputation: 185
I want to pass a M \times N \times K matrix from C++ to R. Basically I have a cv::Mat
object and I want to pass it efficiently in R. It is not very difficult to convert a M \times N cv::Mat
to arma::Mat
or Rcpp::NumericMatrix
. But it will be great if I can get a wrapper for higher dimensional matrices as well.
Upvotes: 1
Views: 237
Reputation: 9433
Now you can use the xtensor
package from CRAN.
// [[Rcpp::plugins(cpp14)]]
// [[Rcpp::plugins(opencv)]]
// [[Rcpp::depends(xtensor)]]
#include <xtensor/xadapt.hpp>
#include <xtensor-r/rtensor.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <Rcpp.h>
using xtensor3d = xt::xtensor<double, 3>;
using rtensor3d = xt::rtensor<double, 3>;
template <typename T, int NCH, typename XT=xt::xtensor<T,3,xt::layout_type::column_major>>
XT to_xt(const cv::Mat_<cv::Vec<T, NCH>>& src) {
std::vector<int> shape = {src.rows, src.cols, NCH};
size_t size = src.total() * NCH;
XT res = xt::adapt((T*) src.data, size, xt::no_ownership(), shape);
return res;
}
// [[Rcpp::export]]
rtensor3d read_image(std::string file) {
cv::Mat img = cv::imread(file);
img.convertTo(img, CV_32FC3);
xtensor3d res = img.channels() == 3 ? to_xt<double, 3>(img) : to_xt<double, 1>(img);
return res;
}
opencv
Rcpp plugin should be exported as:
Rcpp::registerPlugin("opencv", function() {
pkg_config_name <- "opencv4"
pkg_config_bin <- Sys.which("pkg-config")
checkmate::assert_file_exists(pkg_config_bin, access = "x")
list(env = list(
PKG_CXXFLAGS = system(paste(pkg_config_bin, "--cflags", pkg_config_name), intern = TRUE),
PKG_LIBS = system(paste(pkg_config_bin, "--libs", pkg_config_name), intern = TRUE)
))
})
Upvotes: 1