Detect vegetation using opencv on satellite images

I am trying to estimate the area of vegetation in square meters on satellite photos, from the colors. I don’t have a training dataset, and therefore cannot do machine learning. So I know the results will not be very good, but I try anyway.

To do this, I apply a filter on the colors thanks to cv2.inRange.

import numpy as np
import cv2

img = cv2.imread('staticmap.png')
upperbound = np.array([70, 255,255])
lowerbound = np.array([40, 40,40])
mask = cv2.inRange(img, lowerbound, upperbound)
imask = mask>0
white = np.full_like(img, [255,255,255], np.uint8)

result = np.zeros_like(img, np.uint8)
result[imask] = white[imask]

cv2.imshow(winname = 'satellite image', mat = img)
cv2.imshow('vegetation detection', result)

cv2.waitKey(0) 
cv2.destroyAllWindows() 

This gives the following results

enter image description here

So it seems that the detection is not too bad. Now, I would like, from the density of white pixels, detect the areas where there is vegetation and areas where there is not. I imagine an output like this : enter image description here

Are there any open cv functions that can do this?

Answer

You could consider using a Gaussian blur followed by Otsu thresholding like this:

import cv2

# Load image as greyscale
im = cv2.imread('veg.jpg', cv2.IMREAD_GRAYSCALE)

# Apply blur
blur = cv2.GaussianBlur(im,(19,19),0)

# Otsu threshold
_,thr = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

enter image description here