-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discussion: add a masking API to odc.geo to help people do opinionated masking of well known products #117
Comments
Some thoughts. Alex thinks something simple like baking in the SCL, fmask and qa_pixel lookup tables, would be great. Then being able to do something like @Kirill888 said:
and:
@robbibt said:
|
This would make masking so much easier throughout the ODC ecosystem. For usability, it would be fantastic to be able to easily compute masks using the existing
etc. Once |
Do you think it's a good idea to do I kind of think it's better to keep it a bit lower, so folks know what they're doing. That said, the subtleties of choosing which cloud flags and options around opening/dilation etc. are pretty damn fiddly and I use other people's values all the time! |
All Creating a custom mask from a band like |
Just adding my two cents here which is largely just to support the idea/comments above, and to provide an example of similar functionality that exists elsewhere. Something I've learned that's great about working with GEE in python are the wrapper functions groups have built around QA masking. For example, eemont provides accessor functions for rescaling and masking common surface reflectance datasets e.g.
Or both steps can be combined into the simpler Given there are multitude of provenances for xarray datasets something as clean as this probably isn't possible or desirable, but if we could get to the stage of something like I doubt I'd be much use in any back-end work on this but if you're looking for test dummies later on I'm happy to test the functions and provide feedback. |
Alright we are getting into many other desired functionalities here, which is fine but they probably deserve their own issue. We can keep this one as a discussion related to masking of pixels, and create new issue for specific work tasks. I figure is that there are several lower level functionalities related to "pixel masking":
A lot of these can be implemented efficiently using |
Yep, I think those functionalities would address all the main pixel masking-related tasks I can think of. A bunch of the existing masking tools from the |
Related STAC extenion https://github.com/stac-extensions/classification Example of use: curl -s https://planetarycomputer.microsoft.com/api/stac/v1/collections/landsat-c2-l2/items/LC09_L2SR_080122_20240113_02_T2 \
| jq .assets.qa_pixel Sample Asset JSON{
"href": "https://landsateuwest.blob.core.windows.net/landsat-c2/level-2/standard/oli-tirs/2024/080/122/LC09_L2SR_080122_20240113_20240114_02_T2/LC09_L2SR_080122_20240113_20240114_02_T2_QA_PIXEL.TIF",
"classification:bitfields": [
{
"name": "fill",
"length": 1,
"offset": 0,
"classes": [
{
"name": "not_fill",
"value": 0,
"description": "Image data"
},
{
"name": "fill",
"value": 1,
"description": "Fill data"
}
],
"description": "Image or fill data"
},
{
"name": "dilated_cloud",
"length": 1,
"offset": 1,
"classes": [
{
"name": "not_dilated",
"value": 0,
"description": "Cloud is not dilated or no cloud"
},
{
"name": "dilated",
"value": 1,
"description": "Cloud dilation"
}
],
"description": "Dilated cloud"
},
{
"name": "cirrus",
"length": 1,
"offset": 2,
"classes": [
{
"name": "not_cirrus",
"value": 0,
"description": "Cirrus confidence is not high"
},
{
"name": "cirrus",
"value": 1,
"description": "High confidence cirrus"
}
],
"description": "Cirrus mask"
},
{
"name": "cloud",
"length": 1,
"offset": 3,
"classes": [
{
"name": "not_cloud",
"value": 0,
"description": "Cloud confidence is not high"
},
{
"name": "cloud",
"value": 1,
"description": "High confidence cloud"
}
],
"description": "Cloud mask"
},
{
"name": "cloud_shadow",
"length": 1,
"offset": 4,
"classes": [
{
"name": "not_shadow",
"value": 0,
"description": "Cloud shadow confidence is not high"
},
{
"name": "shadow",
"value": 1,
"description": "High confidence cloud shadow"
}
],
"description": "Cloud shadow mask"
},
{
"name": "snow",
"length": 1,
"offset": 5,
"classes": [
{
"name": "not_snow",
"value": 0,
"description": "Snow/Ice confidence is not high"
},
{
"name": "snow",
"value": 1,
"description": "High confidence snow cover"
}
],
"description": "Snow/Ice mask"
},
{
"name": "clear",
"length": 1,
"offset": 6,
"classes": [
{
"name": "not_clear",
"value": 0,
"description": "Cloud or dilated cloud bits are set"
},
{
"name": "clear",
"value": 1,
"description": "Cloud and dilated cloud bits are not set"
}
],
"description": "Clear mask"
},
{
"name": "water",
"length": 1,
"offset": 7,
"classes": [
{
"name": "not_water",
"value": 0,
"description": "Land or cloud"
},
{
"name": "water",
"value": 1,
"description": "Water"
}
],
"description": "Water mask"
},
{
"name": "cloud_confidence",
"length": 2,
"offset": 8,
"classes": [
{
"name": "not_set",
"value": 0,
"description": "No confidence level set"
},
{
"name": "low",
"value": 1,
"description": "Low confidence cloud"
},
{
"name": "medium",
"value": 2,
"description": "Medium confidence cloud"
},
{
"name": "high",
"value": 3,
"description": "High confidence cloud"
}
],
"description": "Cloud confidence levels"
},
{
"name": "cloud_shadow_confidence",
"length": 2,
"offset": 10,
"classes": [
{
"name": "not_set",
"value": 0,
"description": "No confidence level set"
},
{
"name": "low",
"value": 1,
"description": "Low confidence cloud shadow"
},
{
"name": "reserved",
"value": 2,
"description": "Reserved - value not used"
},
{
"name": "high",
"value": 3,
"description": "High confidence cloud shadow"
}
],
"description": "Cloud shadow confidence levels"
},
{
"name": "snow_confidence",
"length": 2,
"offset": 12,
"classes": [
{
"name": "not_set",
"value": 0,
"description": "No confidence level set"
},
{
"name": "low",
"value": 1,
"description": "Low confidence snow/ice"
},
{
"name": "reserved",
"value": 2,
"description": "Reserved - value not used"
},
{
"name": "high",
"value": 3,
"description": "High confidence snow/ice"
}
],
"description": "Snow/Ice confidence levels"
},
{
"name": "cirrus_confidence",
"length": 2,
"offset": 14,
"classes": [
{
"name": "not_set",
"value": 0,
"description": "No confidence level set"
},
{
"name": "low",
"value": 1,
"description": "Low confidence cirrus"
},
{
"name": "reserved",
"value": 2,
"description": "Reserved - value not used"
},
{
"name": "high",
"value": 3,
"description": "High confidence cirrus"
}
],
"description": "Cirrus confidence levels"
}
],
"type": "image/tiff; application=geotiff; profile=cloud-optimized",
"roles": [
"cloud",
"cloud-shadow",
"snow-ice",
"water-mask"
],
"title": "Pixel Quality Assessment Band",
"description": "Collection 2 Level-1 Pixel Quality Assessment Band (QA_PIXEL)",
"raster:bands": [
{
"unit": "bit index",
"nodata": 1,
"data_type": "uint16",
"spatial_resolution": 30
}
]
} |
I agree with these points as well and have a few additional thoughts/comments:
|
I agree that scaling/offsets are a huge pain point for our users - anything we can do to make that stuff easier would be extremely valuable. The masking tools from |
Thanks for the great discussion so far. I agree that opionated cloud masking is a really useful function, but am curious about whether it belongs in odc-geo, or whether it should have a different home. If you're interested, please have a look at this discussion I've started: opendatacube/datacube-core#1566 |
As discussed on Slack, the OpenDataCube has metadata and functionality to handle masking certain flags in a simple way.
It's not documented, whoops, but has a bunch of code around it.
The new
odc-stac
tool doesn't use the ODC metadata, and as such, I've been doing cloud masking ad-hoc all over the place.I think we should set up some kind of opinionated mask tooling, and after discussion, @robbibt and @Kirill888 both agree that it makes sense to do it here in
odc-geo
.This discussion is to capture thoughts on what a high- and low-level API might like and what they'll do.
The text was updated successfully, but these errors were encountered: