Skip to content
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

Panchromatic image sharpening method #32

Closed
aazuspan opened this issue Jun 19, 2021 · 6 comments · Fixed by #40
Closed

Panchromatic image sharpening method #32

aazuspan opened this issue Jun 19, 2021 · 6 comments · Fixed by #40
Assignees
Labels
enhancement New feature or request

Comments

@aazuspan
Copy link
Contributor

Hey @davemlz, what do you think about adding an ee.Image.panSharpen() method to eemont? I've implemented some sharpening algorithms before in Javascript, but it would be cool to have them accessible in Python. I think Landsat 7/8 are the only platforms on GEE with panchromatic bands, so it would probably only work with those collections. If you think that would be a good feature, I'd be happy to work on it!

Thanks!

@davemlz
Copy link
Owner

davemlz commented Jun 19, 2021

Wow, @aazuspan! geeSharp is amazing! Please, do it! :)

Here are some ideas:

  1. This method can be implemented for ee.Image and ee.ImageCollection classes. Here is the template for private functions that I use when a method works for both classes:
def _panSharpen(self, method, ...):
    """Computes pan sharpening...

    Parameters
    ----------
    self : ee.Image | ee.ImageCollection
        Image or image collection to pan sharpen.
    method : string
        Method used to compute pan sharpening.\n
        Available options:
            - 'GS' : Use Gram-Schmidt.
            - 'PCA' : Use Principal Component Analysis.
            - ...

    Returns
    -------
    ee.Image | ee.ImageCollection
        Pan sharpened image or image collection.
    """

    def L7(img):
        panSharpened = "something..."
        return panSharpened 

    def L8(img):
        panSharpened = "something..."
        return panSharpened 

    lookup = {        
        "LANDSAT/LC08/C01/T1_TOA": L8,
        "LANDSAT/LC08/C01/T1_RT_TOA": L8,
        "LANDSAT/LC08/C01/T2_TOA": L8,
        "LANDSAT/LE07/C01/T1_TOA": L7,
        "LANDSAT/LE07/C01/T1_RT_TOA": L7,
        "LANDSAT/LE07/C01/T2_TOA": L7
    }

    platformDict = _get_platform_STAC(self)

    if platformDict["platform"] not in list(lookup.keys()):
        warnings.warn("This platform is not supported for pan sharpening.")
        return self
    else:
        if isinstance(self, ee.image.Image):
            panSharpened = lookup[platformDict["platform"]](self)
        elif isinstance(self, ee.imagecollection.ImageCollection):
            panSharpened = self.map(lookup[platformDict["platform"]])
        return panSharpened 

This template is created in the common.py module and then imported into image.py and imagecollection.py modules (here an example for ee.ImageCollection):

from .common import _panSharpen

@extend(ee.imagecollection.ImageCollection)
def panSharpen(self, method = "GS", ...):
    """Computes pan sharpening...

    Parameters
    ----------
    self : ee.ImageCollection
        Image Collection to pan sharpen.
    method : string
        Method used to compute pan sharpening.\n
        Available options:
            - 'GS' : Use Gram-Schmidt.
            - 'PCA' : Use Principal Component Analysis.
            - ...

    Returns
    -------
    ee.ImageCollection
        Pan sharpened image collection.

    Examples
    ----------
    >>> ...
    """

    return _panSharpen(self, method, ...)
  1. I see that you also have a whole module for computing QA, that's awesome! Here is an idea to compute the QA while computing the panSharpen():
  • Add a new argument to the method (qa).
  • Now, since the QA is an ee.Number (or an ee.Array), the best way to add it to the image would be setting it as a property of the resulting image:
def _panSharpen(self, method, qa...):
    """Computes pan sharpening...

    Parameters
    ----------
    self : ee.ImageCollection
        Image Collection to pan sharpen.
    method : string
        Method used to compute pan sharpening.\n
        Available options:
            - 'GS' : Use Gram-Schmidt.
            - 'PCA' : Use Principal Component Analysis.
            - ...
    qa: string
        Method used to compute QA.\n
        Available options:
            - 'MSE'
            - 'PSNR'
            - ... 

    Returns
    -------
    ee.ImageCollection
        Pan sharpened image collection.
    """

    def L7(img):
        panSharpened = "something..."
        QA = "something..."
        return panSharpened.set({"eemont:PANSHARPEN_QA": QA}) 

    def L8(img):
        panSharpened = "something..."
        QA = "something..."
        return panSharpened.set({"eemont:PANSHARPEN_QA": QA}) 

    lookup = {        
        "LANDSAT/LC08/C01/T1_TOA": L8,
        "LANDSAT/LC08/C01/T1_RT_TOA": L8,
        "LANDSAT/LC08/C01/T2_TOA": L8,
        "LANDSAT/LE07/C01/T1_TOA": L7,
        "LANDSAT/LE07/C01/T1_RT_TOA": L7,
        "LANDSAT/LE07/C01/T2_TOA": L7
    }

    platformDict = _get_platform_STAC(self)

    if platformDict["platform"] not in list(lookup.keys()):
        warnings.warn("This platform is not supported for pan sharpening.")
        return self
    else:
        if isinstance(self, ee.image.Image):
            panSharpened = lookup[platformDict["platform"]](self)
        elif isinstance(self, ee.imagecollection.ImageCollection):
            panSharpened = self.map(lookup[platformDict["platform"]])
        return panSharpened 
  1. User Guide: Since this method is actually a whole set of methods, I think a page in the User Guide explaining it would be amazing! (just if you agree).

If you agree, please go to ./docs/guide/ and in there please create a new file (panSharpen.rst) with the user guide for this method :) feel free to use any of the other guides as an example and don't forget to add at the beginning your name: User guide created by Aaaron Zuspan :)

  1. Tutorials: If you want, create as many tutorials as you wish! 🚀

That's all! Feel free to do it :)

Let me know if you need anything else or if you need help with the template!

Cheers!

@aazuspan
Copy link
Contributor Author

Thanks for putting those templates together! I wasn't sure the best way to identify the platform and bands, but that looks perfect. And adding the quality values as image properties is genius!

I'll get started on adding these features and creating a guide and tutorials :)

@davemlz
Copy link
Owner

davemlz commented Jun 20, 2021

That's perfect! I'm going to assign you this Issue :)

Let me know if you need anything! 🚀

Cheers!

@davemlz davemlz added the enhancement New feature or request label Jun 20, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jun 24, 2021
@aazuspan
Copy link
Contributor Author

I've got a question for you, @davemlz! Some of the pan-sharpening algorithms need to match histograms between images. I was going to just write a private function to handle that in common.py, but I thought maybe it would be worth adding to eemont as a separate method: ee.Image.matchHistogram(other). What do you think?

Noel Gorelick wrote an awesome tutorial for histogram matching in JS that could be adapted pretty quickly. The only tricky thing is that each band in the source image has to be matched to a corresponding band in the target image. No problem if they're from the same collection, but matching a Landsat-8 to a Sentinel-2 or a NAIP image, for example, would be harder.

If you think that's worth adding, would you rather I make a separate issue/PR or include it with this one?

@davemlz
Copy link
Owner

davemlz commented Jun 25, 2021

Hi, @aazuspan!

Yes, that one is a nice feature and would be amazing to have it in eemont! 🚀 I think that an ee.Image.matchHistogram(other) would be very nice! But I also think this one should be more "flexible": Letting people decide which bands to get from each image, let them decide how many bands, also which images to use, and so on. Something like ee.Image.matchHistogram(targetImage, sourceBands, targetBands).

Let me know if that is possible! :) And yes, I think it could be better to record it in another Issue, but you can submit everything in one single PR if you want!

Cheers!

@aazuspan
Copy link
Contributor Author

Cool! I think being able to specify bands for histogram matching is a good solution, and it shouldn't be too hard to implement. I'll open a new issue for that.

aazuspan added a commit to aazuspan/eemont that referenced this issue Jun 28, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 1, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 3, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 3, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 3, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 6, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 8, 2021
…tion coefficient algorithm. Reproject original image before calculating QA. (davemlz#32)
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 9, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 10, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 10, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 11, 2021
aazuspan added a commit to aazuspan/eemont that referenced this issue Jul 12, 2021
davemlz pushed a commit that referenced this issue Jul 19, 2021
* Implement pansharpening (#32)

* Implement histogram matching (#35)

* Histogram matching tutorial (#35)

* Test match histogram method (#35)

* HPFA and PCS algorithms (#23)

* HPFA and PCS algorithms (#32)

* Docstrings and rename variables (#32)

* Add tests for pansharpening. Fix deprecation warning from ee.Image.geometry (#32)

* Implement QA and fix docstrings (#32)

* Docstrings and Black (#32)

* Remove leftover line

* Add more sharpening platforms and implement RASE, ERGAS, and DIV QA methods (#32)

* Calculate ERGAS and RASE image-wise instead of band-wise. Add correlation coefficient algorithm. Reproject original image before calculating QA. (#32)

* Fix missing assignment

* Implement luminance, contrast, and UIQ QA metrics (#32)

* Add QA docstrings and references and re-organize functions (#32)

* Add pansharpening tutorial (#32)

* Add qa to tests (#32)

* Add pansharpening guide (#32)

* Add histogram matching guide (#35)

* Refactor sharpener and qa metric system (#32)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants