diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION index 7d788de..c201369 100644 --- a/CRAN-SUBMISSION +++ b/CRAN-SUBMISSION @@ -1,3 +1,3 @@ -Version: 4.80.0 -Date: 2023-07-20 12:13:05 UTC -SHA: a5d4e9111377647a4ecd4acf0f4e6e4c1749851f +Version: 4.80.1 +Date: 2023-10-31 20:16:13 UTC +SHA: a232d31f9896a90915891173e4d284ac9f8f7892 diff --git a/DESCRIPTION b/DESCRIPTION index 5f5eeb6..867f11d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: ROpenCVLite Type: Package Title: Helper Package for Installing OpenCV with R -Version: 4.80.1 -Date: 2023-10-31 +Version: 4.80.2 +Date: 2023-12-31 Authors@R: c( person("Simon", "Garnier", email = "garnier@njit.edu", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-3886-3974")), diff --git a/NEWS.md b/NEWS.md index 8ab93cb..6f0ab55 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,16 @@ -# ROpenCVLite 4.80.0 +# ROpenCVLite 4.80.2 + +## New features + +* Overhaul of the installation functions for easier update management. + +## Minor improvements and fixes + +* Add compilation flags required to avoid errors on Windows 11. + +--- + +# ROpenCVLite 4.80.1 ## New features diff --git a/R/install.R b/R/install.R new file mode 100644 index 0000000..c233a32 --- /dev/null +++ b/R/install.R @@ -0,0 +1,266 @@ +#' @title Default Install Location of OpenCV +#' +#' @description This function returns the location at which OpenCV should be +#' installed by default. +#' +#' @return A character string. +#' +#' @author Simon Garnier, \email{garnier@@njit.edu} +#' +#' @examples +#' \dontrun{ +#' defaultOpenCVPath() +#' } +#' +#' @export +defaultOpenCVPath <- function() { + pkgPath <- find.package("ROpenCVLite") + paste0(gsub("ROpenCVLite", "", pkgPath), "ROpenCV") +} + + +.configure <- function(install_path = defaultOpenCVPath(), version) { + config <- list() + + config$install_path <- normalizePath(install_path, mustWork = FALSE) + config$pkg_path <- find.package("ROpenCVLite") + + config$arch <- unname(Sys.info()["machine"]) + if (!grepl("64", config$arch)) + stop("Unsupported CPU architecture.") + + config$os_type <- .Platform$OS.type + + if (config$os_type == "windows") { + config$os <- gsub("\r", "", gsub("Caption=", "", system('wmic os get Caption,CSDVersion /value', intern = TRUE)[3])) + config$core <- paste0("https://github.com/opencv/opencv/archive/", version, ".tar.gz") + config$contrib <- paste0("https://github.com/opencv/opencv_contrib/archive/", version, ".tar.gz") + config$rtools_path <- pkgbuild::rtools_path() + + if (is.null(config$rtools_path)) + stop("Rtools is not installed.") + + config$rtools_version <- as.numeric( + regmatches(config$rtools_path, + regexec("rtools\\s*(.*?)\\s*/", + config$rtools_path, + ignore.case = TRUE))[[1]][2] + ) + + if (is.na(config$rtools_version)) { + config$rtools_path <- gsub("(Rtools/).*", "\\1", config$rtools_path) + config$cmake_path <- system("where cmake.exe", intern = TRUE) + config$gcc_path <- paste0(config$rtools_path, "/mingw_64/bin/gcc.exe") + config$gpp_path <- paste0(config$rtools_path, "/mingw_64/bin/g++.exe") + config$windres_path <- paste0(config$rtools_path, "/mingw_64/bin/windres.exe") + config$make_path <- paste0(config$rtools_path, "/mingw_64/bin/mingw32-make.exe") + } else { + config$rtools_path <- gsub(paste0("(rtools", config$rtools_version, "/).*"), "\\1", config$rtools_path) + + if (config$rtools_version == 40) { + config$cmake_path <- system("where cmake.exe", intern = TRUE) + config$gcc_path <- paste0(config$rtools_path, "/mingw64/bin/gcc.exe") + config$gpp_path <- paste0(config$rtools_path, "/mingw64/bin/g++.exe") + config$windres_path <- paste0(config$rtools_path, "/mingw64/bin/windres.exe") + config$make_path <- paste0(config$rtools_path, "/usr/bin/make.exe") + } else { + config$cmake_path <- paste0(config$rtools_path, "/x86_64-w64-mingw32.static.posix", "/bin/cmake.exe") + config$gcc_path <- paste0(config$rtools_path, "/x86_64-w64-mingw32.static.posix", "/bin/gcc.exe") + config$gpp_path <- paste0(config$rtools_path, "/x86_64-w64-mingw32.static.posix", "/bin/g++.exe") + config$windres_path <- paste0(config$rtools_path, "/x86_64-w64-mingw32.static.posix", "/bin/windres.exe") + config$make_path <- paste0(config$rtools_path, "/usr/bin/make.exe") + } + } + } else if (config$os_type == "unix") { + config$os <- unname(Sys.info()["sysname"]) + config$core <- paste0("https://github.com/opencv/opencv/archive/", version, ".zip") + config$contrib <- paste0("https://github.com/opencv/opencv_contrib/archive/", version, ".zip") + config$cmake_path <- system("which cmake", intern = TRUE) + config$gcc_path <- system("which gcc", intern = TRUE) + config$gpp_path <- system("which g++", intern = TRUE) + config$make_path <- system("which make", intern = TRUE) + } else { + stop("Unsupported OS type.") + } + + config$tmp_dir <- gsub("\\\\", "/", base::tempdir()) + config$source_dir <- paste0(config$tmp_dir, "/opencv-", version, "/") + config$contrib_dir <- paste0(config$tmp_dir, "/opencv_contrib-", version, "/modules") + config$build_dir <- paste0(config$source_dir, "build") + + config +} + + +.cmake <- function(config) { + paste0( + config$cmake_path, + ' -G "Unix Makefiles"', + ' -DCMAKE_C_COMPILER=', config$gcc_path, + switch(config$os_type, + windows = paste0(' -DCMAKE_RC_COMPILER=', config$windres_path, + ' -DOpenCV_ARCH=x64', + ' -DOpenCV_RUNTIME=mingw', + ' -DBUILD_SHARED_LIBS=ON', + if (grepl("11", config$os)) ' -DCPU_DISPATCH=SSE4_1,SSE4_2,FP16,AV') + ), + ' -DCMAKE_MAKE_PROGRAM=', config$make_path, + ' -DENABLE_PRECOMPILED_HEADERS=OFF', + ' -DOPENCV_EXTRA_MODULES_PATH=', config$contrib_dir, + ' -DBUILD_LIST=calib3d,core,dnn,features2d,flann,gapi,highgui,imgcodecs,imgproc,ml,objdetect,photo,stitching,video,videoio,ximgproc', + ' -DBUILD_opencv_world=OFF', + ' -DBUILD_opencv_contrib_world=OFF', + ' -DBUILD_PERF_TESTS=OFF', + ' -DBUILD_TESTS=OFF', + ' -DCMAKE_C_FLAGS_RELEASE="-fstack-protector-strong"', + ' -DCMAKE_CXX_FLAGS_RELEASE="-fstack-protector-strong"', + ' -DINSTALL_CREATE_DISTRIB=ON', + ' -DCMAKE_BUILD_TYPE=RELEASE', + ' -DCMAKE_INSTALL_PREFIX=', config$install_path, + ' -B', config$build_dir, + ' -H', config$source_dir + ) +} + + +#' @title Install OpenCV +#' +#' @description This function attempts to download, compile and install OpenCV +#' on the system. This process will take several minutes. +#' +#' @param install_path A character string indicating the location at which +#' OpenCV should be installed. By default, it is the value returned by +#' \code{\link{defaultOpenCVPath}}. +#' +#' @param batch A boolean indicating whether to skip (\code{TRUE}) or not +#' (\code{FALSE}, the default) the interactive installation dialog. This is +#' useful when OpenCV needs to be installed in a non-interactive environment +#' (e.g., during a batch installation on a server). +#' +#' @return A boolean. +#' +#' @author Simon Garnier, \email{garnier@@njit.edu} +#' +#' @examples +#' \dontrun{ +#' installOpenCV() +#' } +#' +#' @export +installOpenCV <- function(install_path = defaultOpenCVPath(), batch = FALSE) { + install <- 0 + pkg_version <- paste0( + strsplit(as.character(utils::packageVersion("ROpenCVLite")), "")[[1]][c(1, 3, 4)], + collapse = ".") + + if (interactive()) { + if (isOpenCVInstalled()) { + cv_version <- gsub("Version ", "", opencvVersion()) + + if (pkg_version == cv_version) { + install <- utils::menu(c("yes", "no"), title = "OpenCV is already installed on this system. Would you like to reinstall it now? This will take several minutes.") + } else { + install <- utils::menu(c("yes", "no"), title = "A new version of OpenCV is available. Would you like to install it now? This will take several minutes.") + } + } else { + install <- utils::menu(c("yes", "no"), title = "OpenCV is not installed on this system. Would you like to install it now? This will take several minutes.") + } + } else { + if (batch) { + packageStartupMessage("OpenCV being installed in non-interactive mode!") + install <- 1 + } else { + packageStartupMessage("OpenCV can only be installed in interactive mode. To override this in a non-interactive context, use installOpenCV(batch = TRUE).") + } + } + + if (!isCmakeInstalled()) + install <- 0 + + if (install == 1) { + config <- .configure(normalizePath(install_path, mustWork = FALSE), pkg_version) + message(paste0("OpenCV will be installed in ", config$install_path)) + old <- try(OpenCVPath(), silent = TRUE) + + if (dir.exists(config$install_path)) { + message("Clearing install path.") + unlink(config$install_path, recursive = TRUE) + } + + if (inherits(config$install_path, "try-error")) { + if (dir.exists(old)) { + message("Removing old OpenCV installation.") + unlink(old, recursive = TRUE) + } + } + + dir.create(config$install_path, showWarnings = FALSE) + dir.create(config$tmp_dir, showWarnings = FALSE) + + if (config$os_type == "windows") { + utils::download.file(config$core, paste0(config$tmp_dir, "/opencv.tar.gz")) + utils::untar(paste0(config$tmp_dir, "/opencv.tar.gz"), exdir = config$tmp_dir) + utils::download.file(config$contrib, paste0(config$tmp_dir, "/opencv_contrib.tar.gz")) + utils::untar(paste0(config$tmp_dir, "/opencv_contrib.tar.gz"), exdir = config$tmp_dir) + } else { + utils::download.file(config$core, paste0(config$tmp_dir, "/opencv.zip")) + utils::unzip(paste0(config$tmp_dir, "/opencv.zip"), exdir = config$tmp_dir) + utils::download.file(config$contrib, paste0(config$tmp_dir, "/opencv_contrib.zip")) + utils::unzip(paste0(config$tmp_dir, "/opencv_contrib.zip"), exdir = config$tmp_dir) + + tmp <- readLines(paste0(config$source_dir, "cmake/OpenCVModule.cmake")) + ix <- which(grepl("# adds dependencies to OpenCV module", tmp)) - 1 + insert <- c( + '# set CMAKE_INSTALL_NAME_DIR if CMAKE_INSTALL_PREFIX isn\'t default value of "/usr/local"', + 'if(UNIX AND NOT ${CMAKE_INSTALL_PREFIX} STREQUAL "/usr/local")', + ' set(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/lib)', + '# message ("setting CMAKE_INSTALL_NAME_DIR: ${CMAKE_INSTALL_NAME_DIR}")', + 'endif()', + '' + ) + writeLines(c(tmp[1:ix], insert, tmp[(ix + 1):length(tmp)]), + paste0(config$source_dir, "cmake/OpenCVModule.cmake")) + } + + system(.cmake(config)) + system(paste0(config$make_path, " -j", parallel::detectCores(), " -C ", config$build_dir)) + system(paste0(config$make_path, " -C", config$build_dir, " install")) + writeLines(config$install_path, con = paste0(config$pkg_path, "/path")) + } else { + packageStartupMessage("OpenCV was not installed at this time. You can install it at any time by using the installOpenCV() function.") + } + + isOpenCVInstalled() +} + + +#' @title Remove OpenCV +#' +#' @description This function removes OpenCV from the system. +#' +#' @return A boolean. +#' +#' @author Simon Garnier, \email{garnier@@njit.edu} +#' +#' @examples +#' \dontrun{ +#' installOpenCV() +#' } +#' +#' @export +removeOpenCV <- function() { + if (isOpenCVInstalled()) { + uninstall <- utils::menu(c("yes", "no"), title = "Would you like to completely remove OpenCV from your R installation? You can reinstall it at any time by using the installOpenCV() function.") + print(uninstall) + + if (uninstall == 1) { + unlink(OpenCVPath(), recursive = TRUE) + !isOpenCVInstalled() + } else { + !isOpenCVInstalled() + } + } else { + message("OpenCV is not installed on this system. Nothing to be done.") + !isOpenCVInstalled() + } +} \ No newline at end of file diff --git a/R/opencv.R b/R/opencv.R deleted file mode 100644 index 5042c7f..0000000 --- a/R/opencv.R +++ /dev/null @@ -1,464 +0,0 @@ -#' @title Default Install Location of OpenCV -#' -#' @description This function returns the location at which OpenCV should be -#' installed by default. -#' -#' @return A character string. -#' -#' @author Simon Garnier, \email{garnier@@njit.edu} -#' -#' @examples -#' \dontrun{ -#' defaultOpenCVPath() -#' } -#' -#' @export -defaultOpenCVPath <- function() { - pkgPath <- find.package("ROpenCVLite") - paste0(gsub("ROpenCVLite", "", pkgPath), "ROpenCV") -} - - -#' @title Install Location of OpenCV -#' -#' @description This function returns the location at which OpenCV is installed. -#' -#' @return A character string. -#' -#' @author Simon Garnier, \email{garnier@@njit.edu} -#' -#' @examples -#' \dontrun{ -#' OpenCVPath() -#' } -#' -#' @export -OpenCVPath <- function() { - pkgPath <- find.package("ROpenCVLite") - - if (file.exists(paste0(pkgPath, "/path"))) { - path <- readLines(paste0(pkgPath, "/path"), 1) - } else { - path <- character() - } - - if (length(path) == 0) - path <- defaultOpenCVPath() - - if (dir.exists(paste0(path, "/include/"))) { - path - } else { - stop("OpenCV is not installed on this system. Please use installOpenCV() to install it.") - } -} - - -#' @title Check OpenCV Installation -#' -#' @description This function checks that OpenCV is installed and accessible. -#' -#' @return A boolean. -#' -#' @author Simon Garnier, \email{garnier@@njit.edu} -#' -#' @examples -#' isOpenCVInstalled() -#' -#' @export -isOpenCVInstalled <- function() { - path <- try(OpenCVPath(), silent = TRUE) - - if (inherits(path, "try-error")) { - FALSE - } else { - dir.exists(paste0(path, "/include/")) - } -} - - -#' @title Check Cmake Installation -#' -#' @description This function checks that Cmake is installed on the system. -#' -#' @return A boolean. -#' -#' @author Simon Garnier, \email{garnier@@njit.edu} -#' -#' @examples -#' isCmakeInstalled() -#' -#' @export -isCmakeInstalled <- function() { - cmake <- system("cmake --version", ignore.stdout = TRUE) == 0 - - if (cmake) { - cmake - } else { - cat("------------------ CMAKE NOT FOUND --------------------\n") - cat("\n") - cat("CMake was not found on the PATH. Please install CMake:\n") - cat("\n") - cat(" - installr::install.cmake() (Windows; inside the R console)\n") - cat(" - yum install cmake (Fedora/CentOS; inside a terminal)\n") - cat(" - apt install cmake (Debian/Ubuntu; inside a terminal)\n") - cat(" - brew install cmake (MacOS; inside a terminal with Homebrew)\n") - cat(" - port install cmake (MacOS; inside a terminal with MacPorts)\n") - cat("\n") - cat("Alternatively install CMake from: \n") - cat("\n") - cat("-------------------------------------------------------\n") - cat("\n") - cmake - } -} - - -#' @title Install OpenCV -#' -#' @description This function attempts to download, compile and install OpenCV -#' on the system. This process will take several minutes. -#' -#' @param path A character string indicating the location at which OpenCV should -#' be installed. By default, it is the value returned by -#' \code{\link{defaultOpenCVPath}}. -#' -#' @param batch A boolean indicating whether to skip (\code{TRUE}) or not -#' (\code{FALSE}, the default) the interactive installation dialog. This is -#' useful when OpenCV needs to be installed in a non-interactive environment -#' (e.g., during a batch installation on a server). -#' -#' @return A boolean. -#' -#' @author Simon Garnier, \email{garnier@@njit.edu} -#' -#' @examples -#' \dontrun{ -#' installOpenCV() -#' } -#' -#' @export -installOpenCV <- function(path = defaultOpenCVPath(), batch = FALSE) { - install <- 0 - path <- normalizePath(path, mustWork = FALSE) - - if (interactive()) { - if (isOpenCVInstalled()) { - pkgVersion <- paste0(strsplit(as.character(utils::packageVersion("ROpenCVLite")), "\\.")[[1]][1:2], collapse = "") - cvVersion <- gsub("\\D+", "", opencvVersion()) - - if (pkgVersion == cvVersion) { - install <- utils::menu(c("yes", "no"), title = "OpenCV is already installed on this system. Would you like to reinstall it now? This will take several minutes.") - } else { - install <- utils::menu(c("yes", "no"), title = "A new version of OpenCV is available. Would you like to install it now? This will take several minutes.") - } - } else { - install <- utils::menu(c("yes", "no"), title = "OpenCV is not installed on this system. Would you like to install it now? This will take several minutes.") - } - } else { - if (batch) { - packageStartupMessage("OpenCV being installed in non-interactive mode!") - install <- 1 - } else { - packageStartupMessage("OpenCV can only be installed in interactive mode. To override this in a non-interactive context, use installOpenCV(batch = TRUE).") - } - } - - if (!isCmakeInstalled()) - install <- 0 - - if (install == 1) { - pkgPath <- find.package("ROpenCVLite") - message(paste0("OpenCV will be installed in ", path)) - old <- try(OpenCVPath(), silent = TRUE) - - if (dir.exists(path)) { - message("Clearing install path.") - unlink(path, recursive = TRUE) - } - - if (inherits(path, "try-error")) { - if (dir.exists(old)) { - message("Removing old OpenCV installation.") - unlink(old, recursive = TRUE) - } - } - - # Sys.setenv(CXX_STD = "CXX11") - - if (.Platform$OS.type == "windows") { - dir.create(path, showWarnings = FALSE) - tmpDir <- gsub("\\\\", "/", base::tempdir()) - dir.create(tmpDir, showWarnings = FALSE) - - utils::download.file("https://github.com/opencv/opencv/archive/4.8.0.tar.gz", - paste0(tmpDir, "/opencv-4.8.0.tar.gz")) - utils::untar(paste0(tmpDir, "/opencv-4.8.0.tar.gz"), - exdir = tmpDir) - - utils::download.file("https://github.com/opencv/opencv_contrib/archive/4.8.0.tar.gz", - paste0(tmpDir, "/opencv_contrib-4.8.0.tar.gz")) - utils::untar(paste0(tmpDir, "/opencv_contrib-4.8.0.tar.gz"), - exdir = tmpDir) - - arch <- c("64", "32") - archAvail <- c(dir.exists(paste0(R.home(), "/bin/x64")), - dir.exists(paste0(R.home(), "/bin/i386"))) - - if (any(archAvail)) { - if (R.Version()$major >= "4") { - rtools4 <- TRUE - rtools4Path <- gsub("\\\\", "/", gsub("/usr/bin", "", pkgbuild::rtools_path()[1])) - } else { - rtools4 <- FALSE - chk_rtools <- utils::capture.output(pkgbuild::check_rtools(debug = TRUE)) - rtoolsPath <- gsub(" ", "", gsub("install_path: ", "", chk_rtools[grepl("install_path", chk_rtools)])) - } - - for (i in 1:2) { - if (archAvail[i] == TRUE) { - sourceDir <- paste0(tmpDir, "/opencv-4.8.0/") - contribDir <- paste0(tmpDir, "/opencv_contrib-4.8.0/modules") - buildDir <- paste0(sourceDir, "build", arch[i]) - dir.create(buildDir, showWarnings = FALSE) - openCVArch <- if (arch[i] == 64) "x64" else "x86" - - if (rtools4) { - if (!grepl("40", pkgbuild::rtools_path())) { - if (openCVArch == "x64") { - gcc_path <- paste0(rtools4Path, "/x86_64-w64-mingw32.static.posix", "/bin/gcc.exe") - gpp_path <- paste0(rtools4Path, "/x86_64-w64-mingw32.static.posix", "/bin/g++.exe") - windres_path <- paste0(rtools4Path, "/x86_64-w64-mingw32.static.posix", "/bin/windres.exe") - make_path <- paste0(rtools4Path, "/usr/bin/make.exe") - system(paste0('cmake -G "Unix Makefiles" -DCMAKE_C_COMPILER=', gcc_path, ' -DCMAKE_CXX_COMPILER=', gpp_path, ' -DCMAKE_RC_COMPILER=', windres_path, ' -DCMAKE_MAKE_PROGRAM=', make_path, ' -DENABLE_PRECOMPILED_HEADERS=OFF -DOpenCV_ARCH=', openCVArch, ' -DOpenCV_RUNTIME=mingw -DBUILD_ZLIB=ON -DOPENCV_EXTRA_MODULES_PATH=', contribDir, ' -DBUILD_LIST=calib3d,core,dnn,features2d,flann,gapi,highgui,imgcodecs,imgproc,ml,objdetect,photo,stitching,video,videoio,ximgproc -DBUILD_opencv_world=OFF -DBUILD_opencv_contrib_world=OFF -DWITH_OPENMP=ON -DWITH_TBB=ON -DWITH_FFMPEG=ON -DWITH_OPENCL=ON -DWITH_EIGEN=ON -DWITH_OPENCLAMDFFT=ON -DWITH_OPENCLAMDBLAS=ON -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DWITH_DSHOW=ON -DBUILD_PROTOBUF=ON -DOPENCV_ENABLE_ALLOCATOR_STATS=OFF -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=RELEASE -DCPU_DISPATCH=SSE4_1,SSE4_2,FP16,AVX -DCMAKE_C_FLAGS_RELEASE="-fstack-protector" -DCMAKE_CXX_FLAGS_RELEASE="-fstack-protector" -DCMAKE_INSTALL_PREFIX=', path, ' -B', buildDir, ' -H', sourceDir)) - system(paste0(make_path, " -j", parallel::detectCores(), " -C ", buildDir)) - system(paste0(make_path, " -C", buildDir, " install")) - } else { - message("RTools >= 4.2 does not support 32bit builds. Skipping compilation for this architecture.") - } - } else { - gcc_path <- paste0(rtools4Path, "/mingw", arch[i], "/bin/gcc.exe") - gpp_path <- paste0(rtools4Path, "/mingw", arch[i], "/bin/g++.exe") - windres_path <- paste0(rtools4Path, "/mingw", arch[i], "/bin/windres.exe") - make_path <- paste0(rtools4Path, "/usr/bin/make.exe") - system(paste0('cmake -G "Unix Makefiles" -DCMAKE_C_COMPILER=', gcc_path, ' -DCMAKE_CXX_COMPILER=', gpp_path, ' -DCMAKE_RC_COMPILER=', windres_path, ' -DCMAKE_MAKE_PROGRAM=', make_path, ' -DENABLE_PRECOMPILED_HEADERS=OFF -DOpenCV_ARCH=', openCVArch, ' -DOpenCV_RUNTIME=mingw -DBUILD_ZLIB=ON -DOPENCV_EXTRA_MODULES_PATH=', contribDir, ' -DBUILD_LIST=calib3d,core,dnn,features2d,flann,gapi,highgui,imgcodecs,imgproc,ml,objdetect,photo,stitching,video,videoio,ximgproc -DBUILD_opencv_world=OFF -DBUILD_opencv_contrib_world=OFF -DWITH_OPENMP=ON -DWITH_TBB=ON -DWITH_FFMPEG=ON -DWITH_OPENCL=ON -DWITH_EIGEN=ON -DWITH_OPENCLAMDFFT=ON -DWITH_OPENCLAMDBLAS=ON -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DWITH_DSHOW=ON -DBUILD_PROTOBUF=OFF -DOPENCV_ENABLE_ALLOCATOR_STATS=OFF -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=', path, ' -B', buildDir, ' -H', sourceDir)) - system(paste0(make_path, " -j", parallel::detectCores(), " -C ", buildDir)) - system(paste0(make_path, " -C", buildDir, " install")) - } - } else { - gcc_path <- paste0(rtoolsPath, "/mingw_", arch[i], "/bin/gcc.exe") - gpp_path <- paste0(rtoolsPath, "/mingw_", arch[i], "/bin/g++.exe") - windres_path <- paste0(rtoolsPath, "/mingw_", arch[i], "/bin/windres.exe") - make_path <- paste0(rtoolsPath, "/mingw_", arch[i], "/bin/mingw32-make.exe") - system(paste0('cmake -G "Unix Makefiles" -DCMAKE_C_COMPILER=', gcc_path, ' -DCMAKE_CXX_COMPILER=', gpp_path, ' -DCMAKE_RC_COMPILER=', windres_path, ' -DCMAKE_MAKE_PROGRAM=', make_path, ' -DENABLE_PRECOMPILED_HEADERS=OFF -DOpenCV_ARCH=', openCVArch, ' -DOpenCV_RUNTIME=mingw -DBUILD_ZLIB=ON -DOPENCV_EXTRA_MODULES_PATH=', contribDir, ' -DBUILD_LIST=calib3d,core,dnn,features2d,flann,highgui,imgcodecs,imgproc,ml,objdetect,photo,stitching,video,videoio,ximgproc -DBUILD_opencv_world=OFF -DBUILD_opencv_contrib_world=OFF -DWITH_OPENMP=ON -DWITH_TBB=ON -DWITH_FFMPEG=ON -DWITH_OPENCL=ON -DWITH_EIGEN=ON -DWITH_OPENCLAMDFFT=ON -DWITH_OPENCLAMDBLAS=ON -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DWITH_DSHOW=ON -DBUILD_PROTOBUF=OFF -DOPENCV_ENABLE_ALLOCATOR_STATS=OFF -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=', path, ' -B', buildDir, ' -H', sourceDir)) - system(paste0(make_path, " -j", parallel::detectCores(), " -C ", buildDir)) - system(paste0(make_path, " -C", buildDir, " install")) - } - } - } - } - } else { - dir.create(path, showWarnings = FALSE) - tmpDir <- base::tempdir() - dir.create(tmpDir, showWarnings = FALSE) - - utils::download.file("https://github.com/opencv/opencv/archive/4.8.0.zip", - paste0(tmpDir, "/opencv-4.8.0.zip")) - utils::unzip(paste0(tmpDir, "/opencv-4.8.0.zip"), - exdir = tmpDir) - - utils::download.file("https://github.com/opencv/opencv_contrib/archive/4.8.0.zip", - paste0(tmpDir, "/opencv_contrib-4.8.0.zip")) - utils::unzip(paste0(tmpDir, "/opencv_contrib-4.8.0.zip"), - exdir = tmpDir) - - file.copy(paste0(pkgPath, "/OpenCVModule.4.8.0.cmake"), - paste0(tmpDir, "/opencv-4.8.0/cmake/OpenCVModule.cmake"), - overwrite = TRUE) - - sourceDir <- paste0(tmpDir, "/opencv-4.8.0/") - contribDir <- paste0(tmpDir, "/opencv_contrib-4.8.0/modules") - buildDir <- paste0(sourceDir, "build") - dir.create(buildDir, showWarnings = FALSE) - - if (grepl("Apple clang", system("c++ --version", intern = TRUE))[1]) { - system(paste0("cmake -DOPENCV_EXTRA_MODULES_PATH=", contribDir, " -DBUILD_LIST=calib3d,core,dnn,features2d,flann,gapi,highgui,imgcodecs,imgproc,ml,objdetect,photo,stitching,video,videoio,ximgproc -DBUILD_opencv_world=OFF -DBUILD_opencv_contrib_world=OFF -DWITH_IPP=ON -DWITH_TBB=ON -DWITH_FFMPEG=ON -DWITH_AVFOUNDATION=ON -DWITH_OPENCL=ON -DWITH_EIGEN=ON -DWITH_OPENCLAMDFFT=ON -DWITH_OPENCLAMDBLAS=ON -D BUILD_ZLIB=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DINSTALL_CREATE_DISTRIB=ON -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=", path, " -B", buildDir, ' -H', sourceDir)) - } else { - arch <- system("uname -m", intern = TRUE) - if (grepl("aarch", arch) | grepl("arm", arch)) { - system(paste0("cmake -DOPENCV_EXTRA_MODULES_PATH=", contribDir, " -DBUILD_LIST=calib3d,core,dnn,features2d,flann,gapi,highgui,imgcodecs,imgproc,ml,objdetect,photo,stitching,video,videoio,ximgproc -DBUILD_opencv_world=OFF -DBUILD_opencv_contrib_world=OFF -DWITH_IPP=OFF -DWITH_OPENMP=ON -DWITH_TBB=ON -DWITH_FFMPEG=ON -DWITH_V4L=ON -DWITH_OPENCL=ON -DWITH_EIGEN=ON -DWITH_OPENCLAMDFFT=ON -DWITH_OPENCLAMDBLAS=ON -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DINSTALL_CREATE_DISTRIB=ON -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=", path, " -B", buildDir, ' -H', sourceDir)) - } else { - system(paste0("cmake -DOPENCV_EXTRA_MODULES_PATH=", contribDir, " -DBUILD_LIST=calib3d,core,dnn,features2d,flann,gapi,highgui,imgcodecs,imgproc,ml,objdetect,photo,stitching,video,videoio,ximgproc -DBUILD_opencv_world=OFF -DBUILD_opencv_contrib_world=OFF -DWITH_IPP=ON -DWITH_OPENMP=ON -DWITH_TBB=ON -DWITH_FFMPEG=ON -DWITH_V4L=ON -DWITH_OPENCL=ON -DWITH_EIGEN=ON -DWITH_OPENCLAMDFFT=ON -DWITH_OPENCLAMDBLAS=ON -DBUILD_PERF_TESTS=OFF -DBUILD_TESTS=OFF -DINSTALL_CREATE_DISTRIB=ON -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=", path, " -B", buildDir, ' -H', sourceDir)) - } - } - - system(paste0("make -j", parallel::detectCores(), " -C ", buildDir)) - system(paste0("make -C ", buildDir, " all install")) - } - - writeLines(path, con = paste0(pkgPath, "/path")) - } else { - packageStartupMessage("OpenCV was not installed at this time. You can install it at any time by using the installOpenCV() function.") - } - - isOpenCVInstalled() -} - - -#' @title Remove OpenCV -#' -#' @description This function removes OpenCV from the system. -#' -#' @return A boolean. -#' -#' @author Simon Garnier, \email{garnier@@njit.edu} -#' -#' @examples -#' \dontrun{ -#' installOpenCV() -#' } -#' -#' @export -removeOpenCV <- function() { - if (isOpenCVInstalled()) { - uninstall <- utils::menu(c("yes", "no"), title = "Would you like to completely remove OpenCV from your R installation? You can reinstall it at any time by using the installOpenCV() function.") - print(uninstall) - - if (uninstall == 1) { - unlink(OpenCVPath(), recursive = TRUE) - !isOpenCVInstalled() - } else { - !isOpenCVInstalled() - } - } else { - message("OpenCV is not installed on this system. Nothing to be done.") - !isOpenCVInstalled() - } -} - - -#' @title OpenCV Version -#' -#' @description This function determines the version of OpenCV installed within -#' R. -#' -#' @return A character string. -#' -#' @author Simon Garnier, \email{garnier@@njit.edu} -#' -#' @examples -#' if (isOpenCVInstalled()) { -#' opencvVersion() -#' } -#' -#' @export -opencvVersion <- function() { - if (isOpenCVInstalled()) { - if (.Platform$OS.type == "windows") { - pcPath <- "/OpenCVConfig-version.cmake" - pc <- utils::read.table(paste0(OpenCVPath(), pcPath), sep = "\t")[1, 1] - paste0("Version ", gsub(")", "", gsub(".*VERSION ", "", pc))) - } else { - odir <- dir(OpenCVPath()) - lib <- odir[grepl("lib", odir)] - pcPath <- paste0("/", lib, "/cmake/opencv4/OpenCVConfig-version.cmake") - pc <- utils::read.table(paste0(OpenCVPath(), pcPath), sep = "\t")[1, 1] - paste0("Version ", gsub(")", "", gsub(".*VERSION ", "", pc))) - } - } else { - stop("OpenCV is not installed on this system. Please use installOpenCV() to install it.") - } -} - - -#' @title C/C++ configuration options -#' -#' @description This function returns the configuration options for compiling -#' C/C++-based packages against OpenCV installed by \code{\link{ROpenCVLite}}. -#' -#' @param output Either 'libs' for library configuration options or 'cflags' for -#' C/C++ configuration flags. -#' -#' @param arch architecture relevant for Windows. If \code{NULL}, then -#' \code{R.version$arch} will be used. -#' -#' @return A concatenated character string (with \code{\link{cat}}) of the -#' configuration options. -#' -#' @author Simon Garnier, \email{garnier@@njit.edu} -#' -#' @examples -#' \dontrun{ -#' if (isOpenCVInstalled()) { -#' opencvConfig() -#' opencvConfig(output = "cflags") -#' opencvConfig(arch = R.version$arch) -#' } -#' } -#' -#' @export -opencvConfig <- function(output = "libs", arch = NULL) { - if (!isOpenCVInstalled()) - stop("OpenCV is not installed on this system. Please use installOpenCV() to install it.") - - prefix <- OpenCVPath() - - if (output == "libs") { - if (.Platform$OS.type == "windows") { - if (is.null(arch)) { - arch = R.version$arch - } - if (grepl("i386", arch)) { - execPrefix <- paste0(prefix, "/x86/mingw") - } else { - execPrefix <- paste0(prefix, "/x64/mingw") - } - libDir <- paste0(execPrefix, "/lib") - libs <- gsub("libopencv", "opencv", list.files(libDir, "lib*")) - libs <- gsub("\\.a", "", libs) - libs <- gsub("\\.dll", "", libs) - libs <- ifelse(substring(libs, 1, 3) == "lib", substring(libs, 4), libs) - libs <- paste0("-l", libs) - cat(paste0('-L"', utils::shortPathName(libDir), '"'), libs) - } else { - execPrefix <- prefix - odir <- dir(execPrefix) - lib <- odir[grepl("lib", odir)] - libDir <- paste0(execPrefix, "/", lib) - libs <- gsub("libopencv", "opencv", list.files(libDir, "lib*")) - libs <- gsub("\\.so", "", libs) - libs <- gsub("\\.dylib", "", libs) - libs <- libs[!grepl("\\.", libs)] - libs <- paste0("-l", libs) - if (Sys.info()[1] == "Darwin") { - cat(paste0("-L", libDir, " ", paste0(libs, collapse = " "))) - } else { - cat(paste0("-Wl,-rpath=", libDir, " ", "-L", libDir, " ", paste0(libs, collapse = " "))) - } - } - } else if (output == "cflags") { - if (.Platform$OS.type == "windows") { - includedirOld <- paste0(prefix, "/include/opencv2") - includedirNew <- paste0(prefix, "/include") - - if (is.null(arch)) { - arch = R.version$arch - } - if (grepl("i386", arch)) { - execdir <- paste0(prefix, "/x86/mingw/bin") - } else { - execdir <- paste0(prefix, "/x64/mingw/bin") - } - - cat(paste0('-I"', utils::shortPathName(includedirOld), '" -I"', - utils::shortPathName(includedirNew), '" -I"', - utils::shortPathName(execdir), '"')) - } else { - includedirOld <- paste0(prefix, "/include/opencv4") - includedirNew <- paste0(prefix, "/include") - - cat(paste0("-I", includedirOld, " -I", includedirNew)) - } - } else { - stop("output should be either 'libs' or 'cflags'") - } -} diff --git a/R/utils.R b/R/utils.R new file mode 100644 index 0000000..299045d --- /dev/null +++ b/R/utils.R @@ -0,0 +1,220 @@ +#' @title Install Location of OpenCV +#' +#' @description This function returns the location at which OpenCV is installed. +#' +#' @return A character string. +#' +#' @author Simon Garnier, \email{garnier@@njit.edu} +#' +#' @examples +#' \dontrun{ +#' OpenCVPath() +#' } +#' +#' @export +OpenCVPath <- function() { + pkgPath <- find.package("ROpenCVLite") + + if (file.exists(paste0(pkgPath, "/path"))) { + path <- readLines(paste0(pkgPath, "/path"), 1) + } else { + path <- character() + } + + if (length(path) == 0) + path <- defaultOpenCVPath() + + if (dir.exists(paste0(path, "/include/"))) { + path + } else { + stop("OpenCV is not installed on this system. Please use installOpenCV() to install it.") + } +} + + +#' @title Check OpenCV Installation +#' +#' @description This function checks that OpenCV is installed and accessible. +#' +#' @return A boolean. +#' +#' @author Simon Garnier, \email{garnier@@njit.edu} +#' +#' @examples +#' isOpenCVInstalled() +#' +#' @export +isOpenCVInstalled <- function() { + path <- try(OpenCVPath(), silent = TRUE) + + if (inherits(path, "try-error")) { + FALSE + } else { + dir.exists(paste0(path, "/include/")) + } +} + + +#' @title Check Cmake Installation +#' +#' @description This function checks that Cmake is installed on the system. +#' +#' @return A boolean. +#' +#' @author Simon Garnier, \email{garnier@@njit.edu} +#' +#' @examples +#' isCmakeInstalled() +#' +#' @export +isCmakeInstalled <- function() { + cmake <- system("cmake --version", ignore.stdout = TRUE) == 0 + + if (cmake) { + cmake + } else { + cat("------------------ CMAKE NOT FOUND --------------------\n") + cat("\n") + cat("CMake was not found on the PATH. Please install CMake:\n") + cat("\n") + cat(" - installr::install.cmake() (Windows; inside the R console)\n") + cat(" - yum install cmake (Fedora/CentOS; inside a terminal)\n") + cat(" - apt install cmake (Debian/Ubuntu; inside a terminal)\n") + cat(" - brew install cmake (MacOS; inside a terminal with Homebrew)\n") + cat(" - port install cmake (MacOS; inside a terminal with MacPorts)\n") + cat("\n") + cat("Alternatively install CMake from: \n") + cat("\n") + cat("-------------------------------------------------------\n") + cat("\n") + cmake + } +} + + +#' @title OpenCV Version +#' +#' @description This function determines the version of OpenCV installed within +#' R. +#' +#' @return A character string. +#' +#' @author Simon Garnier, \email{garnier@@njit.edu} +#' +#' @examples +#' if (isOpenCVInstalled()) { +#' opencvVersion() +#' } +#' +#' @export +opencvVersion <- function() { + if (isOpenCVInstalled()) { + if (.Platform$OS.type == "windows") { + pcPath <- "/OpenCVConfig-version.cmake" + pc <- utils::read.table(paste0(OpenCVPath(), pcPath), sep = "\t")[1, 1] + paste0("Version ", gsub(")", "", gsub(".*VERSION ", "", pc))) + } else { + odir <- dir(OpenCVPath()) + lib <- odir[grepl("lib", odir)] + pcPath <- paste0("/", lib, "/cmake/opencv4/OpenCVConfig-version.cmake") + pc <- utils::read.table(paste0(OpenCVPath(), pcPath), sep = "\t")[1, 1] + paste0("Version ", gsub(")", "", gsub(".*VERSION ", "", pc))) + } + } else { + stop("OpenCV is not installed on this system. Please use installOpenCV() to install it.") + } +} + + +#' @title C/C++ configuration options +#' +#' @description This function returns the configuration options for compiling +#' C/C++-based packages against OpenCV installed by \code{\link{ROpenCVLite}}. +#' +#' @param output Either 'libs' for library configuration options or 'cflags' for +#' C/C++ configuration flags. +#' +#' @param arch architecture relevant for Windows. If \code{NULL}, then +#' \code{R.version$arch} will be used. +#' +#' @return A concatenated character string (with \code{\link{cat}}) of the +#' configuration options. +#' +#' @author Simon Garnier, \email{garnier@@njit.edu} +#' +#' @examples +#' \dontrun{ +#' if (isOpenCVInstalled()) { +#' opencvConfig() +#' opencvConfig(output = "cflags") +#' opencvConfig(arch = R.version$arch) +#' } +#' } +#' +#' @export +opencvConfig <- function(output = "libs", arch = NULL) { + if (!isOpenCVInstalled()) + stop("OpenCV is not installed on this system. Please use installOpenCV() to install it.") + + prefix <- OpenCVPath() + + if (output == "libs") { + if (.Platform$OS.type == "windows") { + if (is.null(arch)) { + arch = R.version$arch + } + if (grepl("i386", arch)) { + execPrefix <- paste0(prefix, "/x86/mingw") + } else { + execPrefix <- paste0(prefix, "/x64/mingw") + } + libDir <- paste0(execPrefix, "/lib") + libs <- gsub("libopencv", "opencv", list.files(libDir, "lib*")) + libs <- gsub("\\.a", "", libs) + libs <- gsub("\\.dll", "", libs) + libs <- ifelse(substring(libs, 1, 3) == "lib", substring(libs, 4), libs) + libs <- paste0("-l", libs) + cat(paste0('-L"', utils::shortPathName(libDir), '"'), libs) + } else { + execPrefix <- prefix + odir <- dir(execPrefix) + lib <- odir[grepl("lib", odir)] + libDir <- paste0(execPrefix, "/", lib) + libs <- gsub("libopencv", "opencv", list.files(libDir, "lib*")) + libs <- gsub("\\.so", "", libs) + libs <- gsub("\\.dylib", "", libs) + libs <- libs[!grepl("\\.", libs)] + libs <- paste0("-l", libs) + if (Sys.info()[1] == "Darwin") { + cat(paste0("-L", libDir, " ", paste0(libs, collapse = " "))) + } else { + cat(paste0("-Wl,-rpath=", libDir, " ", "-L", libDir, " ", paste0(libs, collapse = " "))) + } + } + } else if (output == "cflags") { + if (.Platform$OS.type == "windows") { + includedirOld <- paste0(prefix, "/include/opencv2") + includedirNew <- paste0(prefix, "/include") + + if (is.null(arch)) { + arch = R.version$arch + } + if (grepl("i386", arch)) { + execdir <- paste0(prefix, "/x86/mingw/bin") + } else { + execdir <- paste0(prefix, "/x64/mingw/bin") + } + + cat(paste0('-I"', utils::shortPathName(includedirOld), '" -I"', + utils::shortPathName(includedirNew), '" -I"', + utils::shortPathName(execdir), '"')) + } else { + includedirOld <- paste0(prefix, "/include/opencv4") + includedirNew <- paste0(prefix, "/include") + + cat(paste0("-I", includedirOld, " -I", includedirNew)) + } + } else { + stop("output should be either 'libs' or 'cflags'") + } +} diff --git a/man/OpenCVPath.Rd b/man/OpenCVPath.Rd index c845359..cb09378 100644 --- a/man/OpenCVPath.Rd +++ b/man/OpenCVPath.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/opencv.R +% Please edit documentation in R/utils.R \name{OpenCVPath} \alias{OpenCVPath} \title{Install Location of OpenCV} diff --git a/man/defaultOpenCVPath.Rd b/man/defaultOpenCVPath.Rd index d3c4beb..21aecbc 100644 --- a/man/defaultOpenCVPath.Rd +++ b/man/defaultOpenCVPath.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/opencv.R +% Please edit documentation in R/install.R \name{defaultOpenCVPath} \alias{defaultOpenCVPath} \title{Default Install Location of OpenCV} diff --git a/man/installOpenCV.Rd b/man/installOpenCV.Rd index 7593e8e..eaa90d7 100644 --- a/man/installOpenCV.Rd +++ b/man/installOpenCV.Rd @@ -1,14 +1,14 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/opencv.R +% Please edit documentation in R/install.R \name{installOpenCV} \alias{installOpenCV} \title{Install OpenCV} \usage{ -installOpenCV(path = defaultOpenCVPath(), batch = FALSE) +installOpenCV(install_path = defaultOpenCVPath(), batch = FALSE) } \arguments{ -\item{path}{A character string indicating the location at which OpenCV should -be installed. By default, it is the value returned by +\item{install_path}{A character string indicating the location at which +OpenCV should be installed. By default, it is the value returned by \code{\link{defaultOpenCVPath}}.} \item{batch}{A boolean indicating whether to skip (\code{TRUE}) or not diff --git a/man/isCmakeInstalled.Rd b/man/isCmakeInstalled.Rd index d393785..b780566 100644 --- a/man/isCmakeInstalled.Rd +++ b/man/isCmakeInstalled.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/opencv.R +% Please edit documentation in R/utils.R \name{isCmakeInstalled} \alias{isCmakeInstalled} \title{Check Cmake Installation} diff --git a/man/isOpenCVInstalled.Rd b/man/isOpenCVInstalled.Rd index b310ebd..7f1bd4e 100644 --- a/man/isOpenCVInstalled.Rd +++ b/man/isOpenCVInstalled.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/opencv.R +% Please edit documentation in R/utils.R \name{isOpenCVInstalled} \alias{isOpenCVInstalled} \title{Check OpenCV Installation} diff --git a/man/opencvConfig.Rd b/man/opencvConfig.Rd index b51dd08..212649d 100644 --- a/man/opencvConfig.Rd +++ b/man/opencvConfig.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/opencv.R +% Please edit documentation in R/utils.R \name{opencvConfig} \alias{opencvConfig} \title{C/C++ configuration options} diff --git a/man/opencvVersion.Rd b/man/opencvVersion.Rd index bd53210..e9fff5a 100644 --- a/man/opencvVersion.Rd +++ b/man/opencvVersion.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/opencv.R +% Please edit documentation in R/utils.R \name{opencvVersion} \alias{opencvVersion} \title{OpenCV Version} diff --git a/man/removeOpenCV.Rd b/man/removeOpenCV.Rd index c4b0e5f..9c75495 100644 --- a/man/removeOpenCV.Rd +++ b/man/removeOpenCV.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/opencv.R +% Please edit documentation in R/install.R \name{removeOpenCV} \alias{removeOpenCV} \title{Remove OpenCV}