Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #41

Merged
merged 17 commits into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ revdep
^docs$
^pkgdown$
^codecov\.yml$
test_install
6 changes: 3 additions & 3 deletions CRAN-SUBMISSION
Original file line number Diff line number Diff line change
@@ -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
8 changes: 5 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -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.90.0
Date: 2023-12-31
Authors@R: c(
person("Simon", "Garnier", email = "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-3886-3974")),
Expand All @@ -23,8 +23,10 @@ Imports:
SystemRequirements:
cmake
RoxygenNote: 7.2.3
Biarch: true
Biarch: false
Encoding: UTF-8
Depends:
R (>= 4.0.0)
Suggests:
covr,
knitr,
Expand Down
16 changes: 15 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# ROpenCVLite 4.80.0
# ROpenCVLite 4.90.0

## New features

* Upgrade package to OpenCV 4.9.0.
* Remove support for R < 4.0.0.

## Minor improvements and fixes

* Add compilation flags required to avoid errors on Windows 11.
* Overhaul of the installation functions for easier update management.

---

# ROpenCVLite 4.80.1

## New features

Expand Down
286 changes: 286 additions & 0 deletions R/install.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
#' @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$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$install_path <- utils::shortPathName(install_path)
config$pkg_path <- utils::shortPathName(find.package("ROpenCVLite"))
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 <- utils::shortPathName(pkgbuild::rtools_path()[1])

if (is.null(config$rtools_path))
stop("Rtools is missing.")

config$rtools_path <- gsub("\\\\usr\\\\bin", "", config$rtools_path)
config$rtools_version <- system(
paste0("powershell (Get-Item ", config$rtools_path, "/unins000.exe).VersionInfo.ProductVersion"),
intern = TRUE)
config$rtools_version <- gsub(" ", "", config$rtools_version)

if (is.na(config$rtools_version))
stop("Unsupported Rtools version.")

if (config$rtools_version < "4.2") {
config$cmake_path <- utils::shortPathName(system("where cmake.exe", intern = TRUE))

if (length(config$cmake_path) > 1) {
v <- sapply(config$cmake_path, function(cmake) gsub("cmake version ", "", system(paste0(cmake, " --version"), intern = TRUE)[1]))
config$cmake_path <- config$cmake_path[which(v == max(v))]
}

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")
}

config$tmp_dir <- 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")
} else if (config$os_type == "unix") {
config$install_path <- install_path
config$pkg_path <- find.package("ROpenCVLite")
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)
config$tmp_dir <- 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")
} else {
stop("Unsupported OS type.")
}

ix <- grepl("path", names(config)) | grepl("dir", names(config))
config[ix] <- lapply(config[ix], normalizePath, mustWork = FALSE, winslash = "/")
config
}


.cmake <- function(config) {
paste0(
'"', config$cmake_path, '"',
' -G "Unix Makefiles"',
' -Wno-dev',
' -DCMAKE_C_COMPILER="', config$gcc_path, '"',
' -DCMAKE_CXX_COMPILER="', config$gpp_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, '"',
' -DCMAKE_CXX_STANDARD=11',
' -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',
' -DWITH_OPENMP=ON',
' -DWITH_TBB=ON',
' -DWITH_EIGEN=ON',
' -DWITH_LAPACK=ON',
' -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"))
}

dir.create(config$build_dir, showWarnings = FALSE)
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()
}
}
Loading
Loading