From 1311b4abe859a53bbaea09611fa7abac9861c910 Mon Sep 17 00:00:00 2001 From: Nic Date: Thu, 26 Oct 2023 12:39:02 +0200 Subject: [PATCH 01/22] Update line_segment_detector.R Adapted the code to work with SpatRaster from the terra package and added the possibility to output the lines as an sf object. There's a horrible workaround to solve a transpostion of the data along the second axi but couldn't find a better alternative. Overall, it works smoothly and fast even with high resolution aerial images (tested on 1km tiles with 0.15 cm pixels) --- .../R/line_segment_detector.R | 81 ++++++++++++++++++- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/image.LineSegmentDetector/R/line_segment_detector.R b/image.LineSegmentDetector/R/line_segment_detector.R index f3a1025..1c38674 100644 --- a/image.LineSegmentDetector/R/line_segment_detector.R +++ b/image.LineSegmentDetector/R/line_segment_detector.R @@ -30,6 +30,7 @@ #' @param union_ang_th Numeric value with angle threshold in order to union #' @param union_use_NFA Logical indicating to use NFA to union #' @param union_log_eps Detection threshold to union +#' @param export_sf Boolean. Set to TRUE to export lines as sf spatial objects (WARNING: process may take several time) #' @return an object of class lsd which is a list with the following elements #' \itemize{ #' \item{n: }{The number of found line segments} @@ -78,13 +79,27 @@ #' mat <- drop(mat) #' linesegments <- image_line_segment_detector(mat) #' plot(linesegments, lwd = 2) + + image_line_segment_detector <- function(x, scale = 0.8, - sigma_scale = 0.6, quant = 2.0, ang_th = 22.5, log_eps = 0.0, - density_th = 0.7, n_bins = 1024, - union = FALSE, union_min_length = 5, union_max_distance = 5, - union_ang_th=7, union_use_NFA=FALSE, union_log_eps = 0.0) { + sigma_scale = 0.6, quant = 2.0, ang_th = 22.5, log_eps = 0.0, + density_th = 0.7, n_bins = 1024, + union = FALSE, union_min_length = 5, union_max_distance = 5, + union_ang_th=7, union_use_NFA=FALSE, union_log_eps = 0.0, + export_sf=FALSE ){ + UseMethod("image_line_segment_detector") + } +#' @export +image_line_segment_detector.matrix <- function(x, scale = 0.8, + sigma_scale = 0.6, quant = 2.0, ang_th = 22.5, log_eps = 0.0, + density_th = 0.7, n_bins = 1024, + union = FALSE, union_min_length = 5, union_max_distance = 5, + union_ang_th=7, union_use_NFA=FALSE, union_log_eps = 0.0, + export_sf=FALSE ) { + + stopifnot(is.matrix(x)) linesegments <- detect_line_segments(as.numeric(x), X=nrow(x), @@ -107,6 +122,64 @@ image_line_segment_detector <- function(x, scale = 0.8, linesegments } + + +#' @export +image_line_segment_detector.SpatRaster <- function(x, scale = 0.8, + sigma_scale = 0.6, quant = 2.0, ang_th = 22.5, log_eps = 0.0, + density_th = 0.7, n_bins = 1024, + union = FALSE, union_min_length = 5, union_max_distance = 5, + union_ang_th=7, union_use_NFA=FALSE, union_log_eps = 0.0, + export_sf=FALSE ){ + requireNamespace("terra") + uprightX = terra::ext(x)[2] + uprightY = terra::ext(x)[4] + resol = terra::res(x)[1] + + x = t(terra::as.matrix(x,wide=TRUE)) + + if( anyNA(x) ){ + x[is.na(x)] = 0 + warning("NA values found and set to 0") } + + linesegments = image_line_segment_detector.matrix(x, scale = scale, + sigma_scale = sigma_scale, quant = quant, ang_th = ang_th, log_eps = log_eps, + density_th = density_th, n_bins = n_bins, + union = union, union_min_length = union_min_length, union_max_distance = union_max_distance, + union_ang_th=union_ang_th, union_use_NFA=union_use_NFA, union_log_eps = union_log_eps, + export_sf=export_sf ) + + linesegments = as.data.frame(linesegments$lines) + + # assign spatial coordinates + linesegments$x1 = linesegments$x1 * -resol + uprightY + linesegments$y1 = linesegments$y1 * -resol + uprightX + linesegments$x2 = linesegments$x2 * -resol + uprightY + linesegments$y2 = linesegments$y2 * -resol + uprightX + + + # export object as sf + if(isTRUE(export_sf)){ + requireNamespace("sf") + + linesegments = apply(linesegments, 1, function(x) + { + v <- as.numeric(x[c(2,4,1,3)]) + m <- matrix(v, nrow = 2) + return(sf::st_sfc(sf::st_linestring(m), crs = NA_crs_)) + }) + print("Sf export in progress...") + linesegments = do.call(c, linesegments) + + linesegments = sf::st_sf(linesegments) + linesegments$line_ID = 1:nrow(linesegments) + linesegments$length_m = sf::st_length(linesegments) + } + + return(linesegments) +} + + #' @export print.lsd <- function(x, ...){ cat("Line Segment Detector", sep = "\n") From c5694f2c38dd070048955c9342e277e684be06fc Mon Sep 17 00:00:00 2001 From: Nic Date: Fri, 3 Nov 2023 18:25:00 +0100 Subject: [PATCH 02/22] Update DESCRIPTION --- image.LineSegmentDetector/DESCRIPTION | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/image.LineSegmentDetector/DESCRIPTION b/image.LineSegmentDetector/DESCRIPTION index 5cb72a4..b3d537b 100644 --- a/image.LineSegmentDetector/DESCRIPTION +++ b/image.LineSegmentDetector/DESCRIPTION @@ -15,5 +15,7 @@ Imports: Rcpp (>= 0.12.8), sp LinkingTo: Rcpp Suggests: pixmap, - magick + magick, + sf, + terra RoxygenNote: 7.1.0 From b6bde8638a7517379906b8484d04ea68a7e12b32 Mon Sep 17 00:00:00 2001 From: Nic Date: Wed, 12 Jun 2024 09:50:23 +0200 Subject: [PATCH 03/22] Update contour_detector.R added SpatRaster method --- image.ContourDetector/R/contour_detector.R | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 5d1bee5..96db59d 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -122,6 +122,25 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, ...){ return(contourlines) } +#' @export +image_contour_detector.SpatRaster <- function(x, Q=2.0, ...){ + requireNamespace("terra") + minX = terra::ext(x)[1] + minY = terra::ext(x)[3] + resol = terra::res(x)[1] + x = terra::as.matrix(x, wide=TRUE) + + if( anyNA(x) ){ + x[is.na(x)] = 0 + warning("NA values found and set to 0") } + + contourlines = image_contour_detector.matrix(x, Q=Q) + + contourlines$data$x = contourlines$data$x * resol + minX + contourlines$data$y = contourlines$data$y * resol + minY + return(contourlines) +} + #' @export print.cld <- function(x, ...){ From 952d8d07be34497316d1d96c27292482372b61ac Mon Sep 17 00:00:00 2001 From: Nic Date: Wed, 12 Jun 2024 10:03:56 +0200 Subject: [PATCH 04/22] Update DESCRIPTION --- image.ContourDetector/DESCRIPTION | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/image.ContourDetector/DESCRIPTION b/image.ContourDetector/DESCRIPTION index e8c4ccf..8ae99d2 100644 --- a/image.ContourDetector/DESCRIPTION +++ b/image.ContourDetector/DESCRIPTION @@ -19,5 +19,7 @@ LinkingTo: Rcpp Suggests: pixmap, magick, - raster + raster, + sf, + terra RoxygenNote: 7.1.1 From 78d06a3e0a2ea14314e09c6dea476a013007ccd4 Mon Sep 17 00:00:00 2001 From: Nic Date: Wed, 12 Jun 2024 12:06:02 +0200 Subject: [PATCH 05/22] Update contour_detector.R --- image.ContourDetector/R/contour_detector.R | 35 +++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 96db59d..60fbe6c 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -11,6 +11,7 @@ #' an efficient algorithm is derived producing sub-pixel contours. #' @param x a matrix of image pixel values in the 0-255 range. #' @param Q numeric value with the pixel quantization step +#' @param export_sf Boolean. Set to TRUE to export lines as sf spatial objects (WARNING: process may take several time) #' @param ... further arguments, not used yet #' @return an object of class cld which is a list with the following elements #' \itemize{ @@ -70,8 +71,8 @@ #' \{ #' } #' \donttest{ -#' library(raster) -#' x <- raster(system.file("extdata", "landscape.tif", package="image.ContourDetector")) +#' library(terra) +#' x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetector")) #' #' contourlines <- image_contour_detector(x) #' image(x) @@ -81,12 +82,12 @@ #' \} #' # End of main if statement running only if the required packages are installed #' } -image_contour_detector <- function(x, Q=2.0, ...){ +image_contour_detector <- function(x, Q=2.0 export_sf=FALSE, ...){ UseMethod("image_contour_detector") } #' @export -image_contour_detector.matrix <- function(x, Q=2.0, ...){ +image_contour_detector.matrix <- function(x, Q=2.0, export_sf=FALSE, ...){ stopifnot(is.matrix(x)) contourlines <- detect_contours(x, X=nrow(x), @@ -104,7 +105,7 @@ image_contour_detector.matrix <- function(x, Q=2.0, ...){ } #' @export -image_contour_detector.RasterLayer <- function(x, Q=2.0, ...){ +image_contour_detector.RasterLayer <- function(x, Q=2.0, export_sf=FALSE, ...){ requireNamespace("raster") minX = raster::extent(x)[1] minY = raster::extent(x)[3] @@ -115,7 +116,7 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, ...){ x[is.na(x)] = 0 warning("NA values found and set to 0") } - contourlines = image_contour_detector.matrix(x, Q=Q) + contourlines = image_contour_detector.matrix(x, Q=Q, export_sf=export_sf) contourlines$data$x = contourlines$data$x * resol + minX contourlines$data$y = contourlines$data$y * resol + minY @@ -123,21 +124,33 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, ...){ } #' @export -image_contour_detector.SpatRaster <- function(x, Q=2.0, ...){ +image_contour_detector.SpatRaster <- function(x, Q=2.0, export_sf=FALSE, ...){ requireNamespace("terra") minX = terra::ext(x)[1] minY = terra::ext(x)[3] resol = terra::res(x)[1] - x = terra::as.matrix(x, wide=TRUE) + xmat = terra::as.matrix(x, wide=TRUE) - if( anyNA(x) ){ - x[is.na(x)] = 0 + if( anyNA(xmat) ){ + x[is.na(xmat)] = 0 warning("NA values found and set to 0") } - contourlines = image_contour_detector.matrix(x, Q=Q) + contourlines = image_contour_detector.matrix(xmat, Q=Q, export_sf=export_sf) contourlines$data$x = contourlines$data$x * resol + minX contourlines$data$y = contourlines$data$y * resol + minY + + # export object as sf + if(isTRUE(export_sf)){ + requireNamespace("sf") + + contourlines <- contourlines$data %>% + sf::st_as_sf(coords = c("x", "y"), crs = sf::st_crs(x) ) %>% + dplyr::group_by( curve ) %>% + dplyr::summarize(do_union=FALSE) %>% + sf::st_cast("LINESTRING") + contourlines$length_m = sf::st_length(contourlines) + } return(contourlines) } From 795b9d75db92e945dada49c4c74f472660ecb6e9 Mon Sep 17 00:00:00 2001 From: Nic Date: Wed, 12 Jun 2024 12:20:57 +0200 Subject: [PATCH 06/22] Update contour_detector.R --- image.ContourDetector/R/contour_detector.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 60fbe6c..045305c 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -64,10 +64,10 @@ #' } #' #' ## -#' ## working with a RasterLayer +#' ## working with a SpatRaster #' ## #' \dontshow{ -#' if(require(raster)) +#' if(require(terra)) #' \{ #' } #' \donttest{ From e373efea6966e1c89b43234b7191abce6a5ea32d Mon Sep 17 00:00:00 2001 From: Nic Date: Wed, 12 Jun 2024 12:21:31 +0200 Subject: [PATCH 07/22] Update line_segment_detector.R --- .../R/line_segment_detector.R | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/image.LineSegmentDetector/R/line_segment_detector.R b/image.LineSegmentDetector/R/line_segment_detector.R index 1c38674..573edb5 100644 --- a/image.LineSegmentDetector/R/line_segment_detector.R +++ b/image.LineSegmentDetector/R/line_segment_detector.R @@ -79,7 +79,26 @@ #' mat <- drop(mat) #' linesegments <- image_line_segment_detector(mat) #' plot(linesegments, lwd = 2) - +#' +#' ## +#' ## working with a SpatRaster +#' ## +#' \dontshow{ +#' if(require(terra)) +#' \{ +#' } +#' \donttest{ +#' library(terra) +#' x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetector")) +#' +#' linesegments <- image_line_segment_detector(x) +#' image(x) +#' plot(linesegments, add = TRUE, col = "blue", lwd = 10) +#' } +#' \dontshow{ +#' \} +#' # End of main if statement running only if the required packages are installed +#' } image_line_segment_detector <- function(x, scale = 0.8, sigma_scale = 0.6, quant = 2.0, ang_th = 22.5, log_eps = 0.0, From 5726149caf5edc2aac188676e7de065474a2b061 Mon Sep 17 00:00:00 2001 From: Nic Date: Wed, 12 Jun 2024 12:23:20 +0200 Subject: [PATCH 08/22] Update DESCRIPTION --- image.ContourDetector/DESCRIPTION | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/image.ContourDetector/DESCRIPTION b/image.ContourDetector/DESCRIPTION index 8ae99d2..2f1a3e0 100644 --- a/image.ContourDetector/DESCRIPTION +++ b/image.ContourDetector/DESCRIPTION @@ -9,7 +9,7 @@ Authors@R: c( person("BNOSAC", role = "cph", comment = "R wrapper"), person("Rafael Grompone von Gioi", role = c("ctb", "cph"), email = "grompone@gmail.com", comment = "src/smooth_contours"), person("Gregory Randall", role = c("ctb", "cph"), email = "randall@fing.edu.uy", comment = "src/smooth_contours"), - person("Niccolò Marchi", role = "ctb", email = "niccolo.marchi@unipd.it")) + person("Niccolò Marchi", role = "ctb", email = "sciurusurbanus@hotmail.it")) Encoding: UTF-8 License: AGPL-3 Version: 0.1.1 @@ -17,6 +17,7 @@ URL: https://github.com/bnosac/image Imports: Rcpp (>= 0.12.8), sp LinkingTo: Rcpp Suggests: + dplyr, pixmap, magick, raster, From f2eba9aa3f049e94431bf2f6aa15055e4708703f Mon Sep 17 00:00:00 2001 From: Nic Date: Wed, 12 Jun 2024 12:23:48 +0200 Subject: [PATCH 09/22] Update DESCRIPTION --- image.LineSegmentDetector/DESCRIPTION | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/image.LineSegmentDetector/DESCRIPTION b/image.LineSegmentDetector/DESCRIPTION index b3d537b..636d174 100644 --- a/image.LineSegmentDetector/DESCRIPTION +++ b/image.LineSegmentDetector/DESCRIPTION @@ -7,7 +7,8 @@ Maintainer: Jan Wijffels Authors@R: c( person("Jan", "Wijffels", role = c("aut", "cre", "cph"), email = "jwijffels@bnosac.be", comment = "R wrapper"), person("BNOSAC", role = "cph", comment = "R wrapper"), - person("Rafael Grompone von Gioi", role = c("ctb", "cph"), email = "grompone@gmail.com", comment = "src/lsd")) + person("Rafael Grompone von Gioi", role = c("ctb", "cph"), email = "grompone@gmail.com", comment = "src/lsd")), + person("Niccolò Marchi", role = "ctb", email = "sciurusurbanus@hotmail.it")) License: AGPL-3 Version: 0.1.0 URL: https://github.com/bnosac/image From f42ce79e4bbdcd230ffec248585bdcf99be0b06c Mon Sep 17 00:00:00 2001 From: Nic Date: Mon, 17 Jun 2024 16:22:59 +0200 Subject: [PATCH 10/22] Update line_segment_detector.R changed "export_sf" parameter to "as_sf" --- image.LineSegmentDetector/R/line_segment_detector.R | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/image.LineSegmentDetector/R/line_segment_detector.R b/image.LineSegmentDetector/R/line_segment_detector.R index 573edb5..e70208c 100644 --- a/image.LineSegmentDetector/R/line_segment_detector.R +++ b/image.LineSegmentDetector/R/line_segment_detector.R @@ -30,7 +30,7 @@ #' @param union_ang_th Numeric value with angle threshold in order to union #' @param union_use_NFA Logical indicating to use NFA to union #' @param union_log_eps Detection threshold to union -#' @param export_sf Boolean. Set to TRUE to export lines as sf spatial objects (WARNING: process may take several time) +#' @param as_sf Boolean. Set to TRUE to export lines as sf spatial objects (WARNING: process may take several time) #' @return an object of class lsd which is a list with the following elements #' \itemize{ #' \item{n: }{The number of found line segments} @@ -105,7 +105,7 @@ image_line_segment_detector <- function(x, scale = 0.8, density_th = 0.7, n_bins = 1024, union = FALSE, union_min_length = 5, union_max_distance = 5, union_ang_th=7, union_use_NFA=FALSE, union_log_eps = 0.0, - export_sf=FALSE ){ + as_sf=FALSE ){ UseMethod("image_line_segment_detector") } @@ -116,7 +116,7 @@ image_line_segment_detector.matrix <- function(x, scale = 0.8, density_th = 0.7, n_bins = 1024, union = FALSE, union_min_length = 5, union_max_distance = 5, union_ang_th=7, union_use_NFA=FALSE, union_log_eps = 0.0, - export_sf=FALSE ) { + as_sf=FALSE ) { stopifnot(is.matrix(x)) @@ -149,7 +149,7 @@ image_line_segment_detector.SpatRaster <- function(x, scale = 0.8, density_th = 0.7, n_bins = 1024, union = FALSE, union_min_length = 5, union_max_distance = 5, union_ang_th=7, union_use_NFA=FALSE, union_log_eps = 0.0, - export_sf=FALSE ){ + as_sf=FALSE ){ requireNamespace("terra") uprightX = terra::ext(x)[2] uprightY = terra::ext(x)[4] @@ -166,7 +166,7 @@ image_line_segment_detector.SpatRaster <- function(x, scale = 0.8, density_th = density_th, n_bins = n_bins, union = union, union_min_length = union_min_length, union_max_distance = union_max_distance, union_ang_th=union_ang_th, union_use_NFA=union_use_NFA, union_log_eps = union_log_eps, - export_sf=export_sf ) + as_sf=as_sf ) linesegments = as.data.frame(linesegments$lines) @@ -178,7 +178,7 @@ image_line_segment_detector.SpatRaster <- function(x, scale = 0.8, # export object as sf - if(isTRUE(export_sf)){ + if(isTRUE(as_sf)){ requireNamespace("sf") linesegments = apply(linesegments, 1, function(x) From a19672c4826130949b94ce6cdf266ba637422a35 Mon Sep 17 00:00:00 2001 From: Nic Date: Mon, 17 Jun 2024 16:23:11 +0200 Subject: [PATCH 11/22] Update contour_detector.R changed "export_sf" parameter to "as_sf" --- image.ContourDetector/R/contour_detector.R | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 045305c..78333ac 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -11,7 +11,7 @@ #' an efficient algorithm is derived producing sub-pixel contours. #' @param x a matrix of image pixel values in the 0-255 range. #' @param Q numeric value with the pixel quantization step -#' @param export_sf Boolean. Set to TRUE to export lines as sf spatial objects (WARNING: process may take several time) +#' @param as_sf Boolean. Set to TRUE to export lines as sf spatial objects (WARNING: process may take several time) #' @param ... further arguments, not used yet #' @return an object of class cld which is a list with the following elements #' \itemize{ @@ -82,12 +82,12 @@ #' \} #' # End of main if statement running only if the required packages are installed #' } -image_contour_detector <- function(x, Q=2.0 export_sf=FALSE, ...){ +image_contour_detector <- function(x, Q=2.0 as_sf=FALSE, ...){ UseMethod("image_contour_detector") } #' @export -image_contour_detector.matrix <- function(x, Q=2.0, export_sf=FALSE, ...){ +image_contour_detector.matrix <- function(x, Q=2.0, as_sf=FALSE, ...){ stopifnot(is.matrix(x)) contourlines <- detect_contours(x, X=nrow(x), @@ -105,7 +105,7 @@ image_contour_detector.matrix <- function(x, Q=2.0, export_sf=FALSE, ...){ } #' @export -image_contour_detector.RasterLayer <- function(x, Q=2.0, export_sf=FALSE, ...){ +image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ requireNamespace("raster") minX = raster::extent(x)[1] minY = raster::extent(x)[3] @@ -116,7 +116,7 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, export_sf=FALSE, ...){ x[is.na(x)] = 0 warning("NA values found and set to 0") } - contourlines = image_contour_detector.matrix(x, Q=Q, export_sf=export_sf) + contourlines = image_contour_detector.matrix(x, Q=Q, as_sf=as_sf) contourlines$data$x = contourlines$data$x * resol + minX contourlines$data$y = contourlines$data$y * resol + minY @@ -124,7 +124,7 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, export_sf=FALSE, ...){ } #' @export -image_contour_detector.SpatRaster <- function(x, Q=2.0, export_sf=FALSE, ...){ +image_contour_detector.SpatRaster <- function(x, Q=2.0, as_sf=FALSE, ...){ requireNamespace("terra") minX = terra::ext(x)[1] minY = terra::ext(x)[3] @@ -135,13 +135,13 @@ image_contour_detector.SpatRaster <- function(x, Q=2.0, export_sf=FALSE, ...){ x[is.na(xmat)] = 0 warning("NA values found and set to 0") } - contourlines = image_contour_detector.matrix(xmat, Q=Q, export_sf=export_sf) + contourlines = image_contour_detector.matrix(xmat, Q=Q, as_sf=as_sf) contourlines$data$x = contourlines$data$x * resol + minX contourlines$data$y = contourlines$data$y * resol + minY # export object as sf - if(isTRUE(export_sf)){ + if(isTRUE(as_sf)){ requireNamespace("sf") contourlines <- contourlines$data %>% From 0d21434a35038c9dc576aa2645c2c56b0e1b3956 Mon Sep 17 00:00:00 2001 From: Nic Date: Mon, 1 Jul 2024 21:53:46 +0200 Subject: [PATCH 12/22] Update DESCRIPTION --- image.LineSegmentDetector/DESCRIPTION | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/image.LineSegmentDetector/DESCRIPTION b/image.LineSegmentDetector/DESCRIPTION index 636d174..5f7c262 100644 --- a/image.LineSegmentDetector/DESCRIPTION +++ b/image.LineSegmentDetector/DESCRIPTION @@ -7,8 +7,9 @@ Maintainer: Jan Wijffels Authors@R: c( person("Jan", "Wijffels", role = c("aut", "cre", "cph"), email = "jwijffels@bnosac.be", comment = "R wrapper"), person("BNOSAC", role = "cph", comment = "R wrapper"), - person("Rafael Grompone von Gioi", role = c("ctb", "cph"), email = "grompone@gmail.com", comment = "src/lsd")), + person("Rafael Grompone von Gioi", role = c("ctb", "cph"), email = "grompone@gmail.com", comment = "src/lsd"), person("Niccolò Marchi", role = "ctb", email = "sciurusurbanus@hotmail.it")) +Encoding: UTF-8 License: AGPL-3 Version: 0.1.0 URL: https://github.com/bnosac/image From 2d93e56a3beebb9d0413e058fe636eefb375db68 Mon Sep 17 00:00:00 2001 From: Nic Date: Mon, 1 Jul 2024 22:40:23 +0200 Subject: [PATCH 13/22] Update contour_detector.R --- image.ContourDetector/R/contour_detector.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 78333ac..18805e8 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -82,7 +82,7 @@ #' \} #' # End of main if statement running only if the required packages are installed #' } -image_contour_detector <- function(x, Q=2.0 as_sf=FALSE, ...){ +image_contour_detector <- function(x, Q=2.0, as_sf=FALSE, ...){ UseMethod("image_contour_detector") } From 8379a37fa25ac9642678df92bb4fa4c9ea04a3fb Mon Sep 17 00:00:00 2001 From: Nic Date: Mon, 1 Jul 2024 23:38:42 +0200 Subject: [PATCH 14/22] removed dependency on dplyr --- image.ContourDetector/R/contour_detector.R | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 18805e8..48cf011 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -144,12 +144,25 @@ image_contour_detector.SpatRaster <- function(x, Q=2.0, as_sf=FALSE, ...){ if(isTRUE(as_sf)){ requireNamespace("sf") - contourlines <- contourlines$data %>% - sf::st_as_sf(coords = c("x", "y"), crs = sf::st_crs(x) ) %>% - dplyr::group_by( curve ) %>% - dplyr::summarize(do_union=FALSE) %>% - sf::st_cast("LINESTRING") - contourlines$length_m = sf::st_length(contourlines) + # contourlines <- contourlines$data %>% + # sf::st_as_sf(coords = c("x", "y"), crs = sf::st_crs(x) ) %>% + # dplyr::group_by( curve ) %>% + # dplyr::summarize(do_union=FALSE) %>% + # sf::st_cast("LINESTRING") + + contourlines <- contourlines$data + contourlines = sf::st_as_sf( contourlines, coords = c("x", "y"), crs = sf::st_crs(x) ) + + out = list() + + for( i in unique(contourlines$curve) ){ + ss = subset(contourlines, curve == i ) + ss = sf::st_combine(ss) + out[[length(out)+1]] = sf::st_cast( st_sf(ss), "LINESTRING") + } + + contourlines = do.call(rbind,out) + contourlines$length_m = sf::st_length(contourlines) } return(contourlines) } From 9713cdde987637a929bf0331f88fbe8a6027512b Mon Sep 17 00:00:00 2001 From: Jan Wijffels Date: Tue, 2 Jul 2024 23:28:30 +0200 Subject: [PATCH 15/22] documentation changes --- image.ContourDetector/NAMESPACE | 1 + image.ContourDetector/R/contour_detector.R | 26 ++++++++++++++----- .../man/image_contour_detector.RasterLayer.Rd | 26 +++++++++++++++++++ .../man/image_contour_detector.Rd | 10 +++---- .../man/image_contour_detector.SpatRaster.Rd | 26 +++++++++++++++++++ 5 files changed, 78 insertions(+), 11 deletions(-) create mode 100644 image.ContourDetector/man/image_contour_detector.RasterLayer.Rd create mode 100644 image.ContourDetector/man/image_contour_detector.SpatRaster.Rd diff --git a/image.ContourDetector/NAMESPACE b/image.ContourDetector/NAMESPACE index 97f0294..1c90b27 100644 --- a/image.ContourDetector/NAMESPACE +++ b/image.ContourDetector/NAMESPACE @@ -1,6 +1,7 @@ # Generated by roxygen2: do not edit by hand S3method(image_contour_detector,RasterLayer) +S3method(image_contour_detector,SpatRaster) S3method(image_contour_detector,matrix) S3method(plot,cld) S3method(print,cld) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 48cf011..1300114 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -11,8 +11,7 @@ #' an efficient algorithm is derived producing sub-pixel contours. #' @param x a matrix of image pixel values in the 0-255 range. #' @param Q numeric value with the pixel quantization step -#' @param as_sf Boolean. Set to TRUE to export lines as sf spatial objects (WARNING: process may take several time) -#' @param ... further arguments, not used yet +#' @param ... further arguments passed on to \code{image_contour_detector.matrix}, \code{\link{image_contour_detector.RasterLayer}} or \code{\link{image_contour_detector.SpatRaster}}. #' @return an object of class cld which is a list with the following elements #' \itemize{ #' \item{curves: }{The number of contour lines found} @@ -82,12 +81,12 @@ #' \} #' # End of main if statement running only if the required packages are installed #' } -image_contour_detector <- function(x, Q=2.0, as_sf=FALSE, ...){ +image_contour_detector <- function(x, Q=2.0, ...){ UseMethod("image_contour_detector") } #' @export -image_contour_detector.matrix <- function(x, Q=2.0, as_sf=FALSE, ...){ +image_contour_detector.matrix <- function(x, Q=2.0, ...){ stopifnot(is.matrix(x)) contourlines <- detect_contours(x, X=nrow(x), @@ -104,6 +103,14 @@ image_contour_detector.matrix <- function(x, Q=2.0, as_sf=FALSE, ...){ return(contourlines) } +#' @title Unsupervised Smooth Contour Lines Detection for RasterLayer objects +#' @description Unsupervised Smooth Contour Detection +#' @param x a RasterLayer object +#' @param Q numeric value with the pixel quantization step +#' @param as_sf Boolean. Set to TRUE to export lines as sf spatial objects +#' @param ... further arguments passed on to \code{image_contour_detector.matrix} +#' @return an object of class cld which as described in \code{\link{image_contour_detector}} +#' @seealso \code{\link{image_contour_detector}} #' @export image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ requireNamespace("raster") @@ -116,13 +123,20 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ x[is.na(x)] = 0 warning("NA values found and set to 0") } - contourlines = image_contour_detector.matrix(x, Q=Q, as_sf=as_sf) + contourlines = image_contour_detector.matrix(x, Q=Q, ...) contourlines$data$x = contourlines$data$x * resol + minX contourlines$data$y = contourlines$data$y * resol + minY return(contourlines) } +#' @title Unsupervised Smooth Contour Lines Detection for SpatRaster objects +#' @param x a SpatRaster object +#' @param Q numeric value with the pixel quantization step +#' @param as_sf Boolean. Set to TRUE to export lines as sf spatial objects +#' @param ... further arguments passed on to \code{image_contour_detector.matrix} +#' @return an object of class cld which as described in \code{\link{image_contour_detector}} +#' @seealso \code{\link{image_contour_detector}} #' @export image_contour_detector.SpatRaster <- function(x, Q=2.0, as_sf=FALSE, ...){ requireNamespace("terra") @@ -135,7 +149,7 @@ image_contour_detector.SpatRaster <- function(x, Q=2.0, as_sf=FALSE, ...){ x[is.na(xmat)] = 0 warning("NA values found and set to 0") } - contourlines = image_contour_detector.matrix(xmat, Q=Q, as_sf=as_sf) + contourlines = image_contour_detector.matrix(xmat, Q=Q, ...) contourlines$data$x = contourlines$data$x * resol + minX contourlines$data$y = contourlines$data$y * resol + minY diff --git a/image.ContourDetector/man/image_contour_detector.RasterLayer.Rd b/image.ContourDetector/man/image_contour_detector.RasterLayer.Rd new file mode 100644 index 0000000..d577d6e --- /dev/null +++ b/image.ContourDetector/man/image_contour_detector.RasterLayer.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/contour_detector.R +\name{image_contour_detector.RasterLayer} +\alias{image_contour_detector.RasterLayer} +\title{Unsupervised Smooth Contour Lines Detection for RasterLayer objects} +\usage{ +\method{image_contour_detector}{RasterLayer}(x, Q = 2, as_sf = FALSE, ...) +} +\arguments{ +\item{x}{a RasterLayer object} + +\item{Q}{numeric value with the pixel quantization step} + +\item{as_sf}{Boolean. Set to TRUE to export lines as sf spatial objects} + +\item{...}{further arguments passed on to \code{image_contour_detector.matrix}} +} +\value{ +an object of class cld which as described in \code{\link{image_contour_detector}} +} +\description{ +Unsupervised Smooth Contour Detection +} +\seealso{ +\code{\link{image_contour_detector}} +} diff --git a/image.ContourDetector/man/image_contour_detector.Rd b/image.ContourDetector/man/image_contour_detector.Rd index fc13ad0..c977c57 100644 --- a/image.ContourDetector/man/image_contour_detector.Rd +++ b/image.ContourDetector/man/image_contour_detector.Rd @@ -11,7 +11,7 @@ image_contour_detector(x, Q = 2, ...) \item{Q}{numeric value with the pixel quantization step} -\item{...}{further arguments, not used yet} +\item{...}{further arguments passed on to \code{image_contour_detector.matrix}, \code{\link{image_contour_detector.RasterLayer}} or \code{\link{image_contour_detector.SpatRaster}}.} } \value{ an object of class cld which is a list with the following elements @@ -75,15 +75,15 @@ plot(contourlines) } ## -## working with a RasterLayer +## working with a SpatRaster ## \dontshow{ -if(require(raster)) +if(require(terra)) \{ } \donttest{ -library(raster) -x <- raster(system.file("extdata", "landscape.tif", package="image.ContourDetector")) +library(terra) +x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetector")) contourlines <- image_contour_detector(x) image(x) diff --git a/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd b/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd new file mode 100644 index 0000000..a0a8105 --- /dev/null +++ b/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/contour_detector.R +\name{image_contour_detector.SpatRaster} +\alias{image_contour_detector.SpatRaster} +\title{Unsupervised Smooth Contour Lines Detection for SpatRaster objects} +\usage{ +\method{image_contour_detector}{SpatRaster}(x, Q = 2, as_sf = FALSE, ...) +} +\arguments{ +\item{x}{a SpatRaster object} + +\item{Q}{numeric value with the pixel quantization step} + +\item{as_sf}{Boolean. Set to TRUE to export lines as sf spatial objects} + +\item{...}{further arguments passed on to \code{image_contour_detector.matrix}} +} +\value{ +an object of class cld which as described in \code{\link{image_contour_detector}} +} +\description{ +Unsupervised Smooth Contour Lines Detection for SpatRaster objects +} +\seealso{ +\code{\link{image_contour_detector}} +} From d217bf3dc93864577e8ebff930b6f91704456d46 Mon Sep 17 00:00:00 2001 From: Jan Wijffels Date: Tue, 2 Jul 2024 23:33:04 +0200 Subject: [PATCH 16/22] no need to bring in dplyr dependency --- image.ContourDetector/DESCRIPTION | 1 - 1 file changed, 1 deletion(-) diff --git a/image.ContourDetector/DESCRIPTION b/image.ContourDetector/DESCRIPTION index 2f1a3e0..999ea98 100644 --- a/image.ContourDetector/DESCRIPTION +++ b/image.ContourDetector/DESCRIPTION @@ -17,7 +17,6 @@ URL: https://github.com/bnosac/image Imports: Rcpp (>= 0.12.8), sp LinkingTo: Rcpp Suggests: - dplyr, pixmap, magick, raster, From 5e07b0910c4f69ed9beb832db7af3a4b3c65048a Mon Sep 17 00:00:00 2001 From: Jan Wijffels Date: Tue, 2 Jul 2024 23:33:24 +0200 Subject: [PATCH 17/22] fix R CMD check notes --- image.ContourDetector/R/contour_detector.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 1300114..8a6b86f 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -170,9 +170,9 @@ image_contour_detector.SpatRaster <- function(x, Q=2.0, as_sf=FALSE, ...){ out = list() for( i in unique(contourlines$curve) ){ - ss = subset(contourlines, curve == i ) + ss = subset(contourlines, contourlines$curve == i ) ss = sf::st_combine(ss) - out[[length(out)+1]] = sf::st_cast( st_sf(ss), "LINESTRING") + out[[length(out)+1]] = sf::st_cast( sf::st_sf(ss), "LINESTRING") } contourlines = do.call(rbind,out) From 4f7f60c2219ef2cb382682992ab5c3a7f3776d35 Mon Sep 17 00:00:00 2001 From: Jan Wijffels Date: Tue, 2 Jul 2024 23:52:27 +0200 Subject: [PATCH 18/22] replace NA with 0 in matrix, not in SpatRaster --- image.ContourDetector/R/contour_detector.R | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 8a6b86f..cccaac7 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -145,9 +145,10 @@ image_contour_detector.SpatRaster <- function(x, Q=2.0, as_sf=FALSE, ...){ resol = terra::res(x)[1] xmat = terra::as.matrix(x, wide=TRUE) - if( anyNA(xmat) ){ - x[is.na(xmat)] = 0 - warning("NA values found and set to 0") } + if(anyNA(xmat)){ + xmat[is.na(xmat)] = 0 + warning("NA values found and set to 0") + } contourlines = image_contour_detector.matrix(xmat, Q=Q, ...) From 56f133a2cbb63d360d409cb6b4fc4b171e719fef Mon Sep 17 00:00:00 2001 From: Jan Wijffels Date: Tue, 2 Jul 2024 23:55:08 +0200 Subject: [PATCH 19/22] move example to SpatRaster method --- image.ContourDetector/R/contour_detector.R | 37 +++++++++---------- .../man/image_contour_detector.Rd | 20 ---------- .../man/image_contour_detector.SpatRaster.Rd | 18 +++++++++ 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index cccaac7..c175db1 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -61,26 +61,6 @@ #' \} #' # End of main if statement running only if the required packages are installed #' } -#' -#' ## -#' ## working with a SpatRaster -#' ## -#' \dontshow{ -#' if(require(terra)) -#' \{ -#' } -#' \donttest{ -#' library(terra) -#' x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetector")) -#' -#' contourlines <- image_contour_detector(x) -#' image(x) -#' plot(contourlines, add = TRUE, col = "blue", lwd = 10) -#' } -#' \dontshow{ -#' \} -#' # End of main if statement running only if the required packages are installed -#' } image_contour_detector <- function(x, Q=2.0, ...){ UseMethod("image_contour_detector") } @@ -138,6 +118,23 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ #' @return an object of class cld which as described in \code{\link{image_contour_detector}} #' @seealso \code{\link{image_contour_detector}} #' @export +#' @examples +#' \dontshow{ +#' if(require(terra)) +#' \{ +#' } +#' \donttest{ +#' library(terra) +#' x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetector")) +#' +#' contourlines <- image_contour_detector(x) +#' image(x) +#' plot(contourlines, add = TRUE, col = "blue", lwd = 10) +#' } +#' \dontshow{ +#' \} +#' # End of main if statement running only if the required packages are installed +#' } image_contour_detector.SpatRaster <- function(x, Q=2.0, as_sf=FALSE, ...){ requireNamespace("terra") minX = terra::ext(x)[1] diff --git a/image.ContourDetector/man/image_contour_detector.Rd b/image.ContourDetector/man/image_contour_detector.Rd index c977c57..602bfbb 100644 --- a/image.ContourDetector/man/image_contour_detector.Rd +++ b/image.ContourDetector/man/image_contour_detector.Rd @@ -73,26 +73,6 @@ plot(contourlines) \} # End of main if statement running only if the required packages are installed } - -## -## working with a SpatRaster -## -\dontshow{ -if(require(terra)) -\{ -} -\donttest{ -library(terra) -x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetector")) - -contourlines <- image_contour_detector(x) -image(x) -plot(contourlines, add = TRUE, col = "blue", lwd = 10) -} -\dontshow{ -\} -# End of main if statement running only if the required packages are installed -} } \references{ Rafael Grompone von Gioi, and Gregory Randall, Unsupervised Smooth Contour Detection, diff --git a/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd b/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd index a0a8105..bb09dcf 100644 --- a/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd +++ b/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd @@ -21,6 +21,24 @@ an object of class cld which as described in \code{\link{image_contour_detector} \description{ Unsupervised Smooth Contour Lines Detection for SpatRaster objects } +\examples{ +\dontshow{ +if(require(terra)) +\{ +} +\donttest{ +library(terra) +x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetector")) + +contourlines <- image_contour_detector(x) +image(x) +plot(contourlines, add = TRUE, col = "blue", lwd = 10) +} +\dontshow{ +\} +# End of main if statement running only if the required packages are installed +} +} \seealso{ \code{\link{image_contour_detector}} } From e0d346d2c62da28b46c2a507dfdb6b2fbca25566 Mon Sep 17 00:00:00 2001 From: Jan Wijffels Date: Wed, 3 Jul 2024 00:04:46 +0200 Subject: [PATCH 20/22] docs --- image.ContourDetector/R/contour_detector.R | 8 ++++++-- .../man/image_contour_detector.SpatRaster.Rd | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index c175db1..6f013fc 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -115,12 +115,14 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ #' @param Q numeric value with the pixel quantization step #' @param as_sf Boolean. Set to TRUE to export lines as sf spatial objects #' @param ... further arguments passed on to \code{image_contour_detector.matrix} -#' @return an object of class cld which as described in \code{\link{image_contour_detector}} +#' @return +#' In case \code{as_sf} is \code{FALSE}: an object of class cld which as described in \code{\link{image_contour_detector}}\cr +#' In case \code{as_sf} is \code{TRUE}: an object of class sf with columns ss and length_m #' @seealso \code{\link{image_contour_detector}} #' @export #' @examples #' \dontshow{ -#' if(require(terra)) +#' if(require(terra) && require(sf)) #' \{ #' } #' \donttest{ @@ -130,6 +132,8 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ #' contourlines <- image_contour_detector(x) #' image(x) #' plot(contourlines, add = TRUE, col = "blue", lwd = 10) +#' +#' contourlines <- image_contour_detector(x, as_sf = TRUE) #' } #' \dontshow{ #' \} diff --git a/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd b/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd index bb09dcf..6e136d9 100644 --- a/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd +++ b/image.ContourDetector/man/image_contour_detector.SpatRaster.Rd @@ -16,14 +16,15 @@ \item{...}{further arguments passed on to \code{image_contour_detector.matrix}} } \value{ -an object of class cld which as described in \code{\link{image_contour_detector}} +In case \code{as_sf} is \code{FALSE}: an object of class cld which as described in \code{\link{image_contour_detector}}\cr +In case \code{as_sf} is \code{TRUE}: an object of class sf with columns ss and length_m } \description{ Unsupervised Smooth Contour Lines Detection for SpatRaster objects } \examples{ \dontshow{ -if(require(terra)) +if(require(terra) && require(sf)) \{ } \donttest{ @@ -33,6 +34,8 @@ x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetect contourlines <- image_contour_detector(x) image(x) plot(contourlines, add = TRUE, col = "blue", lwd = 10) + +contourlines <- image_contour_detector(x, as_sf = TRUE) } \dontshow{ \} From 84bb8e3909f4317420986835a40889304f0bdebf Mon Sep 17 00:00:00 2001 From: Nic Date: Wed, 3 Jul 2024 10:49:08 +0200 Subject: [PATCH 21/22] Update contour_detector.R - added curve_ID - fixed '@return' description - fixed minor issues --- image.ContourDetector/R/contour_detector.R | 46 ++++++++++++++++------ 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/image.ContourDetector/R/contour_detector.R b/image.ContourDetector/R/contour_detector.R index 6f013fc..9f7aa07 100644 --- a/image.ContourDetector/R/contour_detector.R +++ b/image.ContourDetector/R/contour_detector.R @@ -89,7 +89,9 @@ image_contour_detector.matrix <- function(x, Q=2.0, ...){ #' @param Q numeric value with the pixel quantization step #' @param as_sf Boolean. Set to TRUE to export lines as sf spatial objects #' @param ... further arguments passed on to \code{image_contour_detector.matrix} -#' @return an object of class cld which as described in \code{\link{image_contour_detector}} +#' @return +#' In case \code{as_sf} is \code{FALSE}: an object of class cld which as described in \code{\link{image_contour_detector}}\cr +#' In case \code{as_sf} is \code{TRUE}: an object of class sf containing the detected lines, a curve ID and its length (in the same units as the SpatRaster's CRS) #' @seealso \code{\link{image_contour_detector}} #' @export image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ @@ -97,16 +99,37 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ minX = raster::extent(x)[1] minY = raster::extent(x)[3] resol = raster::res(x)[1] - x = raster::as.matrix(x) + xmat = raster::as.matrix(x) - if( anyNA(x) ){ - x[is.na(x)] = 0 + if( anyNA(xmat) ){ + x[is.na(xmat)] = 0 warning("NA values found and set to 0") } - contourlines = image_contour_detector.matrix(x, Q=Q, ...) + contourlines = image_contour_detector.matrix( xmat, Q=Q ) contourlines$data$x = contourlines$data$x * resol + minX contourlines$data$y = contourlines$data$y * resol + minY + + # export object as sf + if(isTRUE(as_sf)){ + requireNamespace("sf") + + contourlines <- contourlines$data + contourlines = sf::st_as_sf( contourlines, coords = c("x", "y"), crs = sf::st_crs(x) ) + + out = list() + + for( i in unique(contourlines$curve) ){ + ss = subset(contourlines, curve == i ) + ss = sf::st_combine(ss) + out[[length(out)+1]] = sf::st_cast( sf::st_sf(ss), "LINESTRING") + } + + contourlines = do.call(rbind,out) + contourlines$curve_ID = 1:nrow(contourlines) + contourlines$length = round( sf::st_length(contourlines), 3) + } + return(contourlines) } @@ -115,9 +138,9 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ #' @param Q numeric value with the pixel quantization step #' @param as_sf Boolean. Set to TRUE to export lines as sf spatial objects #' @param ... further arguments passed on to \code{image_contour_detector.matrix} -#' @return +#' @return #' In case \code{as_sf} is \code{FALSE}: an object of class cld which as described in \code{\link{image_contour_detector}}\cr -#' In case \code{as_sf} is \code{TRUE}: an object of class sf with columns ss and length_m +#' In case \code{as_sf} is \code{TRUE}: an object of class sf containing the detected lines, a curve ID and its length (in the same units as the SpatRaster's CRS) #' @seealso \code{\link{image_contour_detector}} #' @export #' @examples @@ -130,7 +153,7 @@ image_contour_detector.RasterLayer <- function(x, Q=2.0, as_sf=FALSE, ...){ #' x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetector")) #' #' contourlines <- image_contour_detector(x) -#' image(x) +#' plot(x) #' plot(contourlines, add = TRUE, col = "blue", lwd = 10) #' #' contourlines <- image_contour_detector(x, as_sf = TRUE) @@ -151,7 +174,7 @@ image_contour_detector.SpatRaster <- function(x, Q=2.0, as_sf=FALSE, ...){ warning("NA values found and set to 0") } - contourlines = image_contour_detector.matrix(xmat, Q=Q, ...) + contourlines = image_contour_detector.matrix( xmat, Q=Q ) contourlines$data$x = contourlines$data$x * resol + minX contourlines$data$y = contourlines$data$y * resol + minY @@ -172,13 +195,14 @@ image_contour_detector.SpatRaster <- function(x, Q=2.0, as_sf=FALSE, ...){ out = list() for( i in unique(contourlines$curve) ){ - ss = subset(contourlines, contourlines$curve == i ) + ss = subset(contourlines, curve == i ) ss = sf::st_combine(ss) out[[length(out)+1]] = sf::st_cast( sf::st_sf(ss), "LINESTRING") } contourlines = do.call(rbind,out) - contourlines$length_m = sf::st_length(contourlines) + contourlines$curve_ID = 1:nrow(contourlines) + contourlines$length = round( sf::st_length(contourlines), 3) } return(contourlines) } From c179f5fcd1b4430aaabcef4be1d5aabf52d9ed82 Mon Sep 17 00:00:00 2001 From: Nic Date: Wed, 3 Jul 2024 11:54:40 +0200 Subject: [PATCH 22/22] Update line_segment_detector.R - refined sf objects creation - removed dependency on sp and moving it to sf - updated plot.lsd --- .../R/line_segment_detector.R | 63 +++++++++++-------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/image.LineSegmentDetector/R/line_segment_detector.R b/image.LineSegmentDetector/R/line_segment_detector.R index e70208c..a365965 100644 --- a/image.LineSegmentDetector/R/line_segment_detector.R +++ b/image.LineSegmentDetector/R/line_segment_detector.R @@ -91,8 +91,8 @@ #' library(terra) #' x <- rast(system.file("extdata", "landscape.tif", package="image.ContourDetector")) #' -#' linesegments <- image_line_segment_detector(x) -#' image(x) +#' linesegments <- image_line_segment_detector(x, as_sf=TRUE) +#' plot(x) #' plot(linesegments, add = TRUE, col = "blue", lwd = 10) #' } #' \dontshow{ @@ -155,44 +155,47 @@ image_line_segment_detector.SpatRaster <- function(x, scale = 0.8, uprightY = terra::ext(x)[4] resol = terra::res(x)[1] - x = t(terra::as.matrix(x,wide=TRUE)) + xmat = t(terra::as.matrix(x,wide=TRUE)) - if( anyNA(x) ){ - x[is.na(x)] = 0 + if( anyNA(xmat) ){ + xmat[is.na(xmat)] = 0 warning("NA values found and set to 0") } - linesegments = image_line_segment_detector.matrix(x, scale = scale, + linesegments = image_line_segment_detector.matrix(xmat, scale = scale, sigma_scale = sigma_scale, quant = quant, ang_th = ang_th, log_eps = log_eps, density_th = density_th, n_bins = n_bins, union = union, union_min_length = union_min_length, union_max_distance = union_max_distance, union_ang_th=union_ang_th, union_use_NFA=union_use_NFA, union_log_eps = union_log_eps, as_sf=as_sf ) - linesegments = as.data.frame(linesegments$lines) - # assign spatial coordinates - linesegments$x1 = linesegments$x1 * -resol + uprightY - linesegments$y1 = linesegments$y1 * -resol + uprightX - linesegments$x2 = linesegments$x2 * -resol + uprightY - linesegments$y2 = linesegments$y2 * -resol + uprightX - + linesegments$lines[,1] = linesegments$lines[,1] * -resol + uprightY + linesegments$lines[,2] = linesegments$lines[,2] * -resol + uprightX + linesegments$lines[,3] = linesegments$lines[,3] * -resol + uprightY + linesegments$lines[,4] = linesegments$lines[,4] * -resol + uprightX + linesegments$lines[,5] = linesegments$lines[,5] * resol # width parameter # export object as sf if(isTRUE(as_sf)){ requireNamespace("sf") + + linesegments = as.data.frame(linesegments$lines) linesegments = apply(linesegments, 1, function(x) { v <- as.numeric(x[c(2,4,1,3)]) m <- matrix(v, nrow = 2) - return(sf::st_sfc(sf::st_linestring(m), crs = NA_crs_)) + return(sf::st_sfc(sf::st_linestring(m))) }) print("Sf export in progress...") linesegments = do.call(c, linesegments) linesegments = sf::st_sf(linesegments) + if( !is.na(sf::st_crs(x)) ){ sf::st_crs(linesegments) = sf::st_crs(x)} + st_geometry(linesegments) = 'geometry' + linesegments$line_ID = 1:nrow(linesegments) - linesegments$length_m = sf::st_length(linesegments) + linesegments$length = round( sf::st_length(linesegments), 3) } return(linesegments) @@ -210,7 +213,7 @@ print.lsd <- function(x, ...){ #' @description Plot the detected lines from the image_line_segment_detector #' @param x an object of class lsd as returned by \code{\link{image_line_segment_detector}} #' @param ... further arguments passed on to plot -#' @return invisibly a SpatialLines object with the lines +#' @return invisibly an sf object with the lines #' @export #' @method plot lsd #' @examples @@ -221,13 +224,23 @@ print.lsd <- function(x, ...){ #' plot(image) #' plot(linesegments, add = TRUE, col = "red") plot.lsd <- function(x, ...){ - requireNamespace("sp") - out <- sp::SpatialLines(lapply(seq_len(x$n), FUN=function(i){ - l <- rbind( - x$lines[i, c("x1", "y1")], - x$lines[i, c("x2", "y2")]) - sp::Lines(sp::Line(l), ID = i) - })) - sp::plot(out, ...) - invisible(out) + requireNamespace("sf") + + out = as.data.frame(x$lines) + + out = apply(out, 1, function(x) + { + v <- as.numeric(x[c(2,4,1,3)]) + m <- matrix(v, nrow = 2) + return( sf::st_sfc(sf::st_linestring(m) ) ) + }) + print("Loading in progress...") + out = do.call(c, out) + + out = sf::st_sf(out, crs = 'NA_crs_') + if( !is.na(sf::st_crs(x)) ){ sf::st_crs(out) = sf::st_crs(x)} + st_geometry(out) = 'geometry' + + plot(out$geometry, ...) + invisible(out$geometry) }