I'm trying to remove clouds from Landsat 5,7 and 8 data. I'm also trying to do this using only open source options, avoiding ArcGIS. I'm familiar with python and have some QGIS experience. Originally, I was trying to use the Semi-Automatic Classification model in QGIS, but it is giving me a lot of problems, and doesn't always output actual classifications (it often just returns a uniformly valued square...). Can anyone point me in the direction of a better option?


4 Answers 4


I have managed to identify cloud pixels in Landsat 8 scenes using the following code. I have included some python / pseudo-code below which will return possible cloud pixels. This is the first pass of identifying the potential cloud layer taken from this paper by Zhu and Woodcock (2014).

The paper also details a second pass that further refines the result by excluded misidentified cloud pixels. You should have a look at that too. The method was developed for Landsat 7 so it should work for all Landsat cases.

def calc_ndsi():
     green = get_green_band()
     swir = get_swir_band()
     return (green - swir)/(green + swir)

def calc_ndvi():
    nir = get_nir_band()
    red = get_red_band()
    return (nir - red)/(nir + red)

def calc_basic_test():
    band_7_test = get_band_seven()
    temp_test = where temp is less than 27 deg C
    ndsi_test = where calc_ndsi < 0.8
    ndvi_test = where calc_ndvi < 0.8
    basic_test = np.logical_and.reduce((band_7_test,
    return basic_test

def calc_whiteness():
    blue = get blue
    green = get green
    red = get red
    mean_vis = (blue + green + red) / 3
    whiteness = (np.abs((blue - mean_vis)/mean_vis) + 
             np.abs((green - mean_vis)/mean_vis) +
             np.abs((red - mean_vis)/mean_vis))
    whiteness[np.where(whiteness>1)] = 1
    return whiteness

def calc_whiteness_test():
    whiteness_test = where calc_whiteness() < 0.7
    return whiteness_test

def calculate_hot_test():
    band = 'rtoa_'
    blue = get blue
    red = get red
    hot_test = (blue - 0.5*red - 0.08) > 0
    return hot_test

def swirnir_test():
    nir = get NIR
    swir = get SWIR
    return (nir/swir) > 0.75

def calc_pcp():
    return np.logical_and.reduce((calc_basic_test(),

So, calc_pcp() will identify the potential cloud pixels in your image.

Note that this method uses the TIRS bands (to get the temperature) in Landsat 8 which are currently not working. Additionally, this method uses data which has already undergone atmospheric correction.

Identifying clouds in remote sensing images is more than a colour processing issue, although calculating the 'whiteness' of the cloud is included in the test.

You should compare the results you get with the Landsat 8 Quality Assessment band.


May I suggest taking a look at fmask by Zhe Zhu


  • neither Python nor QGIS


  • availlable as matlab or C executable
  • great performance in detecting clouds as well as cloud shadows
  • straightforward use

I highly recommend giving it a try. The executables can be obtained from the links and so far our team hasn't found a superior product which is distributed free of charge.

  • Would people be interested in a python version? I have got pretty good results from a python version of fmask that I've built. If there is a need for it I could publish the code. Commented Jan 12, 2015 at 13:07
  • Is it the code working for LT8 before failure of the TIRS or the one allready built for Sentinel-2 (fmask version 3.2 and higher)? Anyway: I'm interested.
    – Kersten
    Commented Jan 12, 2015 at 13:15
  • I am busy implementing the use of the 'cirrus' band in L8. I'll let you know how it goes. The failure of the TIRS meant a bit of a rewrite. I'm glad there is some interest. Commented Jan 12, 2015 at 14:03

take a look at this page http://gistack.rozblog.com/post/32/qa_cloudmask_ports.html at the bottom of this page you can download an erdas imagine model it takes landsat8 QA band and replace cloud pixel values with 0


UPDATE 2022: updated to use the Wayback machine on the link I was linking to in 2015. There. Now the link works

You might try this solution : Disclaimer

I've never removed cloud data before.


It seems like a color processing issue: clouds are a white-gray color. As long as you don't have snow or other large white objects in your ground plane, you could do a search for all pixels that match a criteria of having full red AND full green AND and full blue colors. as to how to do this... try the solution posted above.

  • 1
    There are many other objects in these images which can be as white as clouds. Using this method would not be sufficient in identifying cloud pixels. Commented Jan 8, 2015 at 11:25
  • The link you provided has no any resources, kindly update Commented Jun 13, 2022 at 8:08
  • updated resources.
    – Snazzer
    Commented Jul 13, 2022 at 4:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.