RasterExpressionEvaluator
From fmepedia
RasterExpressionEvaluator is a Workbench Transformer
| Table of contents |
Description
RasterExpressionEvaluator is a transformer that evaluates expressions on each cell in a raster, such as algebraic operations or conditional statements.
Examples
Note that you need FME2009 or newer in order to run these examples.
The examples include simple calculations and conditions with one input raster as well as the operations with two inputs.
Simple Calculation Examples
Inverting Colors
attachment 'RGBColorInverter.fmw|This example' not found demonstrates how to invert images with the following band interpretation list and expression:
RED8;GREEN8;BLUE8 255-A[0];255-A[1];255-A[2]
|
image 'negative.png' not found |
image 'inverted.png' not found |
The images show Heritage Mountain Elementary School and the surrounding area in Google Earth
- attachment 'RGBColorInverter.fmw|Workspace' not found
- attachment 'negative.png|Source data' not found
- attachment 'inverted.png|Result' not found
Brightness Correction
If attachment 'BrightnessSource.jpg|an image is too dark' not found, we can attachment 'BrightnessCorrection.fmw|boost brightness' not found with the following simple expression:
A[0]*1.5;A[1]*1.5;A[2]*1.5
|
image 'BrightnessSourceResized.jpg' not found |
image 'BrightnessCorrectedResized.jpg' not found |
Port Moody, Greater Vancouver
Note that this method should be used cautiously - if there are bright areas in the image, they will reach or exceed the maximum value (255 in my example), which will make them purely white (255, 255, 255 in case of RGB24), and the information in those areas will be lost.
- attachment 'BrightnessCorrection.fmw|Workspace' not found
- attachment 'BrightnessSource.jpg|Source data' not found
- attachment 'BrightnessCorrected.jpg|Result' not found
Color Correction
If one of the colors on attachment 'ColorCorrection.jpg|an image seems to dominate' not found over the others, we can attachment 'ColorCorrection.fmw|change only one band' not found (or apply different coefficients to different bands):
A[0];A[1]/1.2;A[2]
|
image 'ColorCorrectionResized.jpg' not found |
image 'ColorCorrectedResized.jpg' not found |
- attachment 'ColorCorrection.fmw|Workspace' not found
- attachment 'ColorCorrection.jpg|Source data' not found
- attachment 'ColorCorrected.jpg|Result' not found
Color to Grayscale Conversion
Most internet sources suggest the following formula for attachment 'infraredRGB.jpg|color' not found to grayscale attachment 'RGB2Grayscale.fmw|conversion' not found (and many sources also mention that depending on the image it may vary):
0.2989*A[0] + 0.5870*A[1] + 0.1140*A[2]
|
image 'InfraredRGBResized.jpg' not found |
image 'GrayscaleResized.jpg' not found |
The workspace also makes an image based on calculating average values,
0.3333*A[0] + 0.3333*A[1] + 0.3333*A[2]
but the first formula gives better contrast.
- attachment 'RGB2Grayscale.fmw|Workspace' not found
- attachment 'infraredRGB.jpg|Source data' not found
- attachment 'Grayscale.jpg|Result' not found
Unit Conversion
attachment 'UnitConversion.fmw|Conversion between all kinds of units' not found is a very natural operation for RasterExpressionEvaluator. In this example we take attachment '092g02_0101_deme.dem|a numeric raster representing DEM in meters' not found and convert units into attachment 'USGSDEM.dem|feet DEM' not found (band interpretation is INT32):
INT32 A[0]/0.3048
If we inspect results in Visualizer, we will see the results of conversion:
| Meters | Feet |
|---|---|
| image 'unitsMeters.png' not found | image 'unitsFeet.png' not found |
- attachment 'UnitConversion.fmw|Workspace' not found
- attachment '092g02_0101_deme.dem|Source data' not found
- attachment 'USGSDEM.dem|Result' not found
Condition Examples
Color classification
With a simple condition attachment 'GreenFilter.fmw|we can compare' not found cell values in different bands to classify colors. For example, we can find all green cells representing parks. Note that in this workspace we use only one band in the band interpretation list, but we still can use values from all bands:
RED8 if (A[1]-A[0]>5 && A[1]-A[2]>5, 200, 255)
This expression sets cell values to 200 where green is bigger than red and blue more than by 5. The rest of the cells gets the value of 255.
|
image 'GreenFilterResized.png' not found |
image 'GreenFilteredResized.png' not found |
Note that if we simply compare green with red and blue as follows:
if (A[1]>A[0] && A[1]>A[2], 200, 255)
then we will select not only green cells but also cells that are rather close to gray colors.
- attachment 'GreenFilter.fmw|Workspace' not found
- attachment 'GreenFilter.png|Source data' not found
- attachment 'GreenFiltered.png|Result' not found
Update to road centerline extractor example
The example above shows how much simpler my another example - road centerline extractor could be with this new transformer. The expression finds colors where all bands have similar values (white/gray/black) used for roads, their edges, and road labels) or colors that are rather yellowish - red and green band values are close, and they are quite bigger than blue band.
if ((abs(A[0]-A[1])<=3 && abs(A[0]-A[2])<=3) || (abs(A[0]-A[1])<=4 && abs(A[0]-A[2])>10) , 200, 255)
The expression gives the following result:
|
image 'RoadFilterResized.png' not found |
image 'RoadFilteredResized.png' not found |
- attachment 'RoadsOnly.fmw|Workspace' not found
- attachment 'RoadFilter.png|Source data' not found
- attachment 'RoadFiltered.png|Result' not found
Two-Input Examples
Change Detection
The idea of change detection is quite simple - we check whether the cell values of the new image are different from the the cell values of the original image. In this example I had to make one extra step to set cells containing data (not equal to 255) in both images to the same value (200 in this case):
if (A[0]<255, 200, 255)
After that the comparison goes as follows:
For deleted: if(A[0]!=B[0] && A[0]<255, 0, A[0])
For added: if(A[0]!=B[0] && B[0]<255, 0, A[0])
If we want to combine results together, but still make visible what was added, deleted, or stayed unchanged, we can combine the two bands together. However, they both have the same interpretation of RED8. We can change it to GREEN8 and BLUE8, and add the missing RED8. As result, the bands will be ordered as GREEN8;BLUE8;RED8. We can use RasterBandOrderer or reorder bands with RasterExpressionEvaluator, which fits better for this page:
A[2];A[0];A[1]
The source and the revised data as well as the results of comparison are shown below:
| Original | Revised |
|---|---|
|
image 'SAIF.png' not found |
image 'SAFE.png' not found |
| Deleted | Added |
|
image 'deleted.png' not found |
image 'added.png' not found |
| Added/Deleted | |
| image 'added_deleted.png' not found | |
- attachment 'ChangeDetection.fmw|Workspace' not found
- attachment 'SAIF.png|Source data 1' not found
- attachment 'SAFE.png|Source data 2' not found
- attachment 'added.png|Result 1' not found
- attachment 'deleted.png|Result 2' not found
- attachment 'added_deleted.png|Result 3' not found
Adding Data
Two rasters can be combined in a way when one raster supplies a certain layer of information - for example, only a road network (surface and labels), and another raster works as a background.
Classifying only road related cells from the raster map requires quite a complex condition - it should consider major routes (yellow), regular roads (white), and labels on both kinds of roads (labels have different colors). If if the cell satisfies the condition, we can take it from the road raster, otherwise we use the background raster:
if((B[0]==B[1] && B[0]==B[2]) || (abs(B[0]-B[1])<=5 && (B[0]-B[2]>6 && B[0]<100) || (B[0]-B[2]>20 && B[0]>100)), B[0], A[0]); if((B[0]==B[1] && B[0]==B[2]) || (abs(B[0]-B[1])<=5 && (B[0]-B[2]>6 && B[0]<100) || (B[0]-B[2]>20 && B[0]>100)), B[1], A[1]); if((B[0]==B[1] && B[0]==B[2]) || (abs(B[0]-B[1])<=5 && (B[0]-B[2]>6 && B[0]<100) || (B[0]-B[2]>20 && B[0]>100)), B[2], A[2])
This is how the result looks:
| Roads | Background |
|---|---|
|
image 'AddLayerRoads.png' not found |
image 'AddLayerBackground.jpg' not found |
| Combined | |
| image 'AddLayerCombined.jpg' not found | |
You may note that the condition stays the same for all three bands, and only index of the band is changing in the last portion of the statement. We can redesign our workspace in a way that we will need only one condition, but it requires much more transformers.
- attachment 'AddingLayer.fmw|Workspace' not found
- attachment 'AddingLayer.fmw|Workspace with one condition' not found
- attachment 'background.tif|Source data 1' not found
- attachment 'roads.png|Source data 2' not found
- attachment 'Combined.tif|Result' not found
Semitransparency
When we combine two rasters it's quite easy to achieve semitransparency of one of the rasters - we simply add to the existing value of the background only a small portion of the raster we want to see semitransparent:
if(B[0]==0,A[0],A[0]+B[0]/5);if(B[1]==0,A[1],A[1]+B[1]/2);if(B[2]==0,A[2],A[2]+B[2]/5)
As result of this calculation, the original pixels of the aerial image that are covered by the park areas get an addition equal to one fifth of the park pixel value, and this gives us semitransparent look:
| Parks | Background |
|---|---|
|
image 'TranspParks.png' not found |
image 'TranspBackground.jpg' not found |
| Combined | |
| image 'TranspCombined.jpg' not found | |
- attachment 'Semitransparency.fmw|Workspace' not found
- attachment 'AUSTIN_EAST-NEA3_resampled.tif|Source data 1' not found
- attachment 'MI_parks.zip|Source data 2' not found
- attachment 'SemitransparentParks.tif|Result' not found
Using Attribute Value Examples
The expressions in RasterExpressionEvaluator may contain attribute values; in order to use them we have to use the following syntax:
A:attribute_name
Below is an expression with an attribute value:
(A[0]*A:i/10.0 + B[0]*((11-B:i)/10.0)); (A[1]*A:i/10.0 + B[1]*((11-B:i)/10.0)); (A[2]*A:i/10.0 + B[2]*((11-B:i)/10.0)); if(A[3]==0 || B[3]==0,0,255)
attachment 'DonDaleMorph.fmw|The workspace that uses this expression' not found has a loop, which, after ten iterations gives us the following images:
| image 'morph_1.png' not found | image 'morph_2.png' not found | image 'morph_3.png' not found | image 'morph_4.png' not found | image 'morph_5.png' not found |
| image 'morph_6.png' not found | image 'morph_7.png' not found | image 'morph_8.png' not found | image 'morph_9.png' not found | image 'morph_10.png' not found |
Or, assembled into an animated sequence:
image 'morph.gif' not found
- attachment 'DonDaleMorph.fmw|workspace' not found
- attachment 'dale.png|Source data (Dale)' not found
- attachment 'don.png|Source data (Don)' not found
Elevation Zoning Scenario
This example combines rasters of two types - attachment '092g07_0100_demw.dem|a numeric DEM raster' not found and attachment 'map_ref.png|a color RGB raster' not found (don't forget attachment 'map_ref.wld|the worldfile' not found). Besides, it shows how to bring the rasters to the same size in pixels - otherwise RasterExpressionEvaluator won't work.
attachment 'elevationZoning.fmw|The workspace' not found demonstrates an elevation zoning scenario. Depending on values in DEM and zoning interval (zone height), it creates two to four different zones - low, average, high and very high elevations, and shows them on a road map taken from Google Maps.
attachment 'ElevationZoning.png|The resulting map' not found can help you choosing the right vehicle - if you live in red zone, in winter you need four wheel drive or at least perfect tires, in green zone you should be fine even with old tires (perhaps, you can feel some sad memories in my voice).
| DEM | Road Map |
|---|---|
|
image 'smallDEM.png' not found |
image 'smallRoadMap.png' not found |
| Elevation Zoning | |
| image 'smallZoning.png' not found | |
After two rasters are brought to the same size (see the workspace comments), RasterExpressionEvaluators start their job.
In the first expression transformer the road map is changed to have grayscale look, although we still need it in RGB interpretation for two reasons - first, we want to see zones in color, and second - the map looks nicer, when ocean is left blue:
if(A[0]==153 && A[1]==179 && A[2]==204, A[0], 0.2989*A[0] + 0.5870*A[1] + 0.1140*A[2]); if(A[0]==153 && A[1]==179 && A[2]==204, A[1], 0.2989*A[0] + 0.5870*A[1] + 0.1140*A[2]); if(A[0]==153 && A[1]==179 && A[2]==204, A[2], 0.2989*A[0] + 0.5870*A[1] + 0.1140*A[2])
The second RasterExpressionEvaluator classifies the DEM. It also uses an attribute _height, which can be changed from its default value (50 meters) to any integer value in the range between 20 to 100 meters. Press Ctrl+R in order to change this parameter.
if(A[0]==0,0,A[0]/A:_height+1)
The last ExpressionEvaluator changes red and green bands of the A raster (road map) according to zone number stored in raster B (classified DEM). The higher the elevation, the more red we add. Green is boosted for lower elevation zones:
if(B[0]<=2,A[0], if(B[0]==3 || B[0]==4, A[0]*1.1, if(B[0]==5 || B[0]==6, A[0]*1.3, A[0]*1.5))); if(B[0]==0 || B[0]==5 || B[0]==6, A[1], if(B[0]==1 || B[0]==2,A[1]*1.3, if(B[0]>=7, A[1]/1.1, A[1]*1.1))); A[2]
- attachment 'elevationZoning.fmw|workspace' not found
- attachment '092g07_0100_demw.dem|source data 1 (DEM)' not found
- attachment 'map_ref.png|source data 2 (road map)' not found
- attachment 'map_ref.wld|worldfile for road map' not found
