How to apply Raster Function to an Image Service

1185
7
02-14-2022 05:39 AM
MariamJamilah
New Contributor III

Hello,

I have an image service ( mosaic of time dimensional imagery). I want to apply the Minus function (subtraction) to two slices from the image service and display the output. How do I do this? 

I would also like to do change detection using the same two slices, please suggest how to go about it?

I have provided the code that I am currently using to do the above but the result is incorrect, please help!

I am using ArcGIS JS API 4.22

 

  require([
        "esri/Map",
        "esri/views/MapView",
        "esri/layers/support/MosaicRule",
        "esri/layers/ImageryLayer",
        "esri/layers/support/RasterFunction",
        "esri/layers/support/ImageParameters",
        "esri/layers/MapImageLayer"

      ], (Map, MapView, MosaicRule, ImageryLayer, RasterFunction, ImageParameters, MapImageLayer) => {

        const year1 = "Reclass_IntYear2015";
        const mr1 = new MosaicRule({
          where: "name='" + year1 + "'"
        });

        const year2 = "Reclass_IntYear2020";
        const mr2 = new MosaicRule({
          where: "name='" + year2 + "'"
        });
      
        const layer1 = new ImageryLayer({
          url: imageServiceURL,
          mosaicRule: mr1
        });

        const layer2 = new ImageryLayer({
          url: imageServiceURL,
          mosaicRule: mr2
        });

         const map = new Map({
          basemap: "hybrid",
        });

        const view1 = new MapView({
          container: "viewDiv",
          map: map,
          center: {
            x: 87.976322,
            y: 24.04582,
            spatialReference: 4326
          },
          zoom: 10,
          popup: {
            actions: []
          },
   
        });


        minusRF = new RasterFunction();
        minusRF.functionName = "Arithmetic";
        minusRF.outputPixelType = "F32";
        minusRF.functionArguments = {
        "Raster" : layer1,
        "Raster2" : layer2,
        "Operation" : "2",
        "ExtentType" : 0,
        "CellsizeType" : 1}

        const changeDetectionLayer = new ImageryLayer({
              url: imageServiceURL,
              id: "resultLayer",
        );
        changeDetectionLayer.renderingRule = minusRF

        map.add(changeDetectionLayer);  
        
        

 

 

7 Replies
JohnGrayson
Esri Regular Contributor

For the "Raster" and "Raster2" parameters, use the raster ids.  For example, if "Reclass_IntYear2015" has an object id of 5 then the "Raster" parameter should be "$5".

https://developers.arcgis.com/documentation/common-data-types/raster-function-objects.htm
- Check out the section "Using rasters in rendering rules"


MariamJamilah
New Contributor III

Thank you for your response!

I am still unable to understand how to display the output of the raster function. The output is dynamic and must be generated on the fly. 

0 Kudos
JohnGrayson
Esri Regular Contributor

Do you have a CodePen showing the issue, or a URL to the image service?  The link to the help topic provided above shows how to use the raster object id as input parameter to the raster function.  If you're building some type of UI to pick the years then you'll need to know the available raster ids and how they corresponds to each year.  Temporal information can be modeled in many different ways, but in your code above it seems to be part of a raster attribute so you can get those values via a query into the service.  Additionally, you might need to chain together other Raster Functions to provide appropriate colors based on the the type of data or desired visualization, or maybe use an appropriate renderer.

const changeDetectionLayer = new ImageryLayer({
  url: imageServiceURL,
  renderingRule: {
    functionName": "Arithmetic",
    functionArguments: {
      "Raster" : "$5",
      "Raster2" : "$6",
      "Operation" : "2",
      "ExtentType" : 0,
      "CellsizeType" : 1
    },
    outputPixelType: "f32"
  }
});

 

MariamJamilah
New Contributor III

Hello,

Yes,  I will be using a UI to pick the years. The image service has a limited number of rasters and therefore I can pick the objectId for each corresponding year. 

The major issue that I am facing is with displaying the output of the raster function. I am still unsure if using a renderingRule is the way to go about it. I have used the snippet that you have provided and I get a black image as output. I have attached the image and code (zipped file) for your reference.

As suggested, if I have to chain the raster functions as follows: arithmetic --> remap --> colormap. How do I use output of previous raster function in the following function and how do I finally display the result image? 

Thank you so much for helping me out!

MariamJamilah_0-1644899021057.png

 

0 Kudos
MariamJamilah
New Contributor III

Hello,

I have updated the code and attached the recent zipped file.

I am now able to chain the raster functions and display the image (attached below), though not entirely sure if the output is correct.

I would like to know if there is a way to display (render) the positive and negative change (that is, display the increase/decrease post the Minus arithmetic operation). Would using a custom raster function be a good idea? Is it possible to do so?

Thanks!

MariamJamilah_0-1644937229898.png

 

0 Kudos
JohnGrayson
Esri Regular Contributor

Glad to hear you got it working.  There are many ways to model and display the 'difference' between two rasters; two common types I use are relative and absolute.  Displaying relative values show how much gain or loss is associated with each pixel. Displaying absolute difference will translate the results into three values: gain, loss, and no change. Depending on the source data and desired results you might want to add a Remap RF that narrows down the results into a well known set of values, then you could more easily match these values via a ColorMap RF.  I hope this helps.

KrishV
by
Occasional Contributor III

I have the same question. Any sample code for this?

0 Kudos