Question

Automatic Georeferencing with FME

  • 24 November 2014
  • 7 replies
  • 13 views

Badge
Hi All,

 

    I have a large number of rasters I wish to automatically georeference with FME to the "*XY-MT*" projection ("arbitrary metres").

 

    

 

    Each raster has a red dot and a yellow dot that are consistent across rasters and can be used for the georeference. I only require rescaling and positioning, not rotation or warping etc, so two points is fine.

 

    I can already extract these two points (RasterExpressionEvaluator -> RasterToPolygonCoercer ... etc).

 

    

 

    My problem is, now that I have the raster Column/Row for these two features (the location of those dots in the raster), I don't know what to do. The red feature should be placed at "0,0", and the yellow at "5000,0" in the XY-MT projection (or something similarly consistent).

 

    

 

    I've tried using RasterGCPSetter, but the output tif doesn't function as though it's projected (either in QGIS, or within the Inspector).

 

    The RasterGeoReferencer transformer seems to want things I can't give it easily.

 

    

 

    Any suggestions for how to do this?

 

    What does FME do with GCP's? The help doesn't say much.

 

    Thanks,

 

    Jonathan

7 replies

Userlevel 2
Badge +17
Hi Jonathan,

 

 

I think the following method is possible.

 

Assuming these coordinates in the coordinate system of the original raster.

 

red dot: (x0, y0)

 

yellow dot: (x1, y1)

 

lower-left corner of the raster: (xmin, ymin)

 

upper-right corner of the raster: (xmax, ymax)

 

You already have extracted x0, y0, x1 and y1 (maybe y0 = y1); xmin, ymin, xmax, and ymax can also be extracted with the RasterPropertiesExtractor.

 

 

Then, the scale (ratio of expanding or shrinking) can be calculated with this expression. Probably the vertical scale is equal to the horizontal scale in this case, but this method can also be applied to the case where those scales are different. 

 

scale_x = (5000 - 0) / (x1 - x0)

 

scale_y = scale_x

 

 

Since the red dot (x0, y0) should be located at the origin (0, 0) in the destination coordinate system, the lower-left/upper-right coordinates in the destination CS can be calculated like this.

 

xmin_dest = (xmin - x0) * scale_x

 

ymin_dest = (ymin - y0) * scale_y

 

xmax_dest = (xmax - x0) * scale_x

 

ymax_dest = (ymax - y0) * scale_y

 

 

And then, the parameters for the RasterGeoreferencer (Parameter Type: Extents) can be set like this.

 

X/Y Upper Left: xmin_dest/ymax_dest

 

X/Y Upper Right: xmax_dest/ymax_dest

 

X/Y Lower Right: xmax_dest/ymin_dest

 

X/Y Lower Left: xmin_dest/ymin_dest

 

 

Another approach.

 

I think that two Offsetters and one Scaler can also do that in this case.

 

1) Offsetter

 

X Offset: -xmin

 

Y Offset: -ymin

 

2) Scaler

 

X: scale_x

 

Y: scale_y

 

Scale Origion: 0,0

 

3) Offseter

 

X Offset: (xmin - x0) * scale_x

 

Y Offset: (ymin - y0) * scale_y

 

 

Takashi
Badge
Hi Takashi,

 

    Thanks for your detailed response, it's good to see confirmation that I can scale it; the maths will be useful!

 

 

    The problem is that the red and yellow points aren't in corners. They're kind of in the middle, the exact position varies slightly between images.

 

    

 

    The rasters are about 500*500.

 

    - The red dot is usually around the middle: x200, y200 (give or take).

 

    - The yellow dot is to the right of it - say x300, y200 (give or take).

 

 

    See the below for a (hand-drawn) example; the blue areas are the data (can be anywhere, any size/shape).

 

 

 

 

 

 

I wonder if this is possible? Do you (or anyone?) have any thoughts?

 

Thanks,

 

Jonathan
Userlevel 2
Badge +17
Yes, therefore, the expressions I posted will adjust the coordinates, so that the red dot (middle in the original raster) will be located at the origin of the destination CS.

 

Aren't the expressions correct?
Userlevel 2
Badge +17
... ah, you perhaps don't have (x0, y0), (x1, y1) as coordinate values yet? You can calculate them based on raster properties extracted by the RasterPropertiesExtractor.

 

x0 = _xmin + <column number of red dot> * _spacing_x

 

y0 = _ymin + <row number of red dot> * _spacing_y

 

x1 = _xmin + <column number of yellow dot> * _spacing_x

 

y1 = _ymin + <row number of yellow dot> * _spacing_y

 

 

Try assigning the resulting values into the expressions.

 

Userlevel 2
Badge +17
If the row number is increasing in the direction from top to bottom of the raster:

 

y0 = _ymax - <row number of red dot> * _spacing_y

 

y1 = _ymax - <row number of yellow dot> * _spacing_y
Badge

Hi Takashi,

 

Thanks for the answers, they inspired me to take a look at a home-brew solution.

 

Mine's a lot simpler than yours, which makes me suspect its validity, but the output seems sound.

 

 

Basically, I've got two transformers:

 

 

1)

Offsetter.

 

X - Offseting by the value of negative X_RED

 

Y - Offseting by the value of negative Y_RED

 

 

This places the red dot at 0,0.

 

 

2)

I then use a Scaler, which has the same scale factors for X and Y, and am scaling around 0,0 (the red dot).

 

 

The equation for the scaler is:

 

200 / (@Value(_x_yellow)-@Value(_x_red))

 

 

(where 200 is an arbitrary value, but should be the approx average number of pixels between the two dots; the idea is to minimise data loss).

 

 

On the surface at least this seems to work. Can you see anything wrong with that? I'm always suspicious when I come up with an "easy solution". :-)

 

Thanks again for the insights.

 

Jonathan
Userlevel 2
Badge +17
Oh, that's elegant. No, I cannot see anything wrong in your solution.

 

Sometimes, a flash of inspiration solves seemingly difficult problem suddenly :)

Reply