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 @@
-
dim(<Rcpp_Image>)
@@ -320,7 +325,7 @@
- - Display
Image
Object
+ - Display
Image
Object
-
distanceTransform()
@@ -330,22 +335,22 @@
- - 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 @@
- - 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 @@
- - Open New
Image
Display
+ - Open New
Image
Display
-
niBlackThreshold()
@@ -815,7 +820,7 @@
- - 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"]), "");
}