Skip Headers
Oracle® Spatial and Graph GeoRaster Developer's Guide
12c Release 1 (12.1)

E17894-13
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

5 Image Processing and Virtual Mosaic

This chapter describes advanced image processing capabilities, including GCP georeferencing, reprojection, rectification, orthorectification, image scaling, stretching, masking, image segmentation, NDVI computation, Tasseled Cap Transformation, image appending, bands merging, and large-scale advanced image mosaicking.

This chapter also describes the concept and application of virtual mosaic within the context of a large-scale image database and on-the-fly spatial queries over it.

The operations in this chapter are most commonly used to process geospatial images, particularly raw satellite imagery and airborne photographs. However, those operations, just like the GeoRaster raster algebra, apply to all raster data types.

This chapter contains the following major sections:

5.1 Advanced Georeferencing

In GeoRaster, the spatial referencing capability is called SRS (spatial reference system) or georeferencing, which may or may not be related to geography or a geospatial scheme. Georeferencing is a key feature of GeoRaster and is the foundation of spatial query and operations over geospatial image and gridded raster data. See Section 1.6, "Georeferencing" for a detailed description of the SRS models.

GeoRaster supports non-geospatial images, fine art photos, and multi-dimensional arrays, which might not be associated with any coordinate system. For those images and rasters, there is generally no need for georeferencing, but most of the GeoRaster operations still work on them, such as pyramiding, scaling, subsetting, band merging, stretching, and algebraic operations. In these cases, you address the pixels (cells) using the raster's cell space coordinates (that is, row, column, and band).

You can also create a user-defined coordinate system (a new SRID) that is not related to geography, and you can use that SRID as the model coordinate system for the rasters. Then, you can spatially reference these rasters to that SRID; that is, an SRS metadata component will be created for each of those rasters. Doing this causes those rasters to be spatially referenced, and thus co-located in that user-defined model coordinate system. After this is done for all related rasters, GeoRaster operations will work on those rasters as if they are georeferenced to a geographic coordinate system. For example, assume that an artist has painted a large mural on a wall, and that you want to be able to take many high-resolution photographs of different tiles of this wall and then stitch them together. You can spatially reference the tile images and then use the GeoRaster mosaicking capability to do the stitching.

If you do not define a new coordinate system, you can still co-locate the images in the cell space. That is, you can set up different ULT coordinates for the images by calling the SDO_GEOR.setULTCoordinate procedure, so that the images are aligned in the same coordinate system and then can be mosaicked.

Most geospatial image and raster files that you have are probably already georeferenced by other software tools, and thus they may come with georeferencing information. In those cases, the georeferencing information can be directly loaded with the rasters or afterward by using SDO_GEOR.importFrom, SDO_GEOR.setSRS, the GeoRaster loader tool, GDAL, or other third-party ETL tools. For more information, check Section 1.17, "GeoRaster Tools: Viewer, Loader, Exporter" and Section 3.6, "Georeferencing GeoRaster Objects".

If a geospatial image does not have spatial reference information, you can use the GeoRaster Ground Control Point (GCP) support to georeference the image. GCPs are collected either automatically by the remote sensing system or manually afterward. For an image without GCP information, you can use a GeoRaster visualization tool to collection GCPs for the GeoRaster object. GCPs are described in Section 1.6.2, "Ground Control Point (GCP) Georeferencing Model".

After you have the GCPs and want to store them in the GeoRaster metadata, you can get and set the GCP-based georeferencing mode by using the SDO_GEOR.getGCPGeorefModel function and the SDO_GEOR.setGCPGeorefModel procedure. To get, set, and edit only GCPs, use the SDO_GEOR.getControlPoint function and the SDO_GEOR.setControlPoint and SDO_GEOR.deleteControlPoint procedures. The GCPs can also be stored in the GeoRaster metadata when you call SDO_GEOR.georeference.

To get and set only the geometric model, use the SDO_GEOR.getGCPGeorefMethod function and the SDO_GEOR.setGCPGeorefMethod procedure. GeoRaster also allows you to store check points (pointType = 2), which are treated and manipulated in the same way as control points (pointType = 1) except that check points are not used to create the SRS coefficient when SDO_GEOR.georeference is called with the GCPs.

If you have ground control points (GCPs) that are either stored in the GeoRaster object or not, and if you want to calculate the functional fitting georeferencing model, you can call the SDO_GEOR.georeference procedure to find the solution. The functional fitting georeferencing model stores all coefficients in the GeoRaster SRS and enables the coordinate transformations between cell space and model space. To generate the functional fitting georeferencing model using GCP, you must specify an appropriate geometric model. The specific geometric models supported by SDO_GEOR.georeference are Affine Transformation, Quadratic Polynomial, Cubic Polynomial, DLT, Quadratic Rational, and RPC. These models are described in Section 1.6.1, "Functional Fitting Georeferencing Model".

For example, if you have a Landsat image in a plain area and want to georeference it, you might choose the Quadratic Polynomial geometric model. For that purpose, assuming you have collected 9 GCPs (at least 6 GCPs in this case) and 3 check points, you can set up the GCPs and store them in the GeoRaster's metadata using the code in Example 5-1.

Example 5-1 Setting Up the GCP Georeferencing Model

DECLARE
   gr1         sdo_georaster;
   georefModel SDO_GEOR_GCPGEOREFTYPE;
   GCPs        SDO_GEOR_GCP_COLLECTION;
BEGIN
   SELECT georaster INTO gr1 from georaster_table WHERE georid=1 FOR UPDATE;
   GCPs := SDO_GEOR_GCP_COLLECTION( 
                 SDO_GEOR_GCP('1', '', 1, 
                      2, sdo_number_array(25, 73),
                      2, sdo_number_array(237036.9, 897987.2),
                      NULL, NULL),
                 SDO_GEOR_GCP('2', '', 1, 
                      2, sdo_number_array(100, 459),
                      2, sdo_number_array(237229.6, 897949.7),
                      NULL, NULL),
                 SDO_GEOR_GCP('3', '', 1, 
                      2, sdo_number_array(362, 77),
                      2, sdo_number_array(237038.9, 897818.8),
                      NULL, NULL),
                 SDO_GEOR_GCP('4', '', 1, 
                       2, sdo_number_array(478, 402),
                       2, sdo_number_array(237201.06, 897760.56),
                       NULL, NULL),
                 SDO_GEOR_GCP('5', '', 1, 
                       2, sdo_number_array(167, 64),
                       2, sdo_number_array(237032.02, 897916.26),
                       NULL, NULL),
                 SDO_GEOR_GCP('6', '', 1, 
                       2, sdo_number_array(101, 257),
                       2, sdo_number_array(237128.9, 897949.3),
                       NULL, NULL),
                 SDO_GEOR_GCP('7', '', 1, 
                       2, sdo_number_array(235, 501),
                       2, sdo_number_array(237250.9, 897882.2),
                       NULL, NULL),
                 SDO_GEOR_GCP('8', '', 1, 
                       2, sdo_number_array(423, 214),
                       2, sdo_number_array(237107.3, 897788.0),
                       NULL, NULL),
                 SDO_GEOR_GCP('9', '', 1, 
                       2, sdo_number_array(127, 178),
                       2, sdo_number_array(237089.0, 897936.5),
                       NULL, NULL),
                 SDO_GEOR_GCP('10', '', 2, 
                       2, sdo_number_array(131, 425),
                       2, sdo_number_array(237212.8, 897934.2),
                       NULL, NULL),
                 SDO_GEOR_GCP('11', '', 2, 
                       2, sdo_number_array(299, 111),
                       2, sdo_number_array(237055.7, 897850.4),
                       NULL, NULL),
                 SDO_GEOR_GCP('12', '', 2, 
                       2, sdo_number_array(329, 253),
                       2, sdo_number_array(237126.9,897835.4), 
                       NULL, NULL) );
   georefModel := SDO_GEOR_GCPGEOREFTYPE('QuadraticPolynomial', GCPs.count, GCPs, NULL);
   -- Set and store the GCP georeference model into the GeoRaster object's metadata
   sdo_geor.setGCPGeorefModel(gr1, georefModel);
   UPDATE georaster_table SET georaster=gr1 WHERE georid=1;
   COMMIT;
END;
/

After using the code in Example 5-1, you can generate the functional fitting model coefficients by using the code in Example 5-2.

Example 5-2 Generating the Functional Fitting Model Using GCPs

DECLARE
   gr1  sdo_georaster;
   rms  sdo_number_array;
BEGIN
   SELECT georaster INTO gr1 from georaster_table WHERE georid=1 FOR UPDATE;
   -- georeference the image using the GCPs stored in the image's metadata
   rms := sdo_geor.georeference(gr1, null, 26986, 0, 'TRUE'); 
   UPDATE georaster_table SET georaster=gr1 WHERE georid=1;
   COMMIT;
END;
/

The steps in Example 5-1 and Example 5-2 can be combined without the need to pre-set the GCPs into the GeoRaster object's metadata (see the example for SDO_GEOR.georeference in Chapter 6). The returned value array of SDO_GEOR.georeference in Example 5-2 contains RMS values and residuals for each GCP. Using these, you can examine the solution accuracy and identify erratic GCPs. If the accuracy is not satisfactory, recheck all GCPs to make sure they are accurate and add more GCPs as necessary, and then run the script or scripts again.

The GCP support in GeoRaster enables you to spatially reference any non-geospatial images and rasters also.

After geospatial images are georeferenced, you can process those images, such as applying rectification, reprojection, and mosaicking, and spatially querying and subsetting the rasters using geometry polygons in different coordinate systems.

5.2 Image Reprojection

Image reprojection is the process of transforming an image from one SRS (spatial reference system, or coordinate system) to another. Reprojection is particularly useful with certain GeoRaster operations that combine two or more objects, because it requires that all the GeoRaster objects involved be in the same SRS.

Basic reprojection in GeoRaster is performed by the SDO_GEOR.reproject procedure and requires that the source GeoRaster SRID be different from the output SRID.

Example 5-3 reprojects a raster image that had been loaded into a GeoRaster object with SRID 4326, but needs to be reprojected to have the same SRID as other images previously stored with SRID 23619.

Example 5-3 Image Reprojection

DECLARE
  gr1 sdo_georaster;
  gr2 sdo_georaster;
BEGIN
  select raster into gr1 from georaster_load_table where georid = 10;
  delete from georaster_table where georid = 54;
  insert into georaster_table 
         values(54,'reprojected', sdo_geor.init()) 
         returning georaster into gr2;
  sdo_geor.reproject(inGeoRaster   => gr1,
                     pyramidLevel  => 0,
                     cropArea      => null,
                     layerNumbers  => null,
                     resampleParam => 'resampling=BILINEAR',
                     storageParam  => null,
                     outSRID       => 32619,
                     outGeoraster  => gr2);
  update georaster_table set georaster = gr2 where georid = 54;
  commit;
END;

The same operation can be accomplished by the SDO_GEOR.rectify procedure, producing similar results. The SDO_GEOR.rectify procedure offers more capabilities and flexibility than SDO_GEOR.reproject; for example, the input and output SRID can be the same and users can specify the precise resolution of the output (see Section 5.3, "Image Rectification").

If a GeoRaster object does not have an associated SRS, the process for georeferencing and rectifying it is explained in Section 3.6, "Georeferencing GeoRaster Objects" and Section 5.3, "Image Rectification".

Parallel reprojection is supported with the SDO_GEOR_AGGR.mosaicSubset procedure. See Example 5-23, "Parallel Rectification or Reprojection" in Section 5.15.1.

5.3 Image Rectification

Most raster data originating from remote sensors above the ground is usually subject to distortion caused by the terrain, the view angles of the instrument, and the irregular shape of the Earth. Image rectification as explained in this section is the process of transforming the images to reduce some of that distortion.

Rectification is performed by the SDO_GEOR.rectify procedure, and requires that the source GeoRaster object have at least a functional fitting georeferencing model. This means that the image does not need to be rectified, but it needs to have georeference information in the metadata (see Section 3.6, "Georeferencing GeoRaster Objects").

The SDO_GEOR.rectify procedure can use the information available in the source GeoRaster object to automatically establish the spatial extents, dimension, and SRID of the output GeoRaster, and users can also specify different values by using the appropriate parameters.

Example 5-3 rectifies an aerial image that had been loaded into GeoRaster and later georeferenced with GCPs (see Section 5.1, "Advanced Georeferencing"). The image is rectified so that the output GeoRaster object has the same SRS and resolution of an existing GeoRaster object. The image is to be restricted to the area of existing GeoRaster object, and the pixels should be perfectly aligned with the existing GeoRaster object.

Example 5-4 Image Rectification

DECLARE
  gr_src sdo_georaster;
  gr_ref sdo_georaster;
  gr_out sdo_georaster;
BEGIN
  select raster into gr_src from georaster_load_table where georid = 15;
  select raster into gr_ref from georaster_table where georid = 1;
  delete from georaster_table where georid = 2;
  insert into georaster_table 
         values(2, 'rectified', sdo_geor.init()) 
         returning georaster into gr_out;
  sdo_geor.rectify(inGeoRaster      => gr_src,
                   pyramidLevel     => null,
                   elevationParam   => null,
                   dem              => null,
                   outSRID          => sdo_geor.getModelSRID(gr_ref),
                   outModelCoordLoc => null,
                   cropArea         => sdo_geor.generateSpatialExtent(gr_ref),
                   polygonClip      => null,
                   layerNumbers     => null,
                   outResolutions   => sdo_geor.getSpatialResolutions(gr_ref),
                   resolutionUnit   => 'unit=meters',
                   referencePoint   => sdo_geor.getModelCoordinate(gr_ref,
                                       0, sdo_number_array(-0.5,-0.5)),
                   resampleParam    => null,
                   storageParam     => null,
                   outGeoraster     => gr_out);
  update georaster_table set georaster = gr_out where georid = 2;
  commit;
END;

Rectification output can be significantly improved if information about elevation is passed to the SDO_GEOR.rectify procedure. (See Section 5.4, "Image Orthorectification" for more information about elevation.)

Parallel rectification is supported with the SDO_GEOR_AGGR.mosaicSubset procedure. See Example 5-23, "Parallel Rectification or Reprojection" in Section 5.15.1.

5.4 Image Orthorectification

Orthorectification is a rectification transformation process where information about the elevation, the terrain, and the shape of the Earth is used to improve the quality of the output rectified image. Oracle GeoRaster supports single image orthorectification with average height value or DEM.

The orthorectification is done by the SDO_GEOR.rectify procedure and requires that the source GeoRaster have a 3D SRS. The SDO_GEOR.rectify procedure can execute orthorectification with just the average height of the area or with a detailed Digital Elevation Model (DEM).

Related topics:

5.4.1 Orthorectification with Average Height

A GeoRaster object with a Digital Elevation Model (DEM) is optional for orthorectification. For relatively flat terrains, the 3D SRS together with the average height value might be sufficient to correct the distortion of the source image.

Example 5-5 shows orthorectification with average height. For this example, the source image was acquired from DigitalGlobe with RPC. The DEM was not available, but the average elevation of the area is known to be 1748.0 meters.

Example 5-5 Orthorectification with Average Height

DECLARE
  gr_src  sdo_georaster;
  gr_out  sdo_georaster;
BEGIN
  select georaster into gr_src from georaster_table where georid = 1;
  delete from georaster_table where georid = 3;
  insert into georaster_table values(3, 'orthorectified without DEM',
         sdo_geor.init('rdt_4',3)) 
         returning georaster into gr_out;
  sdo_geor.rectify(inGeoRaster      => gr_src,
                   pyramidLevel     => null,
                   elevationParam   => 'average=1748.8',
                   dem              => null,
                   outSRID          => 32613,
                   outModelCoordLoc => null,
                   cropArea         => null,
                   polygonClip      => null,
                   layerNumbers     => null,
                   outResolutions   => null,
                   resolutionUnit   => null,
                   referencePoint   => null,
                   resampleParam    => 'resampling=AVERAGE4',
                   storageParam     => null,
                   outGeoraster     => gr_out);
  update georaster_table set georaster = gr_out where georid = 3;
  commit;
END;

In Example 5-5, the dem parameter is null, and the elevationParam average elevation must be in the same unit as the SRS. Also, in elevationParam the offset and scale keywords are not specified because they are relevant only if DEM is specified.

5.4.2 Orthorectification with DEM

The use of a DEM (Digital Elevation Model) layer improves the accuracy of the rectification process and therefore produces a higher quality output GeoRaster object.

Orthorectification with DEM requires that the source GeoRaster have a 3D SRS. The DEM must cover all the target output area, and it should be in the same SRID as the output. The resolution of the DEM should be similar to the expected resolution of the output GeoRaster object.

For orthorectification with DEM, the elevationParam average keyword is optional; and if it is not specified, the procedure estimates elevation values based on sample values extracted from the DEM on the target area.

The elevationParam offset and scale values can be used to modify the values from the DEM. For example, scale can be used for unit conversion if the DEM values are in a unit other than that of the source GeoRaster SRS, and offset can be used to perform geoidal correction or other offsetting. However, these specifications do not apply the changes to DEM values in the GeoRaster object. An alternative is to pre-process the DEM values by applying the scaling and offsetting to the DEM data before the orthorectification, as explained in Section 4.7, "Raster Data Scaling and Offsetting".

Example 5-6 example performs orthorectification with DEM. The DEM covers all the output area in a resolution approximated to the resolution of the output GeoRaster. The DEM values are in meters but the source image SRS is in feet. There is also a geoid correction on that area of about -15.3 meters:

Example 5-6 Orthorectification with DEM

DECLARE
  gr_src  sdo_georaster;
  gr_dem  sdo_georaster;
  gr_out  sdo_georaster;
BEGIN
  select georaster into gr_src from georaster_table where georid = 1;
  select georaster into gr_dem from georaster_table where georid = 5;
  delete from georaster_table where georid = 6;
  insert into georaster_table values(5, 'orthorectified with DEM',
         sdo_geor.init('rdt_4',6)) 
         returning georaster into gr_out;
  sdo_geor.rectify(inGeoRaster      => gr_src,
                   pyramidLevel     => null,
                   elevationParam   => 'average=1748.8 offset=-15.3',
                   dem              => gr_dem,
                   outSRID          => 32613,
                   outModelCoordLoc => null,
                   cropArea         => null,
                   polygonClip      => null,
                   layerNumbers     => null,
                   outResolutions   => null,
                   resolutionUnit   => null,
                   referencePoint   => null,
                   resampleParam    => 'resampling=BILINEAR',
                   storageParam     => null,
                   outGeoraster     => gr_out);
  update georaster_table set georaster = gr_out where georid = 6;
  commit;
END;

Typically, the DEM covers an area much larger than the target area, and the resolution is coarser than the target resolution of the output GeoRaster object. Using this DEM "as is" would result in poor quality orthorectification. The solution to that common problem is to crop the DEM to the target area and rescale it to the desired resolution, as shown in Example 5-7. This example uses the SDO_GEOR.rectify procedure to transform the low-resolution DEM GeoRaster object into a second DEM GeoRaster object that has the same resolution as the orthorectified GeoRaster object generated by the second call to the SDO_GEOR.rectify procedure.

Example 5-7 Orthorectification with Cropped DEM

DECLARE
  height   number := 1748.8;
  gr_src   sdo_georaster;
  gr_out   sdo_georaster;
  gr_dem   sdo_georaster;
  gr_dem2  sdo_georaster;
  gm_area  sdo_geometry;
begin
  select georaster into gr_src from georaster_table where georid = 1;
  select georaster into gr_dem from georaster_table where georid = 2;
  -- Calculate crop area
  gm_area := sdo_cs.make_2d(
             sdo_geor.generateSpatialExtent(gr_src,height),
             sdo_geor.getModelSRID(gr_dem));
  -- Rectify dem ( re-project, crop area, re-escale and resample )
  delete from georaster_table where georid = 4;
  insert into georaster_table values(4, 
              'rectified DEM',
              sdo_geor.init('rdt_4',4)) 
              returning georaster into gr_dem2;
  sdo_geor.rectify(inGeoRaster      => gr_dem,
                   pyramidLevel     => null,
                   elevationParam   => null,
                   dem              => null,
                   outSRID          => 32613,
                   outModelCoordLoc => null,
                   cropArea         => gm_area,
                   polygonClip      => null,
                   layerNumbers     => null,
                   outResolutions   => sdo_number_array(0.6,0.6),
                   resolutionUnit   => null,
                   referencePoint   => null,
                   resampleParam    => 'resampling=CUBIC',
                   storageParam     => null,
                   outGeoraster     => gr_dem2);
  update georaster_table set georaster = gr_dem2 where georid = 4;
  commit;
  -- Orthorectification with DEM
  select georaster into gr_dem2 from georaster_table where georid = 4;
  delete from georaster_table where georid = 5;
  insert into georaster_table 
         values(5, 'orthorectified', sdo_geor.init('rdt_4',5)) 
         returning georaster into gr_out;
  sdo_geor.rectify(inGeoRaster      => gr_src,
                   pyramidLevel     => null,
                   elevationParam   => 
                          'average=' || height || ' offset=-15.588',
                   dem              => gr_dem2,
                   outSRID          => 32613,
                   outModelCoordLoc => null,
                   cropArea         => gm_area,
                   polygonClip      => null,
                   layerNumbers     => null,
                   outResolutions   => sdo_number_array(0.6,0.6),
                   resolutionUnit   => null,
                   referencePoint   => null,
                   resampleParam    => 'resampling=average16',
                   storageParam     => null,
                   outGeoraster     => gr_out);
  update georaster_table set georaster = gr_out where georid = 5;
  commit;
end;
/

5.5 Image Scaling

Image scaling is the process of enlarging or shrinking an image by changing the pixel size for the row and column dimensions of an image. Image scaling resamples the pixel values from the original image to construct the rescaled version of that image.

One way to perform image scaling is to use the SDO_GEOR.scaleCopy procedure and specify for scaleParam a scaleFactor to be applied to the input image dimensions or a maxDimSize for the output image.

Another way to perform image scaling is to use the SDO_GEOR.rectify procedure and specify the resolution of the output image.

For both SDO_GEOR.scaleCopy and SDO_GEOR.rectify, the resampleParam parameter determines the resampling algorithm that will be performed on the input pixels values to determine the values of the output image.

Example 5-8 performs rescaling by using SDO_GEOR.scaleCopy and specifying the scaleFactor value as 2. The input image will have 2 times more rows and 2 times more columns than the original, and the values will be resampled by the average16 algorithm. Note that the image will be 4 times larger than the original.

Example 5-8 Image Scaling Using SDO_GEOR.scaleCopy

DECLARE
  gr_src  sdo_georaster;
  gr_out  sdo_georaster;
BEGIN
  select georaster into gr_src from georaster_table where georid = 7;
  -- Rescale
  delete from georaster_table where georid = 9;
  insert into georaster_table values(9, 're-scaled by scaleCopy',
              sdo_geor.init('rdt_4',9)) 
              returning georaster into gr_out;
  sdo_geor.scaleCopy(inGeoRaster      => null,
                     scaleFactor      => 'scaleFactor=2',
                     resampleParam    => 'resampling=AVERAGE16',
                     storageParam     => null,
                     outGeoraster     => gr_out);
  update georaster_table set georaster = gr_out where georid = 9;
  commit;
END;
/

Example 5-9 performs rescaling by using SDO_GEOR.rectify and specifying the outResolutions parameter. The input image is already rectified, and the output will have the same SRID as the input.

Example 5-9 Image Scaling Using SDO_GEOR.rectify

DECLARE
  gr_src     sdo_georaster;
  gr_out     sdo_georaster;
BEGIN
  select georaster into gr_src from georaster_table where georid = 7;
  -- Rescale
  delete from georaster_table where georid = 10;
  insert into georaster_table values(10, 're-scaled by rectify',
              sdo_geor.init('rdt_4',10)) 
              returning georaster into gr_out;
  sdo_geor.rectify(inGeoRaster      => null,
                   pyramidLevel     => null,
                   elevationParam   => null,
                   dem              => null,
                   outSRID          => null,
                   outModelCoordLoc => null,
                   cropArea         => null,
                   polygonClip      => null,
                   layerNumbers     => null,
                   outResolutions   => sdo_number_array(1.2,1.2),
                   resolutionUnit   => null,
                   referencePoint   => null,
                   resampleParam    => 'resampling=CUBIC',
                   storageParam     => null,
                   outGeoraster     => gr_out);
  update georaster_table set georaster = gr_out where georid = 10;
  commit;
END;
/

5.6 Image Stretching

Simple and linear image stretching can enhance the image color or contrast. To perform image stretching, use the SDO_GEOR_RA.rasterMathOp procedure. Example 5-10 uses known or pregenerated minimum and maximum cell values to enhance the contrast of a three-band image by linear stretching.

Example 5-10 Image Stretching Using Known Min and Max Cell Values

DECLARE
     gr1 sdo_georaster; -- source 3-band image
     gr2 sdo_georaster; -- output 3-band image
BEGIN
     select georaster into gr1 from georaster_table where georid = 1;
     select georaster into gr2 from georaster_table where georid = 2 for update;
     -- Assume the min and max cell values are (17, 163), (14, 150), and (10, 148) for the bands.
     sdo_geor_ra.rasterMathOp(gr1,
                 SDO_STRING2_ARRAY(
                              '255/(163-17)*({0}-17)',
                              '255/(150-14)*({1}-14)',
                              '255/(148-10)*({2}-10)'),
                 'celldepth=8BIT_U', gr2);
     update georaster_table set georaster = gr2 where georid = 2;
     commit;
END;
/

Example 5-11 dynamically analyzes the statistical minimum and maximum pixel values for each band of an image, and generates the arithmeticExpr parameter value for the SDO_GEOR_RA.rasterMathOp procedure, which then linearly stretches all bands of the image to the range of (0, 255).

Example 5-11 Image Stretching Using Dynamically Generated Min and Max Cell Values

DECLARE
       i integer;
       bands  number;
       gr1 sdo_georaster;
       gr2 sdo_georaster;
       stmt varchar2(5024);
       mmax number;
       mmin number;
       str varchar2(664);
       win SDO_NUMBER_ARRAY;
BEGIN
       select georaster into gr1 from georaster_table where georid = 1;
       select georaster into gr2 from georaster_table where georid = 2 for update;
       i:=0;
       bands:=SDO_GEOR.getBandDimSize(gr1);
       stmt:='';
       LOOP
            str:=to_char(i);
            mmax:=sdo_geor.generateStatisticsMax(gr1,0,'samplingFactor=1',win,str);
            mmin:=sdo_geor.generateStatisticsMin(gr1,0,'samplingFactor=1',win,str);
            stmt:=stmt ||
                        '''255/((' ||trim(to_char(mmax,'990.999'))|| ')-(' ||trim(to_char(mmin,'990.999'))|| '))*({' ||trim(to_char( i,'999' ))|| '} -('  ||trim(to_char(mmin,'990.999'))|| '))''';
            IF(i<(bands-1))
            THEN
                    stmt:=stmt||',';
            END if;
            i := i + 1;
            IF i >=bands
            THEN   EXIT;
            END IF;
       END LOOP; 
       stmt := 'call sdo_geor_ra.rasterMathOp(:1,SDO_STRING2_ARRAY('||stmt||'),'||              
                     '''celldepth=8BIT_U'',:2)';
       execute immediate stmt using gr1,in out gr2;
       dbms_output.put_line(stmt);
       update georaster_table set georaster = gr2 where georid = 2;
       commit;
END;
/

The algorithm used in Example 5-10 and Example 5-11 is called a min-max stretch. For color images another linear stretch algorithm, called a normalization stretch, provides better contrast enhancement. A normalization stretch uses a specified mean and standard deviation, but otherwise is done in a manner similar to these examples.

The same approach as in these examples can be used to stretch rasters in higher or lower cell depth, such a DEM in 32-bit integer or a temperature layer in 64-bit float, to the range of (0, 255) so that such rasters can be displayed properly.

5.7 Image Segmentation

Segmentation is a simple type of classification algorithm, and can be useful in classifying certain types of images into larger ground feature categories, such as land, cloud, water, or snow.

You can use the SDO_GEOR_RA.classify procedure to apply thresholding to images. Thresholding is the simplest segmentation, which classifies an image into two categories by using a single cell value as the threshold. The resulting image has only two values and can be cast into a binary bitmap mask directly in the same process.

You can also apply more image segmentation operations using the SDO_GEOR_RA.classify procedure, by first applying arithmetic operations on multiple bands and then classifying the results into a number of categories.

For examples of using the SDO_GEOR_RA.classify procedure, see Section 4.5, "Classification Operations".

5.8 Image Pyramiding: Parallel Generation and Partial Update

Image pyramiding is one of the most commonly used processes in building large-scale image databases. This section discusses some related techniques: pyramid generation in parallel, partial updating of pyramids, and batch and concurrent processing.

For working more efficiently with pyramids, you can generate pyramids in parallel and perform a partial update of a pyramid. (This section assumes you understand the concepts explained in Section 1.8, "Pyramids".)

For faster pyramid generation, you can specify the parallelParam parameter with the SDO_GEOR.generatePyramid procedure. In Example 5-12, the degree of parallelism is set to 4. (The actual performance improvement for pyramid generation depends on the number of CPUs available to Oracle Database.)

Example 5-12 Parallel Generation of Pyramids

DECLARE
  gr sdo_georaster;
BEGIN
 
  SELECT georaster INTO gr 
    FROM georaster_table WHERE georid = 6 FOR UPDATE;
 
  -- Generate pyramids.
  sdo_geor.generatePyramid(gr, 'rLevel=5, resampling=NN', null, 'parallel=4');
 
  -- Update the original GeoRaster object.
  UPDATE georaster_table SET georaster = gr WHERE georid = 6;
 
  COMMIT;
END;
/

To enable parallel processing of the pyramid generation, SDO_GEOR.generatePyramid performs an implicit commit operation. If an error during the call, the GeoRaster object may in an invalid state. If this occurs, use SDO_GEOR.deletePyramid to remove the newly generated and upper pyramid levels of the GeoRaster object.

You can partially update pyramids by using the SDO_GEOR.updateRaster procedure. In Example 5-13, the target GeoRaster object at a specified area (targetArea is specified as area) is updated by another GeoRaster object. The updateUpperPyramids parameter is set to true, so the upper pyramids of the target GeoRaster object are only partially updated at the specified area. In other words, the upper pyramid levels are not regenerated in full, but only the cells in that targetArea are regenerated, and thus performance is improved.

Example 5-13 Partial Updating of Pyramids

DECLARE
  gr1 sdo_georaster;
  gr2 sdo_georaster;
  area sdo_number_array := sdo_number_array(-200,-50,201,162);
BEGIN
  SELECT georaster INTO gr2 FROM georaster_table WHERE georid=0 FOR UPDATE;
  SELECT georaster INTO gr1 FROM georaster_table WHERE georid=1;
  SDO_GEOR.updateRaster(gr2, 0, null, area, gr1, 0, null, 'true');
  UPDATE GEORASTER_TABLE SET georaster=gr2 WHERE georid=0;
  COMMIT;
END;
/

Other techniques to speed up and automate the pyramiding process include batch processing and concurrent processing can be used. To batch pyramid many images in a certain area, see the example in Section 3.9, "Querying and Searching GeoRaster Objects". To process many batches concurrently, you can start different database sessions

5.9 Bitmap Pyramiding

For most raster data types, image pyramiding as described in Section 5.8 results in pyramids of great quality. However, for bitmap rasters of points, lines, or polylines, which are typically stored in 1-bit cell depth, the same pyramiding approach may not create high-quality pyramids. Distorted point patterns and dashed lines are commonly seen in those pyramids.

To solve such problems, you can use the GeoRaster raster algebra to perform bitmap pyramiding. This approach significantly improves the pyramid quality by avoiding distorted patterns, particularly dashed lines or missing lines in a bitmap raster, such as a road raster map or utility network raster map. It stores the original raster and full pyramids back into 1-bit cell depth (instead of 8-bit), and thus does not inflate the data or waste any disk space.

Example 5-14 shows how to generate high-quality pyramids for bitmap raster. Comments in the example explain the major logical steps.

Example 5-14 Bitmap Pyramiding

DECLARE 
  geor1  SDO_GEORASTER; -- source bitmap raster
  geor2  SDO_GEORASTER; -- temporary raster
  geor3  SDO_GEORASTER; -- resultant bitmap raster with fully pyramids generated
BEGIN
  -- The original 1bit raster with lines/roads value 0 and background value 1
  select georaster into geor1 
       from georaster_table where georid = 22;
 
  -- Step 1: Cast to 8bit raster while mapping 0 (roads) to 255 and 1 (bkgrd) to 0
  delete from georaster_table where georid = 21;
  insert into georaster_table values (21, null, sdo_geor.init('RDT_1',21));
  select georaster into geor2 
    from georaster_table where georid = 21 for update;
  sdo_geor_ra.classify(
        geor1,
        '{0}',
        SDO_NUMBER_ARRAY(1),
        SDO_NUMBER_ARRAY(255, 0),
        'celldepth = 8BIT_U', 
        geor2);
 
  -- Step 2: Generate pyramids on the 8bit raster.
  sdo_geor.generatePyramid(geor2, 'rLevel=15, resampling=bilinear');
 
  -- Step 3, Map value to either 0 or 1. 
  -- Depending on the source raster, adjust value 253 to a different number to improve qualtiy.
  sdo_geor_ra.rasterUpdate(
         geor2,
         null,-- update the raster's full pyramid as well
         SDO_STRING2_ARRAY('{0}<253','{0}>=253'),
         SDO_STRING2_ARRAYSET(SDO_STRING2_ARRAY('0'),SDO_STRING2_ARRAY('1')));
 
  -- Step 4, Cast back to 1bit raster with full pyramids.
  delete from georaster_table where georid = 20;
  insert into georaster_table values (20, null, sdo_geor.init('RDT_1',20));
  select georaster into geor3 
         from georaster_table where georid = 20 for update;
  sdo_geor.changeFormatCopy(geor2, 'celldepth=1BIT pyramid=true', geor3);
 
  -- Step 5, Optionally add a good colormap for the 1bit raster to display roads as white.
  sdo_geor.setColorMap(geor3, 1, 
         sdo_geor_colormap(sdo_number_array(0, 1),
                        sdo_number_array(0, 255),
                        sdo_number_array(0, 255),
                        sdo_number_array(0, 255),
                        sdo_number_array(255, 255)));
 
  -- Commit the resultant raster, which can be used to overwrite the original raster after quality checking.
  UPDATE georaster_table SET georaster = geor3 WHERE georid=20;
  COMMIT;
END;
/

5.10 Vegetation Index Computation

In remote sensing, the Normalized Difference Vegetation Index (NDVI) is a widely used vegetation index, enabling users to quickly identify vegetated areas and monitor the growth and "condition" of plants. Using Landsat TM imagery, the standard NDVI computation formula is: (TM4 - TM3) / (TM4 + TM3).

Example 5-15 takes a Landsat 7 ETM+ image and computes the NDVI, which is stored as another raster of floating number data type. Note that in the GeoRaster algebra language, band numbering starts with 0, so the formula translates into the expression: ({3}-{2})/({3}+{2}).

Example 5-15 Vegetation Index Computation

DECLARE 
  geor1    SDO_GEORASTER; 
  geor2    SDO_GEORASTER; 
EBGIN
  -- Source ETM+ image
  select georaster into geor1 from georaster_table where georid = 2; 
  -- Store NDVI 
  select georaster into geor2 from georaster_table where georid = 3 for update; 
  sdo_geor_ra.rasterMathOp(geor1,
       SDO_STRING_ARRAY('({3}-{2})/({3}+{2})'),
       'celldepth=32bit_real',geor2);
  update georaster_table set georaster = geor2 where georid = 3;
  commit;
end;
/

In addition to NDVI, there are many other vegetation indexes in the area of remote sensing. Many of these can be similarly computed using the GeoRaster raster algebra.

5.11 Tasseled Cap Transformation

Tasseled Cap Transformation (TCT) is a useful tool for analyzing physical ground features using remotely sensed imagery. With various Landsat imagery, it uses 5 bands of either original digital number (DN) or reflectance data to generate 6 new bands, each of which represents different ground features. The 6 resulting bands are generally called (soil) brightness, (vegetation) greenness, (soil and canopy) wetness, haze, TC5, and TC6. Each one or a combination of them is useful for different applications, such as crop growth monitoring and analysis, biomass study, and agriculture planning.

Example 5-16 takes the DN data of a Landsat 5 TM image as input, executes the TCT using the GeoRaster raster algebra, and creates a new image holding the results.

Example 5-16 Tasseled Cap Transformation

declare
    gr1 sdo_georaster;
    gr2 sdo_georaster;
    ret varchar2(32);
begin
    select georaster into gr1 from georaster_table where georid = 2;
    select georaster into gr2 from georaster_table where georid = 4 for update;
    sdo_geor_ra.rasterMathOp(
      gr1,
      SDO_STRING2_ARRAY(
         '0.3561*{0}+0.3972*{1}+0.3904*{2}+0.6966*{3}+0.2286*{4}+0.1596*{6}',
         '(-0.3344)*{0}-0.3544*{1}-0.4556*{2}+0.6966*{3}-0.0242*{4}-0.2630*{6}',
         '0.2626*{0}+0.2141*{1}+0.0926*{2}+0.0656*{3}-0.7629*{4}-0.5388*{6}',
         '0.0805*{0}-0.0498*{1}+0.1950*{2}-0.1327*{3}+0.5752*{4}-0.7775*{6}',
         '(-0.7252)*{0}-0.0202*{1}+0.6683*{2}+0.0631*{3}-0.1494*{4}-0.0274*{6}',
         '0.4000*{0}-0.8172*{1}+0.3832*{2}+0.0602*{3}-0.1095*{4}+0.0985*{6}' ),
      'celldepth=32BIT_REAL',
      gr2); 
    update georaster_table set georaster = gr2 where georid = 4;
    commit;
end;
/

You can also use the same raster algebra language to add code in Example 5-16 to convert the 32-bit floating number image into an 8-bit integer image and to apply image stretching (described in Section 5.6) on the resulting TCT image to generate a new GeoRaster object for visualization and analysis.

In addition to using the optimized implementation of raster algebra algorithms and the embedded parallel processing, you can further take advantage of the Oracle grid computing infrastructure to quickly compute NDVI or apply TCT on thousands of images stored in the GeoRaster database.

5.12 Image Masking

To perform image masking, an application can query the GeoRaster database for bitmap masks, retrieve the desired bitmap mask or masks, and apply the masking operation on the target GeoRaster object for the purpose of displaying the object or performing some other processing. A bitmap mask (described in Section 1.9) can be stored as an independent GeoRaster object; it can also be stored as metadata inside a GeoRaster object and be associated with a single band or with the whole GeoRaster object.

You can also perform masking operations inside the database to generate new GeoRaster objects, using the SDO_GEOR.mask procedure.

5.13 Band Merging

For image classification, time series analysis, and raster GIS modeling, multiple bands or layers of different GeoRaster objects may need to be merged into a single GeoRaster object. This operation is called band or layer merging in GeoRaster, and can be performed by using the SDO_GEOR.mergeLayers procedure. You can either append specified bands of a source GeoRaster object to a target GeoRaster object or merge different bands from two GeoRaster objects into a new GeoRaster object. By doing this merging or appending iteratively, you can merge an unlimited number of bands into a single GeoRaster object.

Example 5-17 assumes there are eight GeoRaster objects, each of which contains only one band loaded from a single-band Landsat ETM+ image file in GeoTIFF format. The number of the band in each GeoRaster object is the same as the GEORID column value for the GeoRaster object. The example merges all bands into a single GeoRaster object to create a complete ETM+ scene.

Example 5-17 Band Merging

DECLARE
    gr1 sdo_georaster;
BEGIN
    select georaster into gr1 from georaster_table where georid = 1 for update;
    for rec in (select georaster from georaster_table 
                     where georid >= 2 and georid <= 8 
                     order by georid)
    loop
       sdo_geor.mergelayers(gr1, rec.georaster);
    end loop;
    update georaster_table set georaster = gr1 where georid = 1;
    commit;
END;
/

5.14 Image Appending

You can append one image to another image when the two images have the same number of bands. Image appending is useful when the geospatial images are collected at intervals and the captured image later needs to be appended to the existing image to make a large image of the whole spatial area. Image appending is also useful for updating the existing image with a new image.

The SDO_GEOR_AGGR.append procedure implements image appending by partially updating the existing GeoRaster object with another GeoRaster object. If the existing GeoRaster object contains pyramids, the pyramids with blocking are partially updated with the new data.

Example 5-18 appends one image to another, with pyramids with blocking are updated at the same time. Because the appendParam parameter specifies 'nodata=true', the NODATA values in the overlapping area are considered transparent.

Example 5-18 Appending One Image to Another Image

DECLARE
    gr1 sdo_georaster;
    gr1 sdo_georaster;
BEGIN
     select georaster into gr1 from georaster_table where georid = 1 for update;
     select georaster into gr2 from georaster_table where georid = 2;
     sdo_geor_aggr.append(gr1, gr2, 0, 'nodata=true');
     update georaster_table set georaster = gr1 where georid= 1;
     commit;
END;
/

5.15 Large-Scale Image Mosaicking

A large geospatial area typically consists of many smaller aerial photographs or satellite images. Large-scale image mosaicking can stitch these small geospatial images into one large image to get a better view of the whole spatial area. GeoRaster provides large-scale mosaicking functions that allow gaps, overlaps, and missing source GeoRaster objects. It supports both rectified and unrectified images. It supports internal reprojection and rectification, common point rules, and simple color balancing. You can also mosaic at a certain pyramid level. This mosaicking process results in a single GeoRaster object, which is also called a physical mosaic as opposed to virtual mosaic (For information about virtual mosaic, see Section 5.16).

The SDO_GEOR.mosaic and SDO_GEOR_AGGR.mosaicSubset procedures provide support for image mosaicking; however, you are strongly encouraged to use SDO_GEOR_AGGR.mosaicSubset because it provides much more advanced features and options, and it is also implemented with parallelism. SDO_GEOR_AGGR.mosaicSubset can take a virtual mosaic, such as a list of GeoRaster tables, a database view with a GeoRaster column, or a REF CURSOR, as the source images.

The SDO_GEOR.mosaic procedure mosaics a set of source GeoRaster images that are rectified, are geospatially aligned under the same SRID, and have the same resolution. The result of the mosaic is another GeoRaster object. If there are overlaps between the source images, the mosaic result will have the last source image's content at the overlapping area. This procedure works well for preprocessed and perfectly aligned source images.

In the examples in this section, the source images are stored in source GeoRaster tables GRTAB, GRTAB1, and GRTAB2, which are defined with the following columns:

  (id          NUMBER PRIMARY KEY,
  cloud_cover  NUMBER     -- percentage of cloud coverage 
  last_update  TIMESTAMP  -- GeoRaster object's last update time
  grobj        SDO_GEORASTER )

Oracle Spatial and Graph spatial indexes have been created on the spatialExtent attribute of the GeoRaster object in these tables.

In these examples, the mosaicked image is stored in GEORASTER_TABLE, which is defined in Section 1.4.1, "Storage Parameters".

Example 5-19 shows the SDO_GEOR.mosaic procedure.

Example 5-19 SDO_GEOR.mosaic (Table and Column Name)

DECLARE
  gr sdo_georaster;
BEGIN
  INSERT INTO georaster_table (georid, georaster) 
      VALUES (12, sdo_geor.init('rdt_1'))
      RETURNING georaster INTO gr;
  sdo_geor.mosaic('grtab', 'grobj', gr, 'blocksize=(512,512,1)');
  UPDATE georaster_table SET georaster=gr WHERE id=12;
END;
/

In the real world, however, the source images are often collected under different circumstances so as to have different resolutions or large areas of overlap, or using a different georeference system. In such cases, you can use the SDO_GEOR_AGGR.mosaicSubset procedure to mosaic these source images into one uniform mosaicked image. Compared to SDO_GEOR.mosaic, the SDO_GEOR_AGGR.mosaicSubset procedure provides more features and options:

  • The source images do not have to be in the same coordinate system (SRID) and have the same georeferencing information or resolutions.

  • The source images can be mosaicked on a user-specified pyramid level.

  • The source images can be mosaicked on user-specified bands.

  • The output images can have a different coordinate system and resolution than the input images (outSRID and outResolutions parameters).

  • You have more control on the output of the overlapping area through the mosaicParam parameter: commonPointRule can specify which cell value to use for the output at the overlapping area, and NODATA can indicate whether to consider the NODATA value at the overlapping area.

  • The output mosaicked image can be aligned at a specified point (the reference point). The source image can be resampled in order to align with the reference point if the source image is out of alignment more than the resampleTolerance value specified in mosaicParam.

  • If there is small gap between the source images that is less than 2 pixels wide, it can be filled using the neighboring pixel values when fillGap is true in mosaicParam.

  • Limited color balancing (linear stretching and normalization) is supported.

  • Parallel processing is supported to speed up the mosaicking process.

Example 5-20 uses SDO_GEOR_AGGR.mosaicSubset to mosaic all the source images from two GeoRaster tables (GRTAB1 and GRTAB2) into a large mosaicked image in SRID 4326 with a resolution of 30 meters on the x and y dimensions.

Example 5-20 SDO_GEOR_AGGR.mosaicSubset

DECLARE
  resolutions sdo_number_array;
  gr sdo_georaster;
BEGIN
    insert into georaster_table (georid, georaster)
        values (10, sdo_geor.init('RDT_1',10))
         returning georaster into gr;
 
    resolutions := sdo_number_array(30, 30);
    sdo_geor_aggr.mosaicSubset('grtab1, grtab2', 'grobj, grobj',
                               0, 4326, null, null, null,
                               null, null, null, resolutions, 'unit=meter',
                               'commonPointRule = end, nodata=true, resampleTolerance=0.2, resampling=bilinear, fillGap=true',
                               'blocksize=(512, 512, 3)', gr, null, 'parallel=4');
 
      update georaster_table set georaster = gr where georid=10;
      commit;                                                              
END;
/

In Example 5-20:

  • Any source image that is not rectified is rectified; any source image that is not in SRID 4326 is reprojected to SRID 4326.

  • Any source image that has a resolution other than 30 meters is scaled to a resolution of 30 meters.

  • The nodata keyword in the mosaicParam parameter is specified as true, which means the NODATA values in the overlapping area are not considered.

  • The resampleTolerance keyword in the mosaicParam parameter is specified as 0.2, which means that if the source image is offset from the target by more than 0.2 pixel, the source image is resampled.

  • The resampling method is specified as bilinear in the mosaicParam parameter.

  • The degree of parallelism is specified as 4 in the parallelParam parameter.

You can call SDO_GEOR_AGGR.validateForMosaicSubset before calling SDO_GEOR_AGGR.getMosaicSubset to make sure that the source images can be mosaicked.

5.15.1 Parallel Compression, Copying, Subsetting, Reprojection, and Rectification

The SDO_GEOR_AGGR.mosaicSubset procedure can take a single GeoRaster object as input. You can use this procedure to conduct several types of parallel operations, including parallel compression and decompression, parallel copying or change format copying, parallel subsetting, parallel reprojection, and parallel rectification. This section gives some examples for these operations. In all these cases, the SDO_GEOR_AGGR.mosaicSubset procedure works on single GeoRaster objects.

Example 5-21 shows parallel compression using the SDO_GEOR_AGGR.mosaicSubset procedure. This applies to both DEFLATE and JPEG compression and decompression.

Example 5-21 Parallel Compression

DECLARE
  gr sdo_georaster;
  cur sys_refcursor;
  crop_area sdo_geometry := null;
BEGIN
  -- create a new georaster object with georid = 2 
  -- to hold the compressed image
  delete from georaster_table where georid = 2;
  insert into georaster_table(georid, georaster) values (2, 
     sdo_geor.init('RDT2', 2)) returning georaster into gr;
 
  -- compress the image with georid = 1 into JPEG using parallel degree of 8 
  open cur for 'select georaster from georaster_table where georid = 1';
  sdo_geor_aggr.mosaicSubset(cur, 0, null, null, null, crop_area, 
                             null, null, null, null, null, null,
                             'compression=JPEG-F', gr, null, 'parallel=8');
 
  update georaster_table set georaster = gr where georid = 2;
  commit;
END;
/

Example 5-22 shows parallel copying using the SDO_GEOR_AGGR.mosaicSubset procedure.

Example 5-22 Parallel Copying

DECLARE
  gr sdo_georaster;
  cur sys_refcursor;
  crop_area sdo_geometry := null;
BEGIN
  -- create a new georaster object with georid = 2 to hold the copy
  delete from georaster_table where georid = 2;
  insert into georaster_table(georid, georaster) values (2, 
     sdo_geor.init('RDT2', 2)) returning georaster into gr;
 
  -- make a copy of the image with georid = 1 using parallel degree of 8 
  open cur for 'select georaster from georaster_table where georid = 1';
  sdo_geor_aggr.mosaicSubset(cur, 0, null, null, null, crop_area,
                             null, null, null, null, null, null,
                             'pyramid=true', gr, null, 'parallel=8');
  update georaster_table set georaster = gr where georid = 2;
  commit;
END;
/

In Example 5-22, if you adjust the storageParam parameter, it works as a parallelized SDO_GEOR.changeFormatCopy operation. If you apply a crop_area (instead of using the default value null), it works as a parallelized SDO_GEOR.subset operation and can do polygon clipping.

Example 5-23 shows parallel rectification or reprojection using the SDO_GEOR_AGGR.mosaicSubset procedure. The output resolution must be between 0.75 and 1.5 times the resolution of the specified source pyramid level if this approach for rectification and reprojection is used.

Example 5-23 Parallel Rectification or Reprojection

DECLARE
  gr sdo_georaster;
  cur sys_refcursor;
  crop_area sdo_geometry := null;
  out_res sdo_number_array := sdo_number_array(30, 30);
BEGIN
  -- create a new georaster object with georid = 2 to hold the result
  delete from georaster_table where georid = 2;
  insert into georaster_table(georid, georaster) values (2, 
     sdo_geor.init('RDT2', 2)) returning georaster into gr;
 
  -- rectify the image with georid = 1 into SRID 32611 and 
  -- resolution 30 by 30 using parallel degree of 4 
  open cur for 'select georaster from georaster_table where georid = 1';
  sdo_geor_aggr.mosaicSubset(cur, 0, 32611, null, null, crop_area,
                             null, null, null, out_res, null, 
                             'resampling=bilinear', null, gr, null, 
                             'parallel=4');
  update georaster_table set georaster = gr where georid = 2;
  commit;
END;
/

To illustrate the parallelized operations, the examples in this section use a null value for most parameters. In your applications, you can apply all other parameters of the SDO_GEOR_AGGR.mosaicSubset procedure; however, the mosaicParam parameter has no effect when the input is a single GeoRaster object.

5.16 Virtual Mosaic

For some applications, mosaicking a collection of images into a single physical mosaic is not necessary or desirable. For example, you might not have enough disk space for storing the mosaic separately or you simply want to save disk space. Another example is if you do not want to keep two identical copies of the same data set but prefer to have the original data set stored as is, such as a DEM data set, yet you want to query over this data set seamlessly. Yet another example is if you want to apply different processing and mosaicking rules for the same region when mosaicking the source images -- a physical mosaic has no such flexibility.

In such cases, instead of mosaicking a set of GeoRaster images into one large GeoRaster image and storing it in a GeoRaster table, you can create a virtual mosaic. A virtual mosaic treats a set of GeoRaster images as one large virtually mosaicked image, without storing it in a GeoRaster table.

In GeoRaster, a virtual mosaic is defined as any large collection of georeferenced GeoRaster objects, rectified or unrectified, from one or more GeoRaster tables or views that is treated as if it is a single GeoRaster object. Pyramids of virtual mosaic are supported. A virtual mosaic can contain unlimited number of images, and a whole GeoRaster database can be treated as a virtual mosaic. You issue a single call to query the virtual mosaic based on area-of-interest (that is, subsetting or cropping), and you can request the cropped images to be in different coordinate system with different resolutions. On-the-fly transformations with resampling and mosaicking with common point rules, based on user requests, are done internally and automatically during the query processes.

The following are ways to define a virtual mosaic:

  • As a GeoRaster table or a list of GeoRaster tables (see Section 5.16.1)

  • As a database view with a GeoRaster column (see Section 5.16.2)

  • As a SQL query statement (a cursor) that results in a collection of GeoRaster objects (see Section 5.16.3)

Regardless of how the virtual mosaic is defined, the GeoRaster objects in the GeoRaster tables must have the spatialExtent attribute generated or set; otherwise, the SDO_GEOR_AGGR.getMosaicSubset and SDO_GEOR_AGGR.mosaicSubset procedures return an empty lob locator or empty GeoRaster object. For general use cases and best query performance, you should always create a spatial index beforehand on the spatialExtent attribute.

After a virtual mosaic is defined, you can use these procedures to query or process it:

  • SDO_GEOR_AGGR.getMosaicSubset to perform on-the-fly queries over the virtual mosaic

    In spatial query of any portion of that virtually mosaicked image, the SDO_GEOR_AGGR.getMosaicSubset procedure performs the mosaic operation dynamically for the queried area and returns the required result in a BLOB on-the-fly, as if it were subsetting a physically stored mosaicked image.

  • SDO_GEOR_AGGR.mosaicSubset to store the mosaicked subset in the database as a GeoRaster object

    The SDO_GEOR_AGGR.mosaicSubset procedure performs the mosaic operation for the queried area and stores the required result in another GeoRaster object persistently

For a typical workflow of using virtual mosaic, see Section 5.16.4, "Using Virtual Mosaic in Applications" and Section 5.16.5, "Special Considerations for Large-Scale Virtual Mosaic".

5.16.1 Virtual Mosaic as One or a List of GeoRaster Tables

A virtual mosaic can be defined as one GeoRaster table or a list of GeoRaster tables. Applications specify each table and its GeoRaster column. In this approach, all GeoRaster objects in the specified GeoRaster columns of those GeoRaster tables are part of the virtual mosaic.

Example 5-24 specifies the source images for virtual mosaicking in a list of GeoRaster tables (GRTAB1, GRTAB2, and GRTAB3, which have the same definitions as GRTAB in Section 5.15).

Example 5-24 Virtual Mosaic as a List of GeoRaster Tables

DECLARE
  lb blob;
  cropArea sdo_geometry;
  outArea  sdo_geometry := null;
  outWin   sdo_number_array:=null;
  resolutions sdo_number_array;
BEGIN
    dbms_lob.createTemporary(lb, TRUE);
 
     cropArea :=  sdo_geometry(2003, 32610, null,                 
                    sdo_elem_info_array(1, 1003, 3), 
                    sdo_ordinate_array(399180, 4247820, 
                                       496140,4353900) );
      resolutions := sdo_number_array(30, 30);
     sdo_geor_aggr.getMosaicSubset('grtab1, grtab2, grtab3', 
                 'grobj, grobj, grobj', 
                 0, 32610, null, null, cropArea,
                 null, null, null, resolutions, null, 
                 'commonPointRule = end, nodata=true', 
                 lb, outArea, outWin);
    dbms_lob.freeTemporary(lb);
    if outWin is not null then
        dbms_output.put_line('output window: (' || outWin(1) || ',' || outWin(2) ||', ' || outWin(3) || ', ' || outWin(4) || ')');
    end if;
END;
/

5.16.2 Virtual Mosaic as a View with a GeoRaster Column

A virtual mosaic can be defined as one database view with a GeoRaster column. Applications specify the view name and its GeoRaster column. In this approach, all GeoRaster objects in the specified GeoRaster column of the view are part of the virtual mosaic. This approach allows you to select the images for the virtual mosaic in complex ways from any number of GeoRaster tables, taking advantage of the spatial index and any other relevant indexes.

You can also define a virtual mosaic as a list combining GeoRaster views and GeoRaster tables.

When a virtual mosaic is defined as a database view, the view can be specified in the georasterTableNames parameter when you query it. Example 5-25 queries the virtual mosaic defined as a view. Note that in this example, the queries sort the images based on their creation time and pick the latest (newest) image for the resulting mosaic in the overlapping areas.

Example 5-25 Using a View on GeoRaster Tables for Virtual Mosaic

Create or replace view grview as select * from (
       Select grobj, last_update from grtab1 where cloud_cover=0 union all
       Select grobj, last_update from grtab2 where cloud_cover=0 union all
       Select grobj, last_update from grtab3 ) order by last_update;

DECLARE
  lb blob;
  cropArea sdo_geometry;
  outArea  sdo_geometry := null;
  outWin   sdo_number_array:=null;
  resolutions sdo_number_array;
BEGIN
    dbms_lob.createTemporary(lb, TRUE);
 
     cropArea :=  sdo_geometry(2003, 32610, null,                 
                    sdo_elem_info_array(1, 1003, 3), 
                    sdo_ordinate_array(399180, 4247820, 
                                       496140,4353900) );
      resolutions := sdo_number_array(30, 30);
     sdo_geor_aggr.getMosaicSubset('grview', 'grobj', 
                 0, 32610, null, null, cropArea,
                 null, null, null, resolutions, null, 
                 'commonPointRule = end, nodata=true', 
                 lb, outArea, outWin);
    dbms_lob.freeTemporary(lb);
    if outWin is not null then
        dbms_output.put_line('output window: (' || outWin(1) || ',' || outWin(2) ||', ' || outWin(3) || ', ' || outWin(4) || ')');
    end if;
END;
/

5.16.3 Virtual Mosaic as a SQL Query Statement or a Cursor

Instead of creating a view, you can define a virtual mosaic as a SQL statement or a runtime database cursor, which selects a collection of GeoRaster objects from the database. Applications create the cursor from the SQL statement and use the cursor as the virtual mosaic. In this definition, all GeoRaster objects in the cursor are part of the virtual mosaic. This approach allows you to select the images for the virtual mosaic in complex ways from any number of GeoRaster tables. However, the spatial indexes are not automatically used in queries over this type of virtual mosaic. To take advantage of spatial indexes, dynamically add a spatial query condition directly using the query window to the SQL statement, so that all images in that query window can be more quickly located.

The SDO_GEOR_AGGR.getMosaicSubset and SDO_GEOR_AGGR.mosaicSubsetprocedures accept a cursor of GeoRaster objects as the virtual mosaic, as shown in Example 5-26. Note that in this example, the queries sort the images based on their creation time and pick the latest (newest) image for the resulting mosaic in the overlapping areas. For best performance when there are many GeoRaster objects in the table, the query of the cursor should use the spatial query window to filter out the unrelated GeoRaster objects, as described in the preceding paragraph.

Example 5-26 Using a Cursor for Virtual Mosaic

DECLARE
  lb blob;
  outArea  sdo_geometry := null;
  outWin   sdo_number_array:=null;
  resolutions sdo_number_array;
  mosaic_stmt  varchar2(1000);
  condition        varchar2(1000);
BEGIN
    dbms_lob.createTemporary(lb, TRUE);
 
    resolutions := sdo_number_array(30, 30);
 
   -- Define the query window (cropArea)
   cropArea := sdo_geometry(2003, 32610, null, 
                           sdo_elem_info_array(1, 1003, 3), 
                           sdo_ordinate_array(399180, 4247820, 496140,4353900) );
 
    -- Define the virtual mosaic
    mosaic_stmt := 'select grobj from (select grobj, last_update from grtab1 ' ||
                   'where cloud_cover=0  union all select grobj, last_update from grtab2 ' ||
                   'where cloud_cover=0) t ';
 
   -- Apply filtering using the query window (cropArea) to speed up query performance
    condition := 'where sdo_anyinteract(t.grobj.spatialExtent,:1) = ''true'' ' ||
                 ' order by last_update'; 
 
   -- Open the virtual mosaic for query
    open cur for mosaic_stmt || condition using cropArea;
 
   -- Query the virtual mosaic (make sure the cropArea used here is the same
   -- as the one used at opening the cursor)
    sdo_geor_aggr.getMosaicSubset(cur, 
                 0, 32610, null, null, cropArea,
                 null, null, null, resolutions, null, 
                 'commonPointRule=end, nodata=true', 
                 lb, outArea, outWin);
    dbms_lob.freeTemporary(lb);
    close cur;
    if outWin is not null then
        dbms_output.put_line('output window: (' || outWin(1) || ',' || outWin(2) ||', ' || outWin(3) || ', ' || outWin(4) || ')');
    end if;
END;
/

5.16.4 Using Virtual Mosaic in Applications

Virtual mosaic can be used as an image serving engine and in a variety of other application scenarios. The definitions of virtual mosaics can be stored by applications separately as strings or other forms. Besides the major query procedures SDO_GEOR_AGGR.getMosaicSubset and SDO_GEOR_AGGR.mosaicSubset, GeoRaster provides other subprograms in the SDO_GEOR_AGGR package to facilitate application development:

SDO_GEOR_AGGR.validateForMosaicSubset, SDO_GEOR_AGGR.getMosaicExtent, and SDO_GEOR_AGGR.getMosaicResolutions can be called in an application to make sure that the virtual mosaic is valid and that the spatial query falls inside the virtual mosaic. The following steps describe a possible workflow for virtual mosaic in an application:

  1. Define a virtual mosaic. For example:

    Create or replace view grview as select * from (
    Select grobj, last_update from grtab1 where cloud_cover=0 union all
    Select grobj, last_update from grtab2 where cloud_cover=0 union all
    Select grobj, last_update from grtab3 ) order by last_update;
    

    Note that tables GRTAB1, GRTAB2, and GRTAB3 were created using the same definition as GRTAB in Section 5.15, "Large-Scale Image Mosaicking", and Oracle Spatial and Graph spatial indexes have been created on the spatialExtent attribute of the GeoRaster object in these tables.

  2. Validate the virtual mosaic data set. For example:

    EXECUTE SDO_GEOR_AGGR.validateForMosaicSubset('grview', 'grobj', OUTSRID, OUTResolutions);
    

    A validation error table can be created and passed to the call if more detailed validation information is needed. See the SDO_GEOR_AGGR.validateForMosaicSubset reference section for details.

  3. Get the spatial extent of the virtual mosaic. For example:

    SELECT SDO_GEOR_AGGR.getMosaicExtent('grview', 'grobj', OUTSRID) from dual;
    
  4. Get the resolution range of the existing source images. For example:

    SELECT SDO_GEOR_AGGR.getMosaicResolutions('grview', 'grobj', 'unit=meter') from dual;
    

    The resolution range reflects the minimum and maximum resolutions of the source images, including all pyramid levels.

  5. Based on the information acquired in the preceding two steps, pass in the spatial query window cropArea and OUTResolutions according to the application requests to get a subset of the virtual mosaic and optionally to apply different resampling methods, different common point rules, special nodata handling, and color balancing. For example:

    SDO_GEOR_AGGR.getMosaicSubset('grview', 'grobj', null, OUTSRID, null, null,
      cropArea, null, null, null, OUTResolutions, null, 
      'commonPointRule=end, nodata=true', lb, outArea, outWin);
    

    Note that OUTResolutions must be within the source image resolution range. If OUTResolutions is the same as the resolutions of the source image at a specified pyramid level, the pyramid data is used in the output mosaic; otherwise, the source image is scaled to the target resolution.

    A typical application repeatedly applies this step to query different areas of interest over the same virtual mosaic for image display, image distribution, or other purposes.

5.16.5 Special Considerations for Large-Scale Virtual Mosaic

A virtual mosaic can contain just several images, but it can also contain tens of thousands or millions of images. Both SDO_GEOR_AGGR.getMosaicSubset and SDO_GEOR_AGGR.mosaicSubset automatically search (using native spatial indexes) the virtual mosaic for all images touching or inside the cropArea and check the resolutions of those images and their pyramids. Only those images or their appropriate pyramid levels touching or inside the cropArea and with their resolutions close to the requested resolution will be used in the mosaicking process. So, the configuration of the source images and their pyramids is critical for the quality of the results and the overall query performance.

The guideline is to avoid too many small images from either different source images or their pyramids in the requested crop areas at the requested resolution.

For a smaller virtual mosaic with only a limited number of images, simply generate full pyramids for each source image, and the query performance will be good for most applications.

For a large area with a larger number of images (more than a few hundred images), the application can generate only a certain number of pyramid levels for each source image, mosaic their top pyramids into new GeoRaster objects, and then generate pyramids for those mosaics, and so forth. For large-scale web visualization projects, all images at source resolutions and at lower resolution levels might be stored as GeoRaster objects without any pyramids built for them.

In these cases (large number of images and large-scale web visualization), if each source image is small and there are many resolution levels in the virtual mosaic, a query on the lower resolution levels would involve metadata resolution queries on many unnecessary images at the higher resolution levels, which slows the query. To improve performance, applications can define many virtual mosaics, each of which includes only all the images at a specific resolution or a few resolution levels. Then, the application finds the right virtual mosaic or mosaics based on the requested resolution as the first step, and then only spatially queries those selected virtual mosaics. This approach can significantly improve performance.

In addition to the preceding considerations, see Section 5.16.5.1, "Improving Query Performance Using MIN_X_RES$ and MAX_X_RES$" for queries where many different resolution levels are involved for the same area.

5.16.5.1 Improving Query Performance Using MIN_X_RES$ and MAX_X_RES$

A more general solution (instead of defining multiple virtual mosaics) for speeding virtual mosaic queries if there are many different resolution levels involved for the same area is to use the MIN_X_RES$ and MAX_X_RES$ columns in the GeoRaster tables or views. You must define these columns (NUMBER data type) in the GeoRaster tables of a virtual mosaic, where they specify the minimum and maximum spatial resolution values, respectively, of the source GeoRaster object. After these columns are added and populated with correct resolution data, the SDO_GEOR_AGGR.getMosaicSubset procedure will (if you use the format with the georasterTableNames parameter) use the resolution range stored in these columns to filter out the source GeoRaster objects that are not at the requested resolutions as specified in the outResolutions parameter. This avoids parsing the metadata of each GeoRaster objects in the cropArea, thus significantly improving performance.

To use this approach, follow these steps:

  1. Add the columns MIN_X_RES$ and MAX_X_RES$ to the GeoRaster tables. For example:

    ALTER TABLE georaster_table ADD (MIN_X_RES$ number, MAX_X_RES$ number);
    
  2. Populate the MIN_X_RES$ column. For example:

    UPDATE georaster_table t 
      SET min_x_res$ = (select column_value from the (select sdo_geor.generateSpatialResolutions(georaster) from dual)
      WHERE rownum=1);
    
  3. Populate the MAX_X_RES$ column. For example:

    UPDATE georaster_table t 
      max_x_res$ = min_x_res$ * power(2, sdo_geor.getPyramidMaxLevel(t.georaster));
    

If the virtual mosaic is defined as a view, the view should also have both columns. For example, the view definition in Example 5-25, "Using a View on GeoRaster Tables for Virtual Mosaic" must be changed to the following:

Create or replace view grview as select * from ( 
       Select grobj, min_x_res$, max_x_res$, last_update from grtab1 where cloud_cover=0 union all
       Select grobj, min_x_res$, max_x_res$, last_update from grtab2 where cloud_cover=0 union all 
       Select grobj, min_x_res$, max_x_res$, last_update from grtab3 ) 
       order by last_update;

After a virtual mosaic is defined as described in this section, applications can query and use it in the same ways as with all other virtual mosaics, but with better performance for large-scale virtual mosaics that involve many resolution levels. For more information, see the SDO_GEOR_AGGR.getMosaicSubset and SDO_GEOR_AGGR.mosaicSubset reference sections.

5.17 Image Serving

Serving of image and raster data to clients or applications is supported through many features of the GeoRaster PL/SQL and Java APIs.

Direct image serving includes searching and then subsetting or cropping the rasters (SDO_GEOR.getRasterSubset), applying reprojection and rectification on-the-fly while cropping the images (SDO_GEOR.reproject and SDO_GEOR.rectify), and directly exporting to files (SDO_GEOR.exportTo).

Virtual mosaic is used mainly, and effectively, to serve an image database to various applications, particularly when you do not want to create large physical mosaics. Virtual mosaic does not require the source images to be preprocessed or mosaicked beforehand. Instead, all images are stored as is, and the whole image data set can be served based on small areas of interest using single calls (SDO_GEOR_AGGR.getMosaicSubset) to the server.

Often, one or a series of preprocessing operations are applied to multiple GeoRaster objects to create the resulting GeoRaster object, and then the features described in this section are used on the resulting GeoRaster object to serve the raster data directly to applications. Thus, a rich set of GeoRaster image manipulation and raster algebra capabilities (described in Chapter 3, "Basic GeoRaster Operations", Chapter 4, "Raster Algebra and Analytics", and this chapter) can be incorporated into the workflow to meet complex image serving requirements.