I was trying to get the percentage of clouds in an image using OpenCV:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('path/to/img')
def create_clouds_mask(img_bgr):
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB) # from bgr to rgb
rgb_white = np.asarray([255, 255, 255]) # white
rgb_grey = np.asarray([138, 138, 138]) # grey
# pick colors from white to grey and creates a mask
mask = cv2.inRange(img_rgb, rgb_grey, rgb_white)
return mask
def cloud_coverage_perc(bgr_img, mask):
# from bgr to hsv (for comparison with the mask)
hsv_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2HSV)
res = cv2.bitwise_and(hsv_img, hsv_img, mask=mask)
ratio = cv2.countNonZero(mask)/(hsv_img.size/3)
perc = np.round(ratio*100, 2) # percentage of the clouds in the image
return res, perc
mask = create_clouds_mask(img)
res, perc = cloud_coverage_perc(img, mask)
print("Clouds perc: ", perc, "%")
plt.imshow(res)
plt.show()
the problem is that i can't find the correct range of colors, for example this image here view from the ISS
the result is the mask
it even takes the island as a part of the clouds, but if I try to higher the values of
rgb_grey = np.asarray([138, 138, 138]) # grey
then the percentage of clouds that are taken is very small.
What can I do to improve the code, so that the islands aren't a problem?