diff --git a/NAMESPACE b/NAMESPACE index acdf0966..2079d710 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -80,6 +80,7 @@ export(add) export(addWeighted) export(anisotropicDiffusion) export(api) +export(approxPolyDP) export(arcLength) export(autothreshold) export(bilateralFilter) diff --git a/R/feature.R b/R/feature.R index 701f3238..959429cb 100644 --- a/R/feature.R +++ b/R/feature.R @@ -255,7 +255,7 @@ goodFeaturesToTrack <- function(image, max_corners, quality_level, min_distance, if (!all(mask$dim()[1:2] == image$dim()[1:2])) stop("mask does not have the same dimensions as image.") - if (mask$depth() != 1) + if (mask$depth() != "8U") stop("mask is not an 8U 'Image' object.") } diff --git a/R/shape.R b/R/shape.R index c838f28a..25b4a1ef 100644 --- a/R/shape.R +++ b/R/shape.R @@ -881,6 +881,57 @@ arcLength <- function(curve, closed = TRUE) { } +#' @title Calculate a Contour Perimeter or a Curve Length +#' +#' @description \code{approxPolyDP} approximates a curve or a polygon with +#' another curve/polygon with less vertices so that the distance between them +#' is less or equal to the specified precision. It uses the Douglas-Peucker +#' algorithm. +#' +#' @param curve An m x 2 matrix of 2D coordinates. +#' +#' @param epsilon A numeric specifying the approximation accuracy. This is the +#' maximum distance between the original curve and its approximation. +#' +#' @param closed A logical indicating whether the curve is closed (perimeter) or +#' not (default: TRUE). +#' +#' @return A matrix with two columns: +#' \itemize{ +#' \item{"x": }{the x coordinates of the approximated curve.} +#' \item{"y": }{the y coordinates of the approximated curve.} +#' } +#' +#' @author Simon Garnier, \email{garnier@@njit.edu} +#' +#' @seealso \code{\link{findContours}} +#' +#' @references Douglas, D. H., & Peucker, T. K. (1973). ALGORITHMS FOR THE +#' REDUCTION OF THE NUMBER OF POINTS REQUIRED TO REPRESENT A DIGITIZED LINE OR +#' ITS CARICATURE. Cartographica: The International Journal for Geographic +#' Information and Geovisualization, 10(2), 112–122. +#' doi:10.3138/FM57-6770-U75U-7727 +#' +#' @examples +#' dots <- image(system.file("sample_img/dots.jpg", package = "Rvision")) +#' dots_gray <- changeColorSpace(dots, "GRAY") +#' dots_bin <- dots_gray < 200 +#' contours <- findContours(dots_bin) +#' ix <- contours$contours[, 1] == 0 +#' approxPolyDP(contours$contours[ix, 2:3], 10) +#' +#' @export +approxPolyDP <- function(curve, epsilon, closed = TRUE) { + if (!is.matrix(curve)) + stop("curve must be a m x 2 matrix.") + + if (ncol(curve) != 2) + stop("curve must be a m x 2 matrix.") + + `_approxPolyDP`(curve, epsilon, closed) +} + + #' @title Pixel Values Along a Line Segment #' #' @description \code{improfile} finds all pixels intersected by a line segment diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml index f6e72bfb..d4024888 100644 --- a/docs/pkgdown.yml +++ b/docs/pkgdown.yml @@ -9,7 +9,7 @@ articles: z5_gpu: z5_gpu.html z6_queue: z6_queue.html z7_stack: z7_stack.html -last_built: 2023-08-04T10:50Z +last_built: 2023-08-08T12:51Z urls: reference: https://swarm-lab.github.io/Rvision/reference article: https://swarm-lab.github.io/Rvision/articles diff --git a/docs/reference/convexHull.html b/docs/reference/convexHull.html index 33e333cd..3ca17448 100644 --- a/docs/reference/convexHull.html +++ b/docs/reference/convexHull.html @@ -98,7 +98,7 @@

Author<

Examples

convexHull(rnorm(100), rnorm(100))
-#> [1]  7 55  8  4 87 80 48 64
+#>  [1]  3 80 86 43  5 87 76 93 30 70
 
 
diff --git a/docs/reference/fitEllipse.html b/docs/reference/fitEllipse.html index 6b957637..f2b2fc0f 100644 --- a/docs/reference/fitEllipse.html +++ b/docs/reference/fitEllipse.html @@ -119,16 +119,16 @@

Author<

Examples

fitEllipse(rnorm(100), rnorm(100))
 #> $angle
-#> [1] 175.1583
+#> [1] 59.89347
 #> 
 #> $height
-#> [1] 3.805757
+#> [1] 4.499532
 #> 
 #> $width
-#> [1] 2.914315
+#> [1] 3.404044
 #> 
 #> $center
-#> [1] -0.02007224 -0.06776221
+#> [1] -0.20713183 -0.01245182
 #> 
 
 
diff --git a/docs/reference/index.html b/docs/reference/index.html index c39d84f5..9a95aa9b 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -143,6 +143,11 @@

All functionsapproxPolyDP() + +
Calculate a Contour Perimeter or a Curve Length
+
+ arcLength()
Calculate a Contour Perimeter or a Curve Length
@@ -285,7 +290,7 @@

All functionsdestroyDisplay() destroyAllDisplays() -
Destroy Image Display
+
Destroy Image Display

dim(<Rcpp_Image>) @@ -320,7 +325,7 @@

All functionsdisplay()

-
Display Image Object
+
Display Image Object
distanceTransform() @@ -330,22 +335,22 @@

All functionsdrawArrow()

-
Draw Arrows on an Image
+
Draw Arrows on an Image
drawCircle()
-
Draw Circles on an Image
+
Draw Circles on an Image
drawEllipse()
-
Draw Ellipses on an Image
+
Draw Ellipses on an Image
drawLine()
-
Draw Lines on an Image
+
Draw Lines on an Image
drawPolyline() @@ -355,17 +360,17 @@

All functionsdrawRectangle()

-
Draw Rectangles on an Image
+
Draw Rectangles on an Image
drawRotatedRectangle()
-
Draw Rotated Rectangles on an Image
+
Draw Rotated Rectangles on an Image
drawText()
-
Draw Text on an Image
+
Draw Text on an Image
edgePreservingFilter() @@ -430,7 +435,7 @@

All functionsflip()

-
Flip an Image
+
Flip an Image
floodFill() @@ -690,7 +695,7 @@

All functionsnewDisplay()

-
Open New Image Display
+
Open New Image Display
niBlackThreshold() @@ -815,7 +820,7 @@

All functionsresize()

-
Resize an Image
+
Resize an Image
rotateScale() diff --git a/docs/reference/minAreaRect.html b/docs/reference/minAreaRect.html index 090fce67..5f157e10 100644 --- a/docs/reference/minAreaRect.html +++ b/docs/reference/minAreaRect.html @@ -100,16 +100,16 @@

Author<

Examples

minAreaRect(rnorm(100), rnorm(100))
 #> $angle
-#> [1] 1.715836
+#> [1] 81.68349
 #> 
 #> $height
-#> [1] 5.917526
+#> [1] 5.16795
 #> 
 #> $width
-#> [1] 4.508763
+#> [1] 4.448408
 #> 
 #> $center
-#> [1] -0.2853765  0.1885252
+#> [1] -0.5567193  0.2278657
 #> 
 
 
diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 7c82b15e..c3df2791 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -84,6 +84,9 @@ https://swarm-lab.github.io/Rvision/reference/api.html + + https://swarm-lab.github.io/Rvision/reference/approxPolyDP.html + https://swarm-lab.github.io/Rvision/reference/arcLength.html diff --git a/man/approxPolyDP.Rd b/man/approxPolyDP.Rd new file mode 100644 index 00000000..377672fd --- /dev/null +++ b/man/approxPolyDP.Rd @@ -0,0 +1,52 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/shape.R +\name{approxPolyDP} +\alias{approxPolyDP} +\title{Calculate a Contour Perimeter or a Curve Length} +\usage{ +approxPolyDP(curve, epsilon, closed = TRUE) +} +\arguments{ +\item{curve}{An m x 2 matrix of 2D coordinates.} + +\item{epsilon}{A numeric specifying the approximation accuracy. This is the +maximum distance between the original curve and its approximation.} + +\item{closed}{A logical indicating whether the curve is closed (perimeter) or +not (default: TRUE).} +} +\value{ +A matrix with two columns: + \itemize{ + \item{"x": }{the x coordinates of the approximated curve.} + \item{"y": }{the y coordinates of the approximated curve.} + } +} +\description{ +\code{approxPolyDP} approximates a curve or a polygon with + another curve/polygon with less vertices so that the distance between them + is less or equal to the specified precision. It uses the Douglas-Peucker + algorithm. +} +\examples{ +dots <- image(system.file("sample_img/dots.jpg", package = "Rvision")) +dots_gray <- changeColorSpace(dots, "GRAY") +dots_bin <- dots_gray < 200 +contours <- findContours(dots_bin) +ix <- contours$contours[, 1] == 0 +approxPolyDP(contours$contours[ix, 2:3], 10) + +} +\references{ +Douglas, D. H., & Peucker, T. K. (1973). ALGORITHMS FOR THE + REDUCTION OF THE NUMBER OF POINTS REQUIRED TO REPRESENT A DIGITIZED LINE OR + ITS CARICATURE. Cartographica: The International Journal for Geographic + Information and Geovisualization, 10(2), 112–122. + doi:10.3138/FM57-6770-U75U-7727 +} +\seealso{ +\code{\link{findContours}} +} +\author{ +Simon Garnier, \email{garnier@njit.edu} +} diff --git a/src/shape.h b/src/shape.h index 6306e87b..8c629f4e 100644 --- a/src/shape.h +++ b/src/shape.h @@ -354,14 +354,35 @@ Rcpp::List _minAreaRect(arma::Mat< float > points) { } double _arcLength(Rcpp::NumericMatrix curve, bool closed) { - std::vector< cv::Point > contourpoints(curve.nrow()); + std::vector< cv::Point > curvepoints(curve.nrow()); for (int i = 0; i < curve.nrow(); i++) { - contourpoints[i].x = curve(i, 0); - contourpoints[i].y = curve(i, 1); + curvepoints[i].x = curve(i, 0); + curvepoints[i].y = curve(i, 1); } - return cv::arcLength(contourpoints, closed); + return cv::arcLength(curvepoints, closed); +} + +Rcpp::NumericMatrix _approxPolyDP(Rcpp::NumericMatrix curve, double epsilon, bool closed) { + std::vector< cv::Point > curvepoints(curve.nrow()); + std::vector< cv::Point > approxpoints; + + for (int i = 0; i < curve.nrow(); i++) { + curvepoints[i].x = curve(i, 0); + curvepoints[i].y = curve(i, 1); + } + + cv::approxPolyDP(curvepoints, approxpoints, epsilon, closed); + Rcpp::NumericMatrix out(approxpoints.size(), 2); + colnames(out) = Rcpp::CharacterVector::create("x", "y"); + + for (int i = 0; i < approxpoints.size(); i++) { + out(i, 0) = approxpoints[i].x; + out(i, 1) = approxpoints[i].y; + } + + return out; } Rcpp::NumericMatrix _pline(Image& image, Rcpp::NumericVector xi, diff --git a/src/visionModule.cpp b/src/visionModule.cpp index c4268722..da4d5625 100644 --- a/src/visionModule.cpp +++ b/src/visionModule.cpp @@ -358,6 +358,7 @@ RCPP_MODULE(methods_Shape) { _["image2"], _["method"]), ""); function("_minAreaRect", &_minAreaRect, List::create(_["points"]), ""); function("_arcLength", &_arcLength, List::create(_["curve"], _["closed"]), ""); + function("_approxPolyDP", &_approxPolyDP, List::create(_["curve"], _["epsilon"], _["closed"]), ""); function("_pline", &_pline, List::create(_["image"], _["xi"], _["yi"], _["connectivity"], _["leftToRight"]), ""); }