[GRASS-SVN] r69026 - in grass-addons/grass7/imagery: . i.fusion.hpf i.fusion.hpf/licenses

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Jul 22 12:09:47 PDT 2016


Author: nikosa
Date: 2016-07-22 12:09:47 -0700 (Fri, 22 Jul 2016)
New Revision: 69026

Added:
   grass-addons/grass7/imagery/i.fusion.hpf/
   grass-addons/grass7/imagery/i.fusion.hpf/README.md
   grass-addons/grass7/imagery/i.fusion.hpf/constants.py
   grass-addons/grass7/imagery/i.fusion.hpf/high_pass_filter.py
   grass-addons/grass7/imagery/i.fusion.hpf/i.fusion.hpf.html
   grass-addons/grass7/imagery/i.fusion.hpf/i.fusion.hpf.py
   grass-addons/grass7/imagery/i.fusion.hpf/licenses/
   grass-addons/grass7/imagery/i.fusion.hpf/licenses/DEMO.TXT
   grass-addons/grass7/imagery/i.fusion.hpf/licenses/DEMONSTRATION.TXT
   grass-addons/grass7/imagery/i.fusion.hpf/test_high_pass_filter.py
Log:
Added i.fusion.hpf

Added: grass-addons/grass7/imagery/i.fusion.hpf/README.md
===================================================================
--- grass-addons/grass7/imagery/i.fusion.hpf/README.md	                        (rev 0)
+++ grass-addons/grass7/imagery/i.fusion.hpf/README.md	2016-07-22 19:09:47 UTC (rev 69026)
@@ -0,0 +1,151 @@
+`i.fusion.hpf` is a GRASS-GIS module to combine high-resolution 
+panchromatic data with lower resolution multispectral data, resulting in an 
+output with both excellent detail and a realistic representation of original 
+multispectral scene colors.
+
+The process involves a convolution using a High Pass Filter (HPF) on the high 
+resolution data, then combining this with the lower resolution multispectral 
+data.
+
+Optionally, a linear histogram matching technique is performed in a way that 
+matches the resulting Pan-Sharpened imaged to them statistical mean and standard 
+deviation of the original multi-spectral image.
+
+Source: Gangkofner, 2008
+
+Algorithm description
+=====================
+
+1.  Computing ratio of low (Multi-Spectral) to high (Panchromatic) resolutions
+
+2.  High Pass Filtering the Panchromatic Image
+
+3.  Resampling MSX image to the higher resolution
+
+4.  Adding weighted High-Pass-Filetred image to the upsampled MSX image
+
+5.  Optionally, matching histogram of Pansharpened image to the one of the 
+original MSX image
+
+## From the original paper
+--------------------------
+
+> Step 1: HP Filtering of the High-resolution Image to Extract the Structural
+> Detail
+
+> Step 2: Adding the HP Filtered Image to Each Band of the Multispectral Image
+> Using a Standard Deviation-based Injection Model
+
+> Step 3: Linear Histogram Match to Adapt SD and Mean of the Merged Image Bands
+> to Those of the Original MS Image Bands
+
+> Figure 1:
+
+     ____________________________________________________________________________
+    +                                                                            +
+    | Pan Img ->  High Pass Filter  ->  HP Img                                   |
+    |                                      |                                     |
+    |                                      v                                     |
+    | MSx Img ->  Weighting Factors ->  Weighted HP Img                          |
+    |       |                              |                                     |
+    |       |                              v                                     |
+    |       +------------------------>  Addition to MSx Img  =>  Fused MSx Image |
+    +____________________________________________________________________________+
+
+
+Installation
+============
+
+## Requirements
+------------
+
+see [GRASS Addons SVN repository, README file, Installation - Code Compilation](https://svn.osgeo.org/grass/grass-addons/README)
+
+## Steps
+
+Making the script `i.fusion.hpf` available from within any GRASS-GIS ver. 7.x session, may be done via the following steps:
+
+1.  launch a GRASS-GIS’ ver. 7.x session
+
+2.  navigate into the script’s source directory
+
+3.  execute `make MODULE_TOPDIR=$GISBASE`
+
+Usage
+=====
+
+After installation, from within a GRASS-GIS session, see help details via `i.fusion.hpf --help`
+
+## Remarks
+
+-   easy to use, i.e.:
+ * for one band `i.fusion.hpf pan=Panchromatic msx=${Band}`
+ * for multiple bands `i.fusion.hpf pan=Panchromatic msx=Red,Green,Blue,NIR`
+
+-   easy to test various parameters that define the High-Pass filter’s *kernel size* and *center value*
+
+-   should work with **any** kind of imagery (think of bitness)
+
+-   the "black border" effect, possibly caused due to a non-perfect match of the high vs. the low resolution 
+of the input images, can be trimmed out by using the `trim` option --a floating point "trimming factor" 
+with which to multiply the pixel size of the low resolution image-- and shrink the extent of the output image
+
+Implementation notes
+====================
+
+-   First commit on Sat Oct 25 12:26:54 2014 +0300
+
+-   Working state reached on Tue Nov 4 09:28:25 2014 +0200
+
+
+## To Do
+
+- Go through <http://trac.osgeo.org/grass/wiki/Submitting/Python>
+
+- Access input raster by row I/O ?
+
+- Proper command history tracking. Not all "r" modules do it... ?
+
+- Add timestamps (r.timestamp)
+
+- Deduplicate code where applicable
+
+- Make the -v messages shorter, yet more informative (ie report center cell)
+
+- Test. Will it compile in other systems?
+
+- Checking options to integrate in `i.pansharpen`. Think of FFM methods vs. 
+Others? 
+
+- Who else to thank?  Transfer from archive/
+- Improve [Documentation.lyx](https://github.com/NikosAlexandris/i.fusion.hpf/blob/master/lyx/Documentation.lyx)
+
+## Questions
+
+- To Ask!
+
+References
+==========
+
+- Gangkofner, U. G., Pradhan, P. S., and Holcomb, D. W. (2008). Optimizing
+the high-pass filter addition technique for image fusion.
+PHOTOGRAMMETRIC ENGINEERING & REMOTE SENSING, 74(9):1107–1118.
+
+- “ERDAS IMAGINE.” Accessed March 19, 2015. http://doc.hexagongeospatial.com/ERDAS%20IMAGINE/ERDAS_IMAGINE_Help/#ii_hpfmerge_mergedialog.htm.
+
+
+- Aniruddha Ghosh & P.K. Joshi (2013) Assessment of pan-sharpened very high-resolution WorldView-2 images, International Journal of Remote Sensing, 34:23, 8336-8359
+
+Ευχαριστώ
+=========
+
+- Nikos Ves
+- Ranjith, <https://class.coursera.org/interactivepython-005/forum/profile?user_id=9361576>
+- Anonymous on coursera's discussion forums
+- Pietro Zambelli
+- StackExchange contributors
+  - <http://stackoverflow.com/a/1140966/1172302>
+  - <http://stackoverflow.com/a/275025/1172302>
+- Yann Chemin
+- Aniruddha Ghosh
+- Παναγιώτης Μαυρογιώργος (https://github.com/pmav99)

Added: grass-addons/grass7/imagery/i.fusion.hpf/constants.py
===================================================================
--- grass-addons/grass7/imagery/i.fusion.hpf/constants.py	                        (rev 0)
+++ grass-addons/grass7/imagery/i.fusion.hpf/constants.py	2016-07-22 19:09:47 UTC (rev 69026)
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+#-*- coding:utf-8 -*-
+
+"""
+ at author: Nikos Alexandris | October 2014
+"""
+
+"""
+Constants for the HPFA Image Fusion Technique:
+Kernel Size, Center Value, Modulation Factor (all depend on Resolution Ratio).
+
+Sources:
+
+- "Optimizing the High-Pass Filter Addition Technique for Image Fusion",
+Ute G. Gangkofner, Pushkar S. Pradhan, and Derrold W. Holcomb (2008).
+
+- “ERDAS IMAGINE.” Accessed March 19, 2015.
+http://doc.hexagongeospatial.com/ERDAS%20IMAGINE/ERDAS_IMAGINE_Help/#ii_hpfmerge_mergedialog.htm.
+
+"""
+
+RATIO_RANGES = (
+    (1, 2.5),
+    (2.5, 3.5),
+    (3.5, 5.5),
+    (5.5, 7.5),
+    (7.5, 9.5),
+    (9.5, float('inf')))
+
+KERNEL_SIZES = (5, 7, 9, 11, 13, 15)
+
+MATRIX_PROPERTIES = zip(RATIO_RANGES, KERNEL_SIZES)
+
+
+# Replicating ERDAS' Imagine parameters -------------------------------------
+CENTER_CELL = {
+    'Low': [24, 48, 80, 120, 168, 336],
+    'Mid': [28, 56, 93, 150, 210, 392],
+    'High': [32, 64, 106, 180, 252, 448]}
+
+# Can't find a unique sequence pattern, so... python fun below: =============
+#ks = (5, 7, 9, 11, 13, 15)
+#lo = list([(s**2-1) for s in ks[0:-1]])
+#lo.append(int((ks[-1]**2-1)*1.5))
+#inc = list([v/6 for v in lo[0:3]])
+#inc.extend([v/4 for v in lo[3:5]])
+#inc.append(lo[-1]/6)
+#mi = list([a + b for a, b in zip(lo, inc)])
+#hi = list([a + b for a, b in zip(mi, inc)])
+#CENTER_CELL = {'High': hi, 'Low': lo, 'Mid': mi}
+# ===========================================================================
+
+
+MODULATOR = {
+    'Min': [0.20, 0.35, 0.35, 0.50, 0.65, 1.00],
+    'Mid': [0.25, 0.50, 0.50, 0.65, 1.00, 1.35],
+    'Max': [0.30, 0.65, 0.65, 1.00, 1.40, 2.00]}
+
+MODULATOR_2 = {'Min': 0.25, 'Mid': 0.35, 'Max': 0.50}
+
+FILTER_TEMPLATE = """\
+MATRIX    {size}
+{kernel}
+DIVISOR   {divisor}
+TYPE      {type}
+"""

Added: grass-addons/grass7/imagery/i.fusion.hpf/high_pass_filter.py
===================================================================
--- grass-addons/grass7/imagery/i.fusion.hpf/high_pass_filter.py	                        (rev 0)
+++ grass-addons/grass7/imagery/i.fusion.hpf/high_pass_filter.py	2016-07-22 19:09:47 UTC (rev 69026)
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+ at author: Nikos Alexandris | Created on 13:02:59, Nov 3 2014
+"""
+
+import os
+from constants import MATRIX_PROPERTIES, CENTER_CELL, MODULATOR, MODULATOR_2, FILTER_TEMPLATE
+
+
+def get_kernel_size(ratio):
+    """
+    High Pass Filter Additive image fusion compatible kernel size.
+    Based on a float ratio, ranging in (1.0, 10.0).
+    Returns a single integer
+    """
+    kernel_size = [k for ((lo, hi), k) in MATRIX_PROPERTIES if lo <= ratio < hi][0]
+    return kernel_size
+
+
+def get_center_cell(level, kernel_size):
+    """
+    High Pass Filter Additive image fusion compatible kernel center
+    cell value.
+    """
+    level = level.capitalize()
+    kernel_size_idx = [k for ((lo, hi), k) in MATRIX_PROPERTIES].index(kernel_size)
+    center = [cc for cc in CENTER_CELL[level]][kernel_size_idx]
+    return center
+
+
+def get_modulator_factor(modulation, ratio):
+    """
+    Return the modulation factor for the first pass of the
+    High-Pass Filter Addition Technique for Image Fusion.
+
+    The modulation factor determines the image's Cripsness.
+
+    Parameters
+    ----------
+    modulation: str
+        Possible values are: `"min", "mid", max"`.
+    ratio: int
+        The resolution ratio between the high resolution pancrhomatic data
+        and the lower resolution spectral data.
+
+    Returns
+    -------
+    modulation_factor: float
+
+    """
+    kernel_size = get_kernel_size(ratio)
+    kernel_size_idx = [k for ((lo, hi), k) in MATRIX_PROPERTIES].index(kernel_size)
+    modulation = modulation.capitalize()
+    modulation_factor = [mf for mf in MODULATOR[modulation]][kernel_size_idx]
+    return modulation_factor
+
+
+def get_modulator_factor2(modulation):
+    """
+    Return the modulation factor for the second pass of the
+    High-Pass Filter Addition Technique for Image Fusion.
+
+    The modulation factor determines the image's Cripsness.
+
+    Parameters
+    ----------
+    modulation: str
+        Possible values are: `"min", "mid", max"`.
+
+    Returns
+    -------
+    modulation_factor: float
+
+    """
+    modulation = modulation.capitalize()
+    modulation_factor = MODULATOR_2[modulation]
+    return modulation_factor
+
+
+def get_row(size):
+    """ Return a matrix row consisting of -1. """
+    row = [-1] * size
+    return row
+
+
+def get_mid_row(size, center):
+    """
+    Return a matrix row consisting of -1 except of the center value which equals `center`.
+    """
+    row = get_row(size)
+    row[size // 2] = center
+    return row
+
+
+def get_kernel(size, level):
+    """
+    Return a compatible Kernel (`size` x `size`) for the
+    High-Pass Filter Addition Technique for Image Fusion.
+
+    Parameters
+    ----------
+    size: int
+        An odd integer specifying the size of the kernel (i.e. number or rows and columns).
+    level: str
+
+    Raises
+    ------
+    ValueError: If `size` is not an odd integer.
+
+    """
+
+    if size % 2 != 1:
+        raise ValueError("Size must be an odd integer, not <%r>" % size)
+    center = get_center_cell(level, size)
+    kernel = [get_row(size)] * size
+    kernel[size // 2] = get_mid_row(size, center)
+    return kernel
+
+
+def matrix_to_string(matrix):
+    lines = [" ".join(str(item) for item in row) for row in matrix]
+    string = os.linesep.join(lines)
+    return string
+
+
+def get_high_pass_filter(ratio, level='Low', divisor=1, type='P'):
+    """
+    Return a filter suitable for applying the High-Pass Filter Addition
+    Technique for Image Fusion using GRASS-GIS' `r.mfilter` module.
+
+    Returns a *NIX ASCII multi-line string whose contents is
+    a matrix defining the way in which raster data will be filtered
+    by r.mfilter. The format of this file is described in r.mfilter's
+    manual.
+
+    """
+    size = get_kernel_size(ratio)
+    kernel = get_kernel(size, level)
+    filter = FILTER_TEMPLATE.format(
+        kernel=matrix_to_string(kernel),
+        divisor=divisor,
+        type=type,
+        size=size,
+    )
+    return filter

Added: grass-addons/grass7/imagery/i.fusion.hpf/i.fusion.hpf.html
===================================================================
--- grass-addons/grass7/imagery/i.fusion.hpf/i.fusion.hpf.html	                        (rev 0)
+++ grass-addons/grass7/imagery/i.fusion.hpf/i.fusion.hpf.html	2016-07-22 19:09:47 UTC (rev 69026)
@@ -0,0 +1,111 @@
+<h2>DESCRIPTION</h2>
+
+<em>i.fusion.hpf</em> is an implementation of the High Pass Filter Additive
+(HPFA) Fusion Technique. It combines high-resolution panchromatic data with
+lower resolution multispectral data, resulting in an output with both excellent
+detail and a realistic representation of original multispectral scene colors.
+
+The process involves a convolution using a High Pass Filter (HPF) on the high 
+resolution data, then combining this with the lower resolution multispectral 
+data. Optionally, a linear histogram matching technique is performed in a way that 
+matches the resulting Pan-Sharpened image to the statistical mean and standard 
+deviation of the original multi-spectral image.<br>
+
+<h3>Background</h3>
+<ol type="1">
+    <li>Computing ratio of low (Multi-Spectral) to high (Panchromatic)
+        resolutions</li>
+    <li>High Pass Filtering the Panchromatic Image</li>
+    <li>Resampling MSX image to the higher resolution</li>
+    <li>Adding weighted High-Pass-Filetred image to the upsampled MSX
+        image</li>
+    <li>Optionally, matching histogram of Pansharpened image to the one of
+        the original MSX image</li>
+</ol>
+
+<pre>
+Figure:
+ ____________________________________________________________________________
++                                                                            +
+| Pan Img ->  High Pass Filter  ->  HP Img                                   |
+|                                      |                                     |
+|                                      v                                     |
+| MSx Img ->  Weighting Factors ->  Weighted HP Img                          |
+|       |                              |                                     |
+|       |                              v                                     |
+|       +------------------------>  Addition to MSx Img  =>  Fused MSx Image |
++____________________________________________________________________________+
+
+</pre>
+Source: Gangkofner, 2008
+
+<h2>NOTES</h2>
+<ul>
+        <li> Grasping and testing the various parameters that define the High-Pass
+        filter's kernel size and center value is a matter of short time.</li>
+    <li> Works with any number and type of raster imagery (8-bit, 16-bit)</li>
+    <li> The "black border" effect, possibly caused due to a non-perfect match of the high vs. the low 
+        resolution of the input images, can be trimmed out by using the <code>trim</code>
+        option --a floating point "trimming factor" with which to multiply the
+        pixel size of the low resolution image-- and shrink the extent of the
+        output image.</li>
+</ul>
+
+<h2>EXAMPLE</h2>
+The module is fairly easy to use. Arbitrary examples:
+<ul>
+    <li>for one band
+<div class="code"><pre>
+ i.fusion.hpf pan=Panchromatic msx=Red
+</pre></div></li>
+
+    <li>for multiple bands
+<div class="code"><pre>
+i.fusion.hpf pan=Panchromatic msx=Red,Green,Blue,NIR
+</pre></div></li>
+</ul>
+    
+Various illustrated examples detailed in the document <a
+    href="https://github.com/NikosAlexandris/i.fusion.hpf/blob/master/Documentation.pdf">i.fusion.hpf, implementation of the High Pass Filter Additive (HPFA) Image Fusion Technique</a> (PDF) 
+
+<h2>TODO</h2>
+<ul>
+    <li> Go through <a
+        href="http://trac.osgeo.org/grass/wiki/Submitting/Python">Submitting
+        Python</a></li>
+    <li> Access input raster by row I/O</li>
+    <li> Support for parallel processing</li>
+    <li> Proper command history tracking.</li>
+    <li> Add timestamps (r.timestamp, temporal framework)</li>
+    <li> Deduplicate code where applicable</li>
+    <li> Make verbose level messages shorter, yet more informative (ie report center cell)</li>
+    <li> Test if it compiles in other systems</li>
+    <li> Check options to integrate in <a href="i.pansharpen.html">i.pansharpen</a>. Think of FFM methods vs. Others?</li>
+    <li> Improve Documentation.lyx</li>
+</ul>
+
+<h2>REFERENCES</h2>
+<ul>
+    <li>Gangkofner, U. G., Pradhan, P. S., and Holcomb, D. W. (2008). Optimizing
+the high-pass filter addition technique for image fusion.
+PHOTOGRAMMETRIC ENGINEERING & REMOTE SENSING, 74(9):1107--1118.</li>
+
+    <li>"ERDAS IMAGINE." Accessed March 19, 2015. <a
+     href="http://doc.hexagongeospatial.com/ERDAS%20IMAGINE/ERDAS_IMAGINE_Help/#ii_hpfmerge_mergedialog.htm">ERDAS
+     IMAGINE Help</a>.</li>
+
+    <li>Aniruddha Ghosh & P.K. Joshi (2013) Assessment of pan-sharpened very
+        high-resolution WorldView-2 images, International Journal of Remote
+        Sensing, 34:23, 8336-8359</li>
+</ul>
+
+<h2>SEE ALSO</h2>
+<em>
+<a href="i.pansharpen.html">i.pansharpen</a>
+</em>
+
+
+<h2>AUTHOR</h2>
+
+Nikos Alexandris<br>
+

Added: grass-addons/grass7/imagery/i.fusion.hpf/i.fusion.hpf.py
===================================================================
--- grass-addons/grass7/imagery/i.fusion.hpf/i.fusion.hpf.py	                        (rev 0)
+++ grass-addons/grass7/imagery/i.fusion.hpf/i.fusion.hpf.py	2016-07-22 19:09:47 UTC (rev 69026)
@@ -0,0 +1,575 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+ MODULE:       i.fusion.hpf
+
+ AUTHOR(S):    Nikos Alexandris <nik at nikosalexandris.net>
+               Converted from a bash shell script | Trikala, Nov. 2014
+
+               Panagiotis Mavrogiorgos <pmav99 at gmail.com>
+               Some refactoring | Oct 2015
+
+ PURPOSE:      HPF Resolution Merge -- Algorithm Replication in GRASS GIS
+
+               Module to combine high-resolution panchromatic data with
+               lower resolution multispectral data, resulting in an output
+               with both excellent detail and a realistic representation of
+               original multispectral scene colors.
+
+               The process involves a convolution using a High Pass Filter
+               (HPF) on the high resolution data, then combining this with
+               the lower resolution multispectral data.
+
+               Optionally, a linear histogram matching technique is performed
+               in a  way that matches the resulting Pan-Sharpened imaged to
+               them statistical mean and standard deviation of the original
+               multi-spectral image. Credits for how to implement this
+               technique go to GRASS-GIS developer Moritz Lennert.
+
+
+               Source: "Optimizing the High-Pass Filter Addition Technique for
+               Image Fusion", Ute G. Gangkofner, Pushkar S. Pradhan,
+               and Derrold W. Holcomb (2008)
+
+               Figure 1:
+
++-----------------------------------------------------------------------------+
+|  Pan Img ->  High Pass Filter  ->  HP Img                                   |
+|                                       |                                     |
+|                                       v                                     |
+|  MSx Img ->  Weighting Factors ->  Weighted HP Img                          |
+|        |                              |                                     |
+|        |                              v                                     |
+|        +------------------------>  Addition to MSx Img  =>  Fused MSx Image |
++-----------------------------------------------------------------------------+
+
+ COPYRIGHT:    (C) 2014 - 2015 by the GRASS Development Team
+
+               This program is free software under the GNU General Public
+               License (>=v2). Read the file COPYING that comes with GRASS
+               for details.
+"""
+
+#%Module
+#%  description: Fusing high resolution Panchromatic and low resolution Multi-Spectral data based on the High-Pass Filter Addition technique (Gangkofner, 2008)
+#%  keywords: imagery
+#%  keywords: fusion
+#%  keywords: sharpening
+#%  keywords: high pass filter
+#%  keywords: HPFA
+#%End
+
+#%flag
+#%  key: l
+#%  description: Linearly match histogram of Pan-sharpened output to Multi-Spectral input
+#%end
+
+#%flag
+#%  key: 2
+#%  description: 2-Pass Processing (recommended) for large resolution ratio (>=5.5)
+#%end
+
+#%flag
+#%  key: c
+#%  description: Match color table of Pan-Sharpened output to Multi-Spectral input
+#%end
+
+#%option G_OPT_R_INPUT
+#% key: pan
+#% key_desc: filename
+#% description: High resolution Panchromatic image
+#% required : yes
+#%end
+
+#%option G_OPT_R_INPUTS
+#% key: msx
+#% key_desc: filename(s)
+#% description: Low resolution Multi-Spectral image(s)
+#% required: yes
+#% multiple: yes
+#%end
+
+#%option G_OPT_R_BASENAME_OUTPUT
+#% key: suffix
+#% key_desc: suffix string
+#% type: string
+#% label: Suffix for output image(s)
+#% description: Names of Pan-Sharpened image(s) will end with this suffix
+#% required: yes
+#% answer: hpf
+#%end
+
+#%option
+#% key: ratio
+#% key_desc: rational number
+#% type: double
+#% label: Custom ratio
+#% description: Custom ratio overriding standard calculation
+#% options: 1.0-10.0
+#% guisection: High Pass Filter
+#% required: no
+#%end
+
+#%option
+#% key: center
+#% key_desc: string
+#% type: string
+#% label: Center cell value
+#% description: Center cell value of the High-Pass-Filter
+#% descriptions: Level of center value (low, mid, high)
+#% options: low,mid,high
+#% required: no
+#% answer: low
+#% guisection: High Pass Filter
+#% multiple : no
+#%end
+
+#%option
+#% key: center2
+#% key_desc: string
+#% type: string
+#% label: 2nd Pass center cell value
+#% description: Center cell value for the second High-Pass-Filter (use -2 flag)
+#% descriptions: Level of center value for second pass
+#% options: low,mid,high
+#% required: no
+#% answer: low
+#% guisection: High Pass Filter
+#% multiple : no
+#%end
+
+#%option
+#% key: modulation
+#% key_desc: string
+#% type: string
+#% label: Modulation level
+#% description: Modulation level weighting the HPF image determining crispness
+#% descriptions: Levels of modulating factors
+#% options: min,mid,max
+#% required: no
+#% answer: mid
+#% guisection: Crispness
+#% multiple : no
+#%end
+
+#%option
+#% key: modulation2
+#% key_desc: string
+#% type: string
+#% label: 2nd Pass modulation level (use -2 flag)
+#% description: Modulation level weighting the second HPF image determining crispness (use -2 flag)
+#% descriptions: mid;Mid: 0.35;min;Minimum: 0.25;max;Maximum: 0.5;
+#% options: min,mid,max
+#% required: no
+#% answer: mid
+#% guisection: Crispness
+#% multiple : no
+#%end
+
+#%option
+#% key: trim
+#% key_desc: rational number
+#% type: double
+#% label: Trimming factor
+#% description: Trim output border pixels by a factor of the pixel size of the low resolution image. A factor of 1.0 may suffice.
+#% guisection: High Pass Filter
+#% required: no
+#%end
+
+# StdLib
+import os
+import sys
+import atexit
+
+# check if within a GRASS session?
+if "GISBASE" not in os.environ:
+    print "You must be in GRASS GIS to run this program."
+    sys.exit(1)
+
+# PyGRASS
+import grass.script as grass
+from grass.pygrass.modules.shortcuts import general as g
+from grass.pygrass.raster.abstract import Info
+from grass.pygrass.utils import get_lib_path
+
+# add "etc" directory to $PATH
+path = get_lib_path("i.fusion.hpf", "")
+if path is None:
+    raise ImportError("Not able to find the path %s directory." % path)
+sys.path.append(path)
+
+# import modules from "etc"
+from high_pass_filter import get_high_pass_filter, get_modulator_factor, get_modulator_factor2
+
+
+def run(cmd, **kwargs):
+    """Pass arbitrary number of key-word arguments to grass commands and the
+    "quiet" flag by default."""
+    grass.run_command(cmd, quiet=True, **kwargs)
+
+
+def cleanup():
+    """Clean up temporary maps"""
+    pattern = 'tmp.{pid}*'.format(pid=os.getpid())
+    run('g.remove', flags="f", type="raster", pattern=pattern)
+
+
+def avg(img):
+    """Retrieving Average of input image"""
+    uni = grass.parse_command("r.univar", map=img, flags='g')
+    avg = float(uni['mean'])
+    return avg
+
+
+def stddev(img):
+    """Retrieving Standard Deviation of input image"""
+    uni = grass.parse_command("r.univar", map=img, flags='g')
+    sd = float(uni['stddev'])
+    return sd
+
+
+def hpf_weight(low_sd, hpf_sd, mod, pss):
+    """Returning an appropriate weighting value for the
+    High Pass Filtered image. The required inputs are:
+    - low_sd:   StdDev of Low resolution image
+    - hpf_sd:   StdDev of High Pass Filtered image
+    - mod:      Appropriate Modulating Factor determining image crispness
+    - pss:      Number of Pass (1st or 2nd)"""
+    wgt = low_sd / hpf_sd * mod  # mod: modulator
+    msg = '   >> '
+    if pss == 2:
+        msg += '2nd Pass '
+    msg += 'Weighting = {l:.{dec}f} / {h:.{dec}f} * {m:.{dec}f} = {w:.{dec}f}'
+    msg = msg.format(l=low_sd, h=hpf_sd, m=mod, w=wgt, dec=3)
+    g.message(msg, flags='v')
+    return wgt
+
+
+def hpf_ascii(center, filter, tmpfile, second_pass):
+    """Exporting a High Pass Filter in a temporary ASCII file"""
+    # structure informative message
+    msg = "   > {m}Filter Properties: center: {c}"
+    msg_pass = '2nd Pass ' if second_pass else ''
+    msg = msg.format(m=msg_pass, c=center)
+    g.message(msg, flags='v')
+
+    # open, write and close file
+    with open(tmpfile, 'w') as asciif:
+        asciif.write(filter)
+
+
+# main program
+
+def main():
+
+    pan = options['pan']
+    msxlst = options['msx'].split(',')
+    outputsuffix = options['suffix']
+    custom_ratio = options['ratio']
+    center = options['center']
+    center2 = options['center2']
+    modulation = options['modulation']
+    modulation2 = options['modulation2']
+
+    if options['trim']:
+        trimming_factor = float(options['trim'])
+    else:
+        trimming_factor = False
+
+    histogram_match = flags['l']
+    second_pass = flags['2']
+    color_match = flags['c']
+
+#    # Check & warn user about "ns == ew" resolution of current region ======
+#    region = grass.region()
+#    nsr = region['nsres']
+#    ewr = region['ewres']
+#
+#    if nsr != ewr:
+#        msg = ('>>> Region's North:South ({ns}) and East:West ({ew}) '
+#               'resolutions do not match!')
+#        msg = msg.format(ns=nsr, ew=ewr)
+#        g.message(msg, flags='w')
+
+    mapset = grass.gisenv()['MAPSET']  # Current Mapset?
+    region = grass.region()  # and region settings
+
+    # List images and their properties
+
+    imglst = [pan]
+    imglst.extend(msxlst)  # List of input imagery
+
+    images = {}
+    for img in imglst:  # Retrieving Image Info
+        images[img] = Info(img, mapset)
+        images[img].read()
+
+    panres = images[pan].nsres  # Panchromatic resolution
+
+    grass.use_temp_region()  # to safely modify the region
+    run('g.region', res=panres)  # Respect extent, change resolution
+    g.message("|! Region's resolution matched to Pan's ({p})".format(p=panres))
+
+    # Loop Algorithm over Multi-Spectral images
+
+    for msx in msxlst:
+        g.message("\nProcessing image: {m}".format(m=msx))
+
+        # Tracking command history -- Why don't do this all r.* modules?
+        cmd_history = []
+
+        #
+        # 1. Compute Ratio
+        #
+
+        g.message("\n|1 Determining ratio of low to high resolution")
+
+        # Custom Ratio? Skip standard computation method.
+        if custom_ratio:
+            ratio = float(custom_ratio)
+            g.message('Using custom ratio, overriding standard method!',
+                      flags='w')
+
+        # Multi-Spectral resolution(s), multiple
+        else:
+            # Image resolutions
+            g.message("   > Retrieving image resolutions")
+
+            msxres = images[msx].nsres
+
+            # check
+            if panres == msxres:
+                msg = ("The Panchromatic's image resolution ({pr}) "
+                       "equals to the Multi-Spectral's one ({mr}). "
+                       "Something is probably not right! "
+                       "Please check your input images.")
+                msg = msg.format(pr=panres, mr=msxres)
+                grass.fatal(_(msg))
+
+            # compute ratio
+            ratio = msxres / panres
+            msg_ratio = ('   >> Resolution ratio '
+                         'low ({m:.{dec}f}) to high ({p:.{dec}f}): {r:.1f}')
+            msg_ratio = msg_ratio.format(m=msxres, p=panres, r=ratio, dec=3)
+            g.message(msg_ratio)
+
+        # 2nd Pass requested, yet Ratio < 5.5
+        if second_pass and ratio < 5.5:
+            g.message("   >>> Resolution ratio < 5.5, skipping 2nd pass.\n"
+                      "   >>> If you insist, force it via the <ratio> option!",
+                      flags='i')
+            second_pass = bool(0)
+
+        #
+        # 2. High Pass Filtering
+        #
+
+        g.message('\n|2 High Pass Filtering the Panchromatic Image')
+
+        tmpfile = grass.tempfile()  # Temporary file - replace with os.getpid?
+        tmp = 'tmp.' + grass.basename(tmpfile)  # use its basenam
+        tmp_pan_hpf = '{tmp}_pan_hpf'.format(tmp=tmp)  # HPF image
+        tmp_msx_blnr = '{tmp}_msx_blnr'.format(tmp=tmp)  # Upsampled MSx
+        tmp_msx_hpf = '{tmp}_msx_hpf'.format(tmp=tmp)  # Fused image
+        tmp_hpf_matrix = grass.tempfile()  # ASCII filter
+
+        # Construct and apply Filter
+        hpf = get_high_pass_filter(ratio, center)
+        hpf_ascii(center, hpf, tmp_hpf_matrix, second_pass)
+        run('r.mfilter', input=pan, filter=tmp_hpf_matrix,
+            output=tmp_pan_hpf,
+            title='High Pass Filtered Panchromatic image',
+            overwrite=True)
+
+        # 2nd pass
+        if second_pass and ratio > 5.5:
+            # Temporary files
+            tmp_pan_hpf_2 = '{tmp}_pan_hpf_2'.format(tmp=tmp)  # 2nd Pass HPF image
+            tmp_hpf_matrix_2 = grass.tempfile()  # 2nd Pass ASCII filter
+            # Construct and apply 2nd Filter
+            hpf_2 = get_high_pass_filter(ratio, center2)
+            hpf_ascii(center2, hpf_2, tmp_hpf_matrix_2, second_pass)
+            run('r.mfilter',
+                input=pan,
+                filter=tmp_hpf_matrix_2,
+                output=tmp_pan_hpf_2,
+                title='2-High-Pass Filtered Panchromatic Image',
+                overwrite=True)
+
+        #
+        # 3. Upsampling low resolution image
+        #
+
+        g.message("\n|3 Upsampling (bilinearly) low resolution image")
+
+        run('r.resamp.interp',
+            method='bilinear', input=msx, output=tmp_msx_blnr, overwrite=True)
+
+        #
+        # 4. Weighting the High Pass Filtered image(s)
+        #
+
+        g.message("\n|4 Weighting the High-Pass-Filtered image (HPFi)")
+
+        # Compute (1st Pass) Weighting
+        msg_w = "   > Weighting = StdDev(MSx) / StdDev(HPFi) * " \
+            "Modulating Factor"
+        g.message(msg_w)
+
+        # StdDev of Multi-Spectral Image(s)
+        msx_avg = avg(msx)
+        msx_sd = stddev(msx)
+        g.message("   >> StdDev of <{m}>: {sd:.3f}".format(m=msx, sd=msx_sd))
+
+        # StdDev of HPF Image
+        hpf_sd = stddev(tmp_pan_hpf)
+        g.message("   >> StdDev of HPFi: {sd:.3f}".format(sd=hpf_sd))
+
+        # Modulating factor
+        modulator = get_modulator_factor(modulation, ratio)
+        g.message("   >> Modulating Factor: {m:.2f}".format(m=modulator))
+
+        # weighting HPFi
+        weighting = hpf_weight(msx_sd, hpf_sd, modulator, 1)
+
+        #
+        # 5. Adding weighted HPF image to upsampled Multi-Spectral band
+        #
+
+        g.message("\n|5 Adding weighted HPFi to upsampled image")
+        fusion = '{hpf} = {msx} + {pan} * {wgt}'
+        fusion = fusion.format(hpf=tmp_msx_hpf, msx=tmp_msx_blnr,
+                               pan=tmp_pan_hpf, wgt=weighting)
+        grass.mapcalc(fusion)
+
+        # command history
+        hst = 'Weigthing applied: {msd:.3f} / {hsd:.3f} * {mod:.3f}'
+        cmd_history.append(hst.format(msd=msx_sd, hsd=hpf_sd, mod=modulator))
+
+        if second_pass and ratio > 5.5:
+
+            #
+            # 4+ 2nd Pass Weighting the High Pass Filtered image
+            #
+
+            g.message("\n|4+ 2nd Pass Weighting the HPFi")
+
+            # StdDev of HPF Image #2
+            hpf_2_sd = stddev(tmp_pan_hpf_2)
+            g.message("   >> StdDev of 2nd HPFi: {h:.3f}".format(h=hpf_2_sd))
+
+            # Modulating factor #2
+            modulator_2 = get_modulator_factor2(modulation2)
+            msg = '   >> 2nd Pass Modulating Factor: {m:.2f}'
+            g.message(msg.format(m=modulator_2))
+
+            # 2nd Pass weighting
+            weighting_2 = hpf_weight(msx_sd, hpf_2_sd, modulator_2, 2)
+
+            #
+            # 5+ Adding weighted HPF image to upsampled Multi-Spectral band
+            #
+
+            g.message("\n|5+ Adding small-kernel-based weighted 2nd HPFi "
+                      "back to fused image")
+
+            add_back = '{final} = {msx_hpf} + {pan_hpf} * {wgt}'
+            add_back = add_back.format(final=tmp_msx_hpf, msx_hpf=tmp_msx_hpf,
+                                       pan_hpf=tmp_pan_hpf_2, wgt=weighting_2)
+            grass.mapcalc(add_back)
+
+            # 2nd Pass history entry
+            hst = "2nd Pass Weighting: {m:.3f} / {h:.3f} * {mod:.3f}"
+            cmd_history.append(hst.format(m=msx_sd, h=hpf_2_sd, mod=modulator_2))
+
+        if color_match:
+            g.message("\n|* Matching output to input color table")
+            run('r.colors', map=tmp_msx_hpf, raster=msx)
+
+        #
+        # 6. Stretching linearly the HPF-Sharpened image(s) to match the Mean
+        #     and Standard Deviation of the input Multi-Sectral image(s)
+        #
+
+        if histogram_match:
+
+            # adapt output StdDev and Mean to the input(ted) ones
+            g.message("\n|+ Matching histogram of Pansharpened image "
+                      "to %s" % (msx), flags='v')
+
+            # Collect stats for linear histogram matching
+            msx_hpf_avg = avg(tmp_msx_hpf)
+            msx_hpf_sd = stddev(tmp_msx_hpf)
+
+            # expression for mapcalc
+            lhm = '{out} = ({hpf} - {hpfavg}) / {hpfsd} * {msxsd} + {msxavg}'
+            lhm = lhm.format(out=tmp_msx_hpf, hpf=tmp_msx_hpf,
+                             hpfavg=msx_hpf_avg, hpfsd=msx_hpf_sd,
+                             msxsd=msx_sd, msxavg=msx_avg)
+
+            # compute
+            grass.mapcalc(lhm, quiet=True, overwrite=True)
+
+            # update history string
+            cmd_history.append("Linear Histogram Matching: %s" % lhm)
+
+        #
+        # Optional. Trim to remove black border effect (rectangular only)
+        #
+
+        if trimming_factor:
+
+            tf = trimming_factor
+
+            # communicate
+            msg = '\n|* Trimming output image border pixels by '
+            msg += '{factor} times the low resolution\n'.format(factor=tf)
+            nsew = '   > Input extent: n: {n}, s: {s}, e: {e}, w: {w}'
+            nsew = nsew.format(n=region.n, s=region.s, e=region.e, w=region.w)
+            msg += nsew
+
+            g.message(msg)
+
+            # re-set borders
+            region.n -= tf * images[msx].nsres
+            region.s += tf * images[msx].nsres
+            region.e -= tf * images[msx].ewres
+            region.w += tf * images[msx].ewres
+
+            # communicate and act
+            msg = '   > Output extent: n: {n}, s: {s}, e: {e}, w: {w}'
+            msg = msg.format(n=region.n, s=region.s, e=region.e, w=region.w)
+            g.message(msg)
+
+            # modify only the extent
+            run('g.region',
+                n=region.n, s=region.s, e=region.e, w=region.w)
+            trim = "{out} = {input}".format(out=tmp_msx_hpf, input=tmp_msx_hpf)
+            grass.mapcalc(trim)
+
+        #
+        # End of Algorithm
+
+        # history entry
+        run("r.support", map=tmp_msx_hpf, history="\n".join(cmd_history))
+
+        # add suffix to basename & rename end product
+        msx_name = "{base}.{suffix}"
+        msx_name = msx_name.format(base=msx.split('@')[0], suffix=outputsuffix)
+        run("g.rename", raster=(tmp_msx_hpf, msx_name))
+
+        # remove temporary files
+        cleanup()
+
+    # visualising-related information
+    grass.del_temp_region()  # restoring previous region settings
+    g.message("\n|! Original Region restored")
+    g.message("\n>>> Hint, rebalancing colors (via i.colors.enhance) "
+              "may improve appearance of RGB composites!",
+              flags='i')
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    atexit.register(cleanup)
+    sys.exit(main())


Property changes on: grass-addons/grass7/imagery/i.fusion.hpf/i.fusion.hpf.py
___________________________________________________________________
Added: svn:executable
   + *

Added: grass-addons/grass7/imagery/i.fusion.hpf/licenses/DEMO.TXT
===================================================================
--- grass-addons/grass7/imagery/i.fusion.hpf/licenses/DEMO.TXT	                        (rev 0)
+++ grass-addons/grass7/imagery/i.fusion.hpf/licenses/DEMO.TXT	2016-07-22 19:09:47 UTC (rev 69026)
@@ -0,0 +1,124 @@
+DIGITALGLOBE, INC.
+DEMONSTRATION
+END USER LICENSE AGREEMENT
+
+DigitalGlobe, Inc. ("DigitalGlobe") for a period of 90 
+days grants the Demonstrator (the "End User") a limited, 
+non-transferable, non-exclusive license to use the 
+DigitalGlobe® products and authorized third party products, 
+collectively referred to as "Product" or "Products", and 
+a limited right to develop Derived Works as defined below. 
+DigitalGlobe and End User may be referred to hereinafter 
+individually as a "Party" and collectively as "Parties."  
+All rights not expressly granted to End User are retained 
+by DigitalGlobe.  In consideration for the rights granted 
+under this End User License Agreement ("License"), End User 
+agrees to be bound to the terms herein and agrees that this 
+License shall govern the rights and obligations of the 
+Parties. In the event that this License is inconsistent 
+with any license included with the Products in electronic 
+form or in any "shrink-wrap" form delivered with the Products, 
+this License shall govern.
+
+1. AUTHORIZED USERS.  The demonstration license applies to 
+multiple users solely within the End User's organization at 
+multiple locations.
+
+2. LICENSE GRANTED AND PERMITTED USES.  By accepting the 
+terms of this license, the End User is permitted the rights 
+to use the Products internally at its facilities within its 
+country of residence and to:
+
+i	Make an unlimited number of copies for demonstration 
+purposes.
+ii	Modify the Products or use the Products to create 
+Derived Works to support the demonstration activities.
+iii	Display the Products to users outside of the Authorized 
+User group with the DigitalGlobe logo conspicuously featured 
+and provide appropriate copyright attribution.  However, copies 
+of the Products shall not be given to those outside the 
+Authorized User group.
+
+3. ATTRIBUTION.  End User agrees that any embodiment of the 
+Products permitted under this License or any Derived Works 
+will contain the following notice: "Includes material 
+© DigitalGlobe, Inc. All rights reserved."
+
+4. PROHIBITED USES.   The End User shall not:
+
+i	Copy or reproduce the Products (even if merged with other 
+materials), other than as consistent with the Permitted Uses. 
+ii	Sell, license, transfer or disclose the Products or use 
+them in any manner not expressly authorized by this License.
+iii	Alter or remove any copyright notice or proprietary legend 
+contained in or on the Products or Derived Work.  
+iv	Retain any Products beyond the term of the demonstration 
+period or the term of the license.  End User must discontinue 
+use of the Products and certify in writing that all copies of 
+the Products have been destroyed or returned to DigitalGlobe.   
+
+5. DERIVED WORKS.  Derived Works that End User may create 
+containing any data from the Products are subject to this 
+license and End User acknowledges, and will cause its employees 
+and agents to acknowledge, that DigitalGlobe and its licensors 
+will own all rights in any copy, translation, modification, 
+adaptation of such Derived Work.
+
+6. TERMINATION.  Without prejudice to any other rights, DigitalGlobe 
+may terminate this License by written notice to the End User if the 
+End User fails to comply with the terms and conditions of this License.  
+Upon termination, End User must discontinue use of the Products and 
+certify in writing that all copies of the Products have been destroyed 
+or returned to DigitalGlobe.
+
+7.	LIMITATIONS AND DISCLAIMER OF WARRANTY.  DigitalGlobe provides 
+a limited warranty for 30 days that the data delivered will be of 
+the area of interest ordered and the media used to carry the 
+Products will be from physical or material defects.  
+DigitalGlobe's sole liability shall be to replace the 
+media if the media (not the data encoded thereon) is defective 
+and the End User returns the media to DigitalGlobe within 30 
+days of delivery.  WITH THE EXCEPTION OF THE PRECEDING WARRANTY, 
+THE PRODUCTS ARE PROVIDED WITHOUT WARRANTY OF ANY KIND, EXPRESS 
+OR IMPLIED, AND ALL WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, 
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  DIGITALGLOBE 
+DOES NOT WARRANT THAT THE PRODUCTS WILL MEET THE END USER'S NEEDS 
+OR EXPECTATIONS, OR THAT OPERATIONS OF THE PRODUCTS WILL BE ERROR 
+FREE OR UNINTERRUPTED.  NO INFORMATION PROVIDED BY DIGITALGLOBE OR 
+ITS AGENTS, EMPLOYEES, OR ITS RESELLERS OR DISTRIBUTORS SHALL CREATE 
+A WARRANTY, OR IN ANY WAY INCREASE THE SCOPE OF THIS LIMITED WARRANTY, 
+AND THE END USER IS NOT ENTITLED TO RELY ON ANY SUCH INFORMATION.
+
+8.	NO CONSEQUENTIAL DAMAGES.  IN NO EVENT SHALL DIGITALGLOBE BE 
+LIABLE FOR ANY CLAIM OR LOSS INCURRED BY THE END USER, INCLUDING 
+WITHOUT LIMITATION, COMPENSATORY, INCIDENTAL, INDIRECT, SPECIAL, 
+CONSEQUENTIAL, EXEMPLARY OR OTHER NONCOMPENSATORY DAMAGES.
+
+9.	MISCELLANEOUS.  
+
+i	This License Agreement constitutes the complete and exclusive 
+agreement between DigitalGlobe and the End User relating to its 
+subject matter.  This License Agreement supersedes all prior and 
+contemporaneous representations, correspondence, proposals or 
+agreements relating to its subject matter, whether oral or written.  
+This License Agreement may be modified only by a written amendment 
+signed by both DigitalGlobe and the End User.  If any provision is 
+determined to be invalid or unenforceable, the remaining provisions 
+of this License Agreement shall continue to be valid and enforceable.  
+Neither this License Agreement nor any of the rights granted by it may 
+be assigned or transferred by the End User without the prior written 
+consent of DigitalGlobe.  This restriction on assignments or transfers 
+shall apply to assignments or transfers by operation of law, as well as 
+by contract, merger or consolidation.  Any attempted assignment or 
+transfer in derogation of this prohibition is void.
+ii	The End User shall be responsible for obtaining any and all 
+required governmental authorizations, including but not limited to 
+any export or import licenses, and foreign exchange permits. 
+iii	This Agreement shall be governed by the laws of the State of 
+Colorado.
+ 
+DigitalGlobe, Inc.
+Demonstration EULA_4923 Rev. 1.0
+06/01/2004
+
+

Added: grass-addons/grass7/imagery/i.fusion.hpf/licenses/DEMONSTRATION.TXT
===================================================================
--- grass-addons/grass7/imagery/i.fusion.hpf/licenses/DEMONSTRATION.TXT	                        (rev 0)
+++ grass-addons/grass7/imagery/i.fusion.hpf/licenses/DEMONSTRATION.TXT	2016-07-22 19:09:47 UTC (rev 69026)
@@ -0,0 +1,72 @@
+DIGITALGLOBE(r) PRODUCT 
+END USER LICENSE AGREEMENT
+This END USER LICENSE AGREEMENT ("Agreement") is made between DigitalGlobe, Inc. ("DigitalGlobe") and you or, if you represent an entity or other organization, that entity or organization (in either case, "You").  You have ordered or otherwise expressed an interest in obtaining a license to certain products of DigitalGlobe, including, without limitation, aerial or satellite photography, imagery or orthophotos, vector, attribute or other data, or other related documentation, information or content.  DigitalGlobe is willing to provide You with a license to those products of DigitalGlobe described in the confirmation of Your order provided by DigitalGlobe (Your "Confirmation") or otherwise provided to You in connection with this Agreement (collectively, the "Product") if You agree to be bound by the terms and conditions of this Agreement.  
+PLEASE READ THE TERMS AND CONDITIONS OF THIS AGREEMENT PROVIDED BELOW CAREFULLY.  BY ACCESSING OR USING THE PRODUCT, YOU ACKNOWLEDGE THAT YOU HAVE READ, AND AGREE TO BE BOUND BY THE TERMS AND CONDITIONS OF, THIS AGREEMENT.  
+IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT, DIGITALGLOBE IS NOT WILLING TO LICENSE THE PRODUCT TO YOU.  IF THE PRODUCT WAS DELIVERED TO YOU ON A TANGIBLE MEDIUM SUCH AS A CD, THEN YOU MUST RETURN THE PRODUCT IN ITS ORIGINAL PACKAGING, WITHOUT BREAKING THE SEAL.  IF THE PRODUCT WAS MADE AVAILABLE TO YOU IN AN ELECTRONIC FORMAT, THEN YOU MUST NOT DOWNLOAD, ACCESS OR USE THE PRODUCT.  IF YOU DO NOT RETURN THE PRODUCT OR IF YOU DOWNLOAD, ACCESS OR USE THE PRODUCT, AS SPECIFIED ABOVE, YOU ACKNOWLEDGE AND AGREE TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS AGREEMENT. 
+This Agreement will be entered into as of the date You first download, access or use the Product (the "Effective Date").  This Agreement consists of these terms and conditions and Your  Confirmation (which is incorporated herein and made a part hereof).  Unless otherwise amended as set forth herein, this Agreement represents the entire agreement and understanding between You and DigitalGlobe as to the matters set forth herein and will exclusively govern Your access to and use of the Product and will supersede any oral or written proposal, agreement or other communication between You and DigitalGlobe regarding the Product.  Your acceptance of this Agreement is expressly limited to the terms and conditions set forth herein.  Any additional or inconsistent terms provided by You in any other documents such as a purchase order will not have any legally binding effect on DigitalGlobe.  This Agreement may be modified only by a binding written instrument entered into by You and DigitalGlobe
 .  All waivers under this Agreement must be in writing.  Any waiver or failure to enforce any provision of this Agreement on one occasion will not be deemed a waiver of any other provision or of such provision on any other occasion.  
+1. Definitions.  For purposes of this Agreement, the following definitions apply.  Any capitalized terms in this Agreement not listed below will have the meanings given to them in this Agreement or, if not defined in this Agreement, will have their plain English (US) meanings.  
+a. Commercial Purpose.  Redistribution, retransmission or publication in exchange for a fee or other consideration, which may include, without limitation: (i) advertising; (ii) use in marketing and promotional materials and services on behalf of a customer, client, employer, employee or for Your own benefit; (iii) use in any materials or services for sale or for which fees or charges are paid or received (e.g., textbook supplemental materials, books, syllabi, course packs); and (iv) use in any books, news publication or journal without an Educational Purpose.
+b. Customer Group.  
+i. one individual;
+ii. one company, corporation, or similar legal entity (excluding affiliates or subsidiaries which will be treated as a separate Customer Group);
+iii. one subsidiary or affiliate of an entity;
+iv. one department of a federal agency at the U.S. Cabinet level (e.g., office of the U.S. Dept. of Agriculture of U.S. Dept. of Interior, but excluding sub-agencies);
+v. one civilian federal agency below the U.S. Cabinet level;
+vi. one department of the four branches of the military, a defense agency, one of the unified commands, one of the non-Dept. of Defense entities identified in 50 U.S.C. Section 401a or the State Department;
+vii. one department of a foreign military or an international defense or intelligence agency;
+viii. one state or provincial agency;
+ix. one county or local government;
+x. one non-governmental organization or non-profit organization;
+xi. one department within a single educational organization within a single country;
+xii. one international agency such as NATO, but excluding the United Nations and the European Union;
+xiii. one office or department within the United Nations or the European Union; or
+xiv. any one entity equivalent to any of the entities listed above, located outside the United States. 
+c. Demonstration Purpose.  Any non-Commercial Purpose for demonstration, promotional or training purposes for a period of no more than 90 days from Product shipment.
+d. Derivative.  Any addition, improvement, update, modification, translation, transformation, adaptation or derivative work of or to the Product, authored, created or developed by or on behalf of You, including, without limitation, any reformatting of the Product into a different format or media from which it is delivered to You, any addition of data, information or other content to the Product, or any copy or reproduction of the Product.  
+e. Educational Purpose.  Any non-Commercial Purpose undertaken for study or research solely in furtherance of education.
+f. Federal Civil Government Agency.  Any government agency at the federal level, EXCLUDING all U.S. Department of Defense agencies and those agencies defined under U.S. Code Title 50.  The U.S. Army Corp of Engineers is included in the definition of Federal Civil Government Agency under this Agreement.   
+g. Fees.  The fees set forth in Your  Confirmation.  
+h. Joint Project.  An undertaking between You and one or more other Customer Groups based on a contractual relationship existing as of the Effective Date.
+i. Purpose.  As may be indicated in Your  Confirmation, Demonstration Purposes or Educational Purposes.  
+j. State and Local Government Agency.  Any government agency at the state and local level.  With regard to the United States, the term "state" includes the 50 United States and the United States' territories and possessions. 
+k. User.  Employees or contractors of You or, as applicable, a Customer Group.  
+2. Grant of License.   Subject to Your compliance with the terms and conditions of this Agreement, including, without limitation, payment of all applicable Fees, DigitalGlobe grants to You a non-exclusive, non-transferable, limited license to allow the number of Users identified on Your  Confirmation to access, reproduce, store, display and create Derivatives of the Product, solely for the Purpose indicated in Your  Confirmation or, if no Purpose is indicated in Your  Confirmation, solely for Your own internal business purposes.  
+a. If You are not a Federal Civil Government Agency or a State and Local Government Agency, You may post the Product and Derivative on Your website at a resolution no better than 10 meters in a static, non-downloadable, non-distributable, non-interactive fashion and in a manner that does not allow a third party to extract or access the Product as a standalone file;
+b. If You are a Federal Civil Government Agency, You may post the Product and Derivative to publicly accessible Internet web sites provided that: (a) the quality of the image data available for download is presented in a color composite jpeg or a 50:1 compressed file format without associated geospatial information; and (b) the Product or Derivative posted to publicly accessible websites is in a secure format that allows printing and viewing at no better than ten meter resolution.  The Product and any Derivatives may be posted to secure Intranet websites and may be used only for the purposes of a Joint Project and subject to Section 3;
+c. If You are a State and Local Government Agency, You may post the Product and any Derivatives on Your website at full resolution for non-Commercial Purposes, in a non-downloadable, non-distributable fashion, and in a manner that does not allow a third party to extract or access the Product as a standalone file;
+3. Sublicense.  Subject to Your compliance with the terms and conditions of this Agreement, including, without limitation, payment of all applicable Fees, You may grant sublicenses of the rights granted to You under Section 2 to access, reproduce, store, and display the Product to Customer Groups engaged in a Joint Project with You solely for the internal business purposes of the Customer Group in completing the Joint Project with You.  All Customer Groups will be identified by You and confirmed by DigitalGlobe (on Your  Confirmation or otherwise) in advance of any sublicense by You.  The number of permitted Users within each Customer Group sublicensed hereunder will be limited to the type of license You have purchased as follows:  
+Type of License Purchased
+Number of Permitted Users Within Sublicensed Customer Group
+Base
+Up to 5
+Group
+From 6 to 10
+Enterprise
+From 11 to 25
+Enterprise Premium
+More than 25
+Educational
+1
+Demonstration
+1
+If the number of individuals of a sublicensed Customer Group using or accessing the Product exceeds the number of Users permitted under this Section 3, the Customer Group will be counted as multiple sublicensees based on the number of individuals using the Product, for purposes of determining compliance with the table above.  If a sublicensed Customer Group is involved in multiple Joint Projects with You, the Customer Group will be counted as multiple sublicensees based on the number of Joint Projects involved for purposes of determining compliance with the table above.   Each sublicense must require  the sublicensee to agree to be bound by this Agreement.  You will remain responsible for any noncompliance by any sublicensee and sublicensee's breach of this Agreement shall be deemed to be Your breach of this Agreement.  
+4. Restrictions.  You recognize and agree that the Product is the property of DigitalGlobe and contains valuable assets and proprietary information of DigitalGlobe.  Accordingly, except as expressly permitted in Sections 2 or 3, You will not, and will not permit any User or third party to: (a) publish, transmit, reproduce, create Derivatives of or otherwise utilize the Product in any form, format or media; (b) merge the Product with any other data, information or content; (c) reverse engineer or otherwise attempt to derive the algorithms, databases or data structures upon which the Product is based; (d) distribute, sublicense, rent, lease or loan the Product; (e) use the Product for the business needs of any third person or entity, including without limitation, providing any services to any third parties; (f) remove, bypass or circumvent any electronic or other forms of protection measure included on or with the Product; (g) alter, obscure or remove any copyright notice, copyright m
 anagement information or proprietary legend contained in or on the Product; or (h) otherwise use or access the Product or any Derivatives for any purpose not expressly permitted under this Agreement, including, without limitation, for Commercial Purposes. Excepting Advanced Ortho Aerial Products or other Products consisting of Microsoft Aerial Imagery or Derivatives consisting of Microsoft Aerial Imagery, all Products and Derivatives must contain the following copyright notice conspicuously displayed in connection with the Product or Derivative Work: "(c) DigitalGlobe, Inc. All Rights Reserved" for the Product, and "Includes copyrighted material of DigitalGlobe, Inc., All Rights Reserved" for Derivatives.  All Advanced Ortho Aerial Products and Derivatives containing Microsoft Aerial Imagery must include, on or near the Licensed Image,  the attribution, "Available Exclusively by DigitalGlobe" as well as the following copyright notice in an "About" page, "Terms of Use", End User Lice
 nse Agreement, or similar medium: "Image (c) 20xx Microsoft Corporation" annotating the applicable year. You acknowledge that You need to obtain a separate distribution license from DigitalGlobe in order to distribute or publish the Product or any Derivative Work in any form not expressly permitted under Section 2 or 3.  
+5. Ownership.  The Product, and all worldwide intellectual property and proprietary rights therein and related thereto, including, without limitation, all patents, copyrights, trademarks, trade secrets, moral rights, sui generis rights and other right in databases, and all rights arising from or pertaining to the foregoing rights, are and will remain the exclusive property of DigitalGlobe and its suppliers.  All rights in and to the Product not expressly granted to You are reserved by DigitalGlobe and its suppliers.  This Agreement does not grant You title to the Product or any copies of the Product.  Any rights of Customer in any Derivative do not provide Customer with any rights in or to any Product used or incorporated in that Derivative except as granted under this Agreement.   
+6. Confidentiality.  The Product includes metadata and other confidential and proprietary information of DigitalGlobe ("Confidential Information").  You will not use any Confidential Information for any purpose not expressly permitted hereunder and will disclose Confidential Information only to Your employees and permitted sublicensees who have a need to know for purposes of this Agreement and who are under a duty of confidentiality no less restrictive than Your duty hereunder.  You will protect the Confidential Information from unauthorized use, access, or disclosure in the same manner as You protect Your own confidential or proprietary information of similar nature and with no less than reasonable care.  
+7. Audit.  At DigitalGlobe's request, You will provide assurances acceptable to DigitalGlobe that You are using the Product consistent with the terms of this Agreement.  Upon notice, DigitalGlobe may inspect Your records, accounts and books relating to the use of the Product to ensure that the Product is being used in accordance with this Agreement.  
+8. Term and Termination.  This Agreement remains in full force until terminated as provided below.  DigitalGlobe has the right to terminate this Agreement, effective immediately upon notice to You, if You breach any provision of this Agreement.  Upon termination of this Agreement, all rights granted to You hereunder shall immediately cease and You and Your sublicensees will: (a) discontinue all use of the Product; (b) if the Product was delivered on a tangible medium, return to DigitalGlobe the Product and all copies thereof; (c) purge all copies of the Product or any portion thereof from all computer storage devices or medium on which You have placed or permitted others to place the Product; and (d) give DigitalGlobe a written certification that You have complied with all of Your obligations hereunder.  
+9. Limited Warranty; Disclaimer.  DigitalGlobe warrants that, for a period of 30 days after Your receipt of the Product, the Product will perform substantially in accordance with its applicable specifications.  DigitalGlobe's sole obligation and Your entire remedy for breach of the above warranty is for DigitalGlobe, at its sole option and expense, to: (a) repair or replace the non-conforming Product returned during the warranty period; or (b) refund all fees paid by You for the non-conforming Product returned during the warranty period.  This limited warranty is void if any non-conformity has resulted from any accident, abuse, misuse, misapplication, or modification of or to the Product or any breach of this Agreement.  EXCEPT AS EXPRESSLY PROVIDED IN THIS SECTION 9, ALL PRODUCT IS PROVIDED "AS IS" WITHOUT ANY REPRESENTATIONS OR WARRANTIES OF ANY KIND AND ALL WARRANTIES, WHETHER EXPRESS OR IMPLIED, ORAL OR WRITTEN, ARISING BY LAW OR OTHERWISE, ARE EXPRESSLY DISCLAIMED AND EXCLUDED 
 BY DIGITALGLOBE, INCLUDING, WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.  DIGITALGLOBE DOES NOT WARRANT THAT THE PRODUCT WILL BE ACCURATE, CURRENT OR COMPLETE, THAT THE PRODUCT WILL MEET YOUR NEEDS OR EXPECTATIONS, OR THAT THE OPERATION OF THE PRODUCT WILL BE ERROR FREE OR UNINTERRUPTED.  DIGITALGLOBE PROVIDES ALL CONTENT AS A SERVICE TO YOU.  SPATIAL, SPECTRAL, AND TEMPORAL ACCURACY CANNOT BE GUARANTEED.  DIGITALGLOBE RESERVES THE RIGHT, AT ITS SOLE DISCRETION, TO MODIFY CERTAIN IMAGE CHARACTERISTICS OF THE CONTENT INCLUDING, BUT NOT LIMITED TO, WATERMARKING AND DIMENSIONS.
+10. Limitation of Liability.  IN NO EVENT WILL DIGITALGLOBE OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL, CONSEQUENTIAL, SPECIAL, EXEMPLARY, OR INDIRECT DAMAGES (INCLUDING LOST PROFITS OR LOST DATA) ARISING FROM, OR RELATING TO, THIS AGREEMENT OR THE PRODUCT, EVEN IF DIGITALGLOBE OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  DIGITALGLOBE AND ITS SUPPLIERS' TOTAL CUMULATIVE LIABILITY IN CONNECTION WITH THIS AGREEMENT AND THE PRODUCT, WHETHER IN CONTRACT OR TORT OR OTHERWISE, WILL NOT EXCEED THE AMOUNT OF FEES PAID TO DIGITALGLOBE FOR THE PRODUCT.  THIS SECTION 10 SHALL BE GIVEN FULL EFFECT EVEN IF THE WARRANTY PROVIDED IN SECTION 9 IS DEEMED TO HAVE FAILED OF ITS ESSENTIAL PURPOSE.  
+11. Indemnification.  You will indemnify, defend, and hold harmless DigitalGlobe and its subsidiaries, affiliates and subcontractors, and their respective owners, officers, directors, employees and agents, from and against any and all direct or indirect claims, damages, losses, damages, liabilities, expenses, and costs (including reasonable attorneys' fees) arising from or out of: (1) Your use of the Product for any purpose; (2) Your actual or alleged breach of any provision of this Agreement; or (3) damage to property or injury to or death of any person directly or indirectly caused by You. DigitalGlobe will provide You with notice of any such claim or allegation, and DigitalGlobe has the right to participate in the defense of any such claim at its expense.  
+12. Export Control.  You will not export or re-export any Software in violation of the U.S. Export Administration regulations or other applicable laws and regulations.  You will defend, indemnify, and hold harmless DigitalGlobe from and against all fines, penalties, liabilities, damages, costs, and expenses incurred by DigitalGlobe as a result of any violation of such laws and regulations by You or any of Your agents or employees.
+13. Additional Terms.
+a. You acknowledge that any actual or threatened breach of Section 2, 3, 4, or 6 will constitute immediate and irreparable harm to DigitalGlobe for which monetary damages would be an inadequate remedy.  Therefore, without limiting any other remedy available at law or in equity, upon any such breach or any threat thereof, DigitalGlobe will be entitled to seek injunctive relief against You as remedy for such breach.  To the fullest extent not prohibited by applicable law, any action brought for such relief may be brought by DigitalGlobe upon ex parte application and without notice or posting of any bond, and You expressly waive any requirement for notice or the posting of any bond.  If any action is brought to enforce this Agreement, the prevailing party will be entitled to receive its reasonable attorney's fees, court costs, and other collection expenses, in addition to any other relief it may receive.
+b. Failure to require performance of any provision of this Agreement does not waive DigitalGlobe's right to subsequently require full and proper performance of such provision.  If any provision of this Agreement is determined to be invalid or unenforceable, such provision will to the extent possible be deemed amended by limiting and reducing it to the minimum extent necessary to make such provision valid and enforceable and the remaining provisions of this Agreement shall continue to be valid and enforceable and will be liberally construed to carry out the provisions and intent hereof.  The invalidity or unenforceability of any provision of this Agreement in any jurisdiction will not affect the validity or enforceability of such provision in any other jurisdiction, nor will the invalidity or unenforceability of any provision of this Agreement with respect to any person affect the validity or enforceability of such provision with respect to any other person.  
+c. Neither this Agreement nor any of the rights or obligations hereunder may be assigned or transferred by You (by operation of law or otherwise) without the prior written consent of DigitalGlobe.  This restriction on assignment or transfer shall apply to assignments or transfers by operation of law, as well as by contract, merger or consolidation.  Any attempted assignment or transfer in violation of the foregoing will be null and void.
+d. This Agreement shall be governed by the laws of the State of Colorado, U.S.A., without regard to conflicts of law principles that would require the application of the laws of any other state or jurisdiction.  The United Nations Convention on Contracts for the International Sale of Goods does not apply to this Agreement.  Any action or proceeding arising from or relating to this Agreement must be brought in the federal courts or state courts for Boulder County, Colorado, and each party irrevocably submits to the jurisdiction and venue of any such court in any such action or proceeding.
+e. Any notices to DigitalGlobe relating to this Agreement shall be in writing and delivered by personal delivery or U.S. certified mail (return receipt requested) to the address provided below and will be effective upon receipt by DigitalGlobe:  
+DIGITALGLOBE, INC.
+ATTN: LEGAL DEPT.
+1601 Dry Creek Dr., Suite 260
+Longmont, CO  80503, USA
+All notices to You relating to this Agreement shall be delivered by personal delivery, electronic mail, facsimile transmission or by U.S. certified mail (return receipt requested) to the address DigitalGlobe has on file for You, and will be deemed given upon personal delivery, 5 days after deposit in the mail, or upon acknowledgment of receipt of electronic transmission.
\ No newline at end of file

Added: grass-addons/grass7/imagery/i.fusion.hpf/test_high_pass_filter.py
===================================================================
--- grass-addons/grass7/imagery/i.fusion.hpf/test_high_pass_filter.py	                        (rev 0)
+++ grass-addons/grass7/imagery/i.fusion.hpf/test_high_pass_filter.py	2016-07-22 19:09:47 UTC (rev 69026)
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# author: Panagiotis Mavrogiorgos
+
+""" Test High Pass Filtering functions.  """
+
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
+
+
+from high_pass_filter import get_row, get_mid_row, get_kernel, get_center_cell
+
+
+def test_get_row():
+    for size in (3, 5, 7, 9):
+        row = get_row(size)
+        assert len(row) == size
+        assert all(item == -1 for item in row)
+
+
+def test_get_mid_row():
+    center = -23
+    for size in (3, 5, 7, 9):
+        row = get_mid_row(size, center)
+        assert len(row) == size
+        assert row[size // 2] == center
+        assert [item == -1 for item in row if item != center]
+
+
+def test_get_kernel():
+    for size, level in [(5, "Low"), (5, "Mid"), (7, "High")]:
+        kernel = get_kernel(size, level)
+        # test number of rows/columns
+        assert len(kernel) == size
+        assert all(len(row) == size for row in kernel)
+        # test matrix contents
+        mid_row = size // 2
+        for i, row in enumerate(kernel):
+            if i == mid_row:
+                center = get_center_cell(level, size)
+                assert row == get_mid_row(size, center)
+            else:
+                assert row == get_row(size)



More information about the grass-commit mailing list