% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/algorithm-itd.R
\name{itd_lmf}
\alias{itd_lmf}
\alias{lmf}
\title{Individual Tree Detection Algorithm}
\usage{
lmf(ws, hmin = 2, shape = c("circular", "square"), ws_args = "Z")
}
\arguments{
\item{ws}{numeric or function. Length or diameter of the moving window used to detect the local
maxima in the units of the input data (usually meters). If it is numeric a fixed window size is used.
If it is a function, the function determines the size of the window at any given location on the canopy.
By default function takes the height of a given pixel or point as its only argument and return the
desired size of the search window when centered on that pixel/point. This can be controled with
the `ws_args` parameter}

\item{hmin}{numeric. Minimum height of a tree. Threshold below which a pixel or a point
cannot be a local maxima. Default is 2.}

\item{shape}{character. Shape of the moving window used to find the local maxima. Can be "square"
or "circular".}

\item{ws_args}{list. Named list of argument for the function `ws` if `ws` is a function.}
}
\description{
This function is made to be used in \link{locate_trees}. It implements an algorithm for tree
detection based on a local maximum filter. The windows size can be fixed or variable and its
shape can be square or circular. The internal algorithm works either with a raster or a point cloud.
It is deeply inspired by Popescu & Wynne (2004) (see references).
}
\examples{
LASfile <- system.file("extdata", "MixedConifer.laz", package="lidR")
las <- readLAS(LASfile, select = "xyzi", filter = "-inside 481250 3812980 481300 3813050")

# =================
# point-cloud-based
# =================

# 5x5 m fixed window size
ttops <- locate_trees(las, lmf(5))

#plot(las) |> add_treetops3d(ttops)

# variable windows size
f <- function(x) { x * 0.07 + 3}
ttops <- locate_trees(las, lmf(f))

#plot(las) |> add_treetops3d(ttops)

# Very custom variable windows size
f <- function(x, y, z) { x * 0.07 + y * 0.01 + z}
ws_args <- list(x = "Z", y = "Intensity", z = 3)
ttops <- locate_trees(las, lmf(f, ws_args = ws_args))

# ============
# raster-based
# ============

chm <- rasterize_canopy(las, res = 1, p2r(0.15), pkg = "terra")
ttops <- locate_trees(chm, lmf(5))

plot(chm, col = height.colors(30))
plot(sf::st_geometry(ttops), add = TRUE, col = "black", cex = 0.5, pch = 3)

# variable window size
f <- function(x) { x * 0.07 + 3 }
ttops <- locate_trees(chm, lmf(f))

plot(chm, col = height.colors(30))
plot(sf::st_geometry(ttops), add = TRUE, col = "black", cex = 0.5, pch = 3)
}
\references{
Popescu, Sorin & Wynne, Randolph. (2004). Seeing the Trees in the Forest: Using Lidar and
Multispectral Data Fusion with Local Filtering and Variable Window Size for Estimating Tree Height.
Photogrammetric Engineering and Remote Sensing. 70. 589-604. 10.14358/PERS.70.5.589.
}
\seealso{
Other individual tree detection algorithms: 
\code{\link{itd_manual}}
}
\concept{individual tree detection algorithms}
