One Dimension

Identifying trees from lidar data and creating a site survey

In this post–
I explore our goals for managing the trees on our property, particularly western juniper which has become a nuisance in eastern and central Oregon due to fire suppression. I develop a method to algorithmically identify all the trees on the property with lidar data and create a basic site survey.
a survey of the property, lidar image, and satellite image

Our property is located in the transition zone where the the ponderosa pines that cover the eastern slopes of the Cascades gradually give way to western juniper and sagebrush. On the property there are two types of trees: mature (>80 yo) ponderosa pines (pinus ponderosa) and young (<50 yo) western junipers (juniperus occidentalis).

As we begin to install utilities, a driveway, and buildings, we’d like to keep the ponderosa pines undisturbed. They’re beautiful trees and take at least a human lifetime to get established. Old stands of ponderosa pines are lovely places to sit and spend an afternoon.

A grove of ponderosa pines
A stand of old ponderosa pines encountered driving down logging roads in Jefferson County, Oregon.
A grove of ponderosa pines

Juniper is taking over the world

Juniper, on the other hand, is less precious.

Western juniper is a common part of the central and eastern Oregon landscape. Junipers can live for over a thousand years and become gnarled and twisted old relics.

An old juniper
A twisted old juniper.

However, since western settlement began around 1870, juniper has been expanding beyond its range and taking over other ecosystems. I found this publication from OSU to be a nice summary of the situation.

The expansion is primarily because of the fire suppression that began in the early 1900’s. Lightning fires would have normally killed off young junipers before they reached maturity, leaving only the trees on rock outcroppings and isolated locations. Without fires, the junipers grow unencumbered.

An old view of Pilot Butte
Pilot Butte in Bend, Oregon around 1900. The northeast (right) side of the butte appears to be sparesely covered in ponderosa pines. The foreground is primarily sagebrush with a few scattered junipers.
A modern view of Pilot Butte
The same view of Pilot Butte today from Google Earth. The northeast side is now densely covered in young juniper with relatively few remaining pines. The south side (left) of the butte burned in 1968, which is likely why it’s sparser. While the foreground is much more developed, many juniper trees have grown up there too.

This results in ecosystems dominated by juniper. In sagebrush steppe, junipers grow to shade out the sage and eventually prevent anything else from growing by monopolizing all available soil moisture. In transitional zones junipers grow up under the ponderosa pines and pull moisture away, eventually stressing and the mature pine trees and leaving them susceptible to beetle attack.

I’ve noticed this dynamic on our property; lots of small junipers grow up around the pines. On the whole five acres there’s many young juniper and just one young ponderosa pine. Interestingly, there are stumps from the old-growth pines that used to cover the property, more pines than there are today. I’m guessing that the pines weren’t replaced because the the fast-growing juniper created a canopy that prevented the shade-intolerant ponderosa pines from seeding and growing up.

A stump surrounded by juniper
Juniper taking over on our property. A pine stump (left) now surrounded by scraggly juniper and an old snag (right) with young juniper grown up since it died.

Where are the pines?

In light of the junipers’ aggressive colonization efforts, our general management strategy is to preserve the mature ponderosa pines and reduce the density of junipers.

As we plan for development of the property, it’s important to know where the pines are in order to work around them. This is often accomplished with a survey; a surveyor would be able to record the locations of trees over a certain diameter. However we don’t have a survey.

Another option would be to walk the property and record the coordinates of each tree. The only tool I have with GPS is my phone, which seems to have variable accuracy around 15-20 feet. That’s not accurate enough for me.

Working in QGIS, I decided to try to use freely available GIS datasets to identify the location of the ponderosa pine trees from aerial imagery.

Hand-classifying trees with satellite imagery

I started with satellite imagery available through the USDA’s National Agriculture Imagery Program. It isn’t limited to agricultural land; the dataset contains imagery for the entire CONUS in 60 or 30 centimeter per-pixel resolution.

Satellite imagery of Deschutes County, Oregon
NAIP imagery of Deschutes County, Oregon. Over 100 inches of precipitation falls on the far western areas of the image and less than 10 inches on the far east.
Satellite imagery of two lakes amidst a sea of pines
A section of imagery over Newberry Caldera.

I began to pick out the locations of the ponderosa pines from the satellite images. I found myself relying on the length of the trees’ shadow to distinguish between the taller pines from the junipers. In areas where the shadows were unclear it wasn’t possible to positively identify specific tree locations. I’d need another method.

Satellite imagery of the property
NAIP imagery of the entire property (left) and an enlarged section (right). It’s difficult to distinguish which tree is a pine and which is a juniper.

The shadows got me thinking about alternative data sources. Since the trees on the property are spaced out and don’t form a dense canopy, it could be possible to use aerially-captured lidar data to detect them.

Algorithmically identifying trees with lidar data

I don’t know if there’s a “proper” way to extract tree positions from lidar data, but what follows is the path I took to arrive there while figuring it out as I went. It might not be optimal, but it ended up working.

I found high-resolution lidar data available through the State of Oregon’s Department of Geology and Mineral Industries. There’s two forms of lidar that are useful here: highest hit and bare earth. Highest hit lidar provides height readings for everything: each pixel represents the height of the underlying tree canopy, buildings, or ground. Bare earth is as it sounds: each pixel represents the height of the ground. Subtracting the two creates a canopy height map: the height of any trees or buildings off the ground.

Subtracting the highest hit lidar from the bare earth to create a canopy map

The trees’ center points are the local maximum; the highest-value pixel in each cluster of non-zero value pixels. To find these highest-value pixels, I ran the GRASS GIS algorithm r.neighbors that creates a square around each pixel (5×5 in this case) and sets the pixel to the highest value in that square. I then subtracted the two rasters and set the locally highest-value pixels to 1.

Finding the local maximum by subtracting the canopy map from the highest-value-neighbors

Next, I cleaned up the results by setting all non-one values to zero, creating a binary mask. However not all the points included in the mask are true local maximum. This is because when running the r.neighbors algorithm I set the square size to 5, so in regions larger than 5 pixels that weren’t part of a tree the background noise was amplified and a very small maximum was found. To clean this noise up, I multiplied the mask with the canopy map to get the height values for each maximum, then filtered out any points with values less than 10.

Cleaning up the results to produce the final local maximum points

To create points representing the tree positions I converted the pixels to polygons with gdal_polygonize, then ran the QGIS centroid algorithm to find the centroids of each single-pixel sized polygon.

Converting the pixels to points

The results are decent! At most the points appear to be off a few pixels. With each pixel being 30cm, the accuracy is conservatively around 90cm, though most points appear dead on.

The resulting points over the lidar imagery
The points over the satellite imagery

With each tree associated with its height from the canopy map, I made a histogram of all the tree heights. There are 275 trees on the property, most falling in the 20-40ft height range.

A histogram of tree heights

The ponderosa pines are more mature and taller than the junipers, starting around 40ft and up. Using this rough heuristic it’s easy to estimate which trees are pines.

A survey showing the tree positions, colored by species
The final survey. Circles denote trees, the size of the circle is dependent on the height of the tree. An estimation of tree species is shown on the right, pines are green and junipers are orange.

Next up: verification and thinning trees

The next step is to take this survey and walk the site to verify the trees detected through this process are really there and marked as the correct species. After that I’ll mark junipers that should be removed around the pines and in areas where they’re growing too densely. Then I’ll get out a chainsaw and implement the plan.