During bilinear interpolation, cubic convolution and sin(x)/x, the last pixel and/or scanline will be reused to produce the grey level values for the georeferenced image if the uncorrected pixel window used to calculate the corrected matrix grey level value falls outside the bounds of the uncorrected image at its corner edges. This reuse of pixel values can have the effect of producing image edges which are darker or lighter than the interior of the image.
In GCPWorks, the Resampling type can be set in the ``Disk to Disk Registration'', or the ``Pre-registration Checking'' panel.
See Also: Pre-Registration Checking, Disk to Disk Registration
Nearest neighbour interpolation introduces a small error into the newly registered image. The image may be offset spatially by up to 1/2 a pixel, causing a jagged or blocky appearance if there is much rotation or scale change.
1. For a given pixel and scanline, transform from the CENTRE of the pixel and scanline. For example, for output pixel 10, scanline 13, transform from the centre (i.e. pixel 9.5, line 12.5). For this discussion, output pixel 9.5, line 12.5 gets transformed to input pixel 0.7, line 1.2.
2. Round up the resulting decimal transformed pixel, line by 1/2 an input pixel and 1/2 an input scanline.
Rounded transformed pixel = 0.7 + 0.5 = 1.2 Rounded transformed line = 1.2 + 0.5 = 1.73. Drop the fractional part from the rounded pixel, line from step 2 to determine the input pixel, scanline. This pixel, scanline will be be noted as "X" in the following diagrams.
Truncated integer pixel = 1 Truncated integer line = 14. If the truncated pixel, line from Step 3 is outside the input image dimensions no further processing is required for the output pixel, so go back to Step 1 to process the next pixel of the output scanline.
If the truncated pixel, scanline from Step 3 lies within the input image, continue on to Step 5 for further processing.
5. Save the fractional part of the rounded pixel, line as the "distances":
Xdistance = (Rounded transformed pixel from Step 2) - (Truncated integer pixel from Step 3) = 1.2 - 1 = 0.2 Ydistance = (Rounded transformed line from Step 2) - (Truncated integer line from Step 3) = 1.7 - 1 = 0.7These distances will be in the range of 0.0 to less than +1.0. (A distance +1.0 or more would have selected an adjacent pixel and/or scanline.)
6. Read the input scanline and as many adjacent scanlines as required by the size of the resampling kernel, if they have not been read already and are residing in memory. If the adjacent scanlines are outside the bounds of the input image reuse the most appropriate pixels and/or scanlines. For example for Cubic Convolution resampling (a 4 x 4 resampling kernel)
-1 0 1 2 +---+---+---+---+ -1 | | | | | +---+---+---+---+ 0 | | X | | | +---+---+---+---+ 1 | | | | | +---+---+---+---+ 2 | | | | | +---+---+---+---+for input pixel 1, line 1 (from Step 3), scanline 1 would be used for row 0 of the resampling kernel and reused for row -1. Row 1 of the resampling kernel would use input scanline 2. Row 2 of the resampling kernel would use input scanline 3.
As the pixels in column -1 are outside the image, the pixels from column 0 are reused for column -1.
The effect of reusing pixels and/or scanlines at the edges may show as a darkening (or lightening) of the output imagery at those columns and/or scanlines. Effectively it is giving a stronger weighting to those grey-levels in the resampling kernel.
NOTE: In the following descriptions the resampling is shown as a function. In the actual code, these functions are not used but are coded in an expanded form.
REFERENCE: John A. Richards, 1986: "Remote Sensing Digital Image Analysis, An Introduction", New York, Springer-Verlag, pages 52-55.
Nearest Neighbour
Resampling kernel (k) has the dimensions 1
pixel by 1 scanline.
0 +---+ 0 | X | +---+Process for the resample window:
output = NearestNeighbour( k[0,0] )Where the resampling function is:
NearestNeighbour( f0 ) { return( f0 ); }
0 1 +---+---+ 0 | X | | +---+---+ 1 | | | +---+---+Process for the resample window:
row[0] = BilinearInterpolation( (1.0 - Xdistance), k[0,0], Xdistance , k[0,1] ) row[1] = BilinearInterpolation( (1.0 - Xdistance), k[1,0], Xdistance , k[1,1] )
output = BilinearInterpolation( (1.0 - Ydistance), row[0], Ydistance , row[1] )Where the resampling function is:
BilinearInterpolation( distance0, f0, distance1, f1 ) { return( f0 * distance0 + f1 * distance1 ); }
-1 0 1 2 +---+---+---+---+ -1 | | | | | +---+---+---+---+ 0 | | X | | | +---+---+---+---+ 1 | | | | | +---+---+---+---+ 2 | | | | | +---+---+---+---+Process for the resample window:
row[-1] = CubicConvolution(Xdistance,k[-1,-1],k[-1,0],k[-1,1],k[-1,2]) row[ 0] = CubicConvolution(Xdistance,k[ 0,-1],k[ 0,0],k[ 0,1],k[ 0,2]) row[ 1] = CubicConvolution(Xdistance,k[ 1,-1],k[ 1,0],k[ 1,1],k[ 1,2]) row[ 2] = CubicConvolution(Xdistance,k[ 2,-1],k[ 2,0],k[ 2,1],k[ 2,2])
output = CubicConvolution(Ydistance,row[-1],row[ 0],row[ 1],row[ 2])Where the resampling function is:
CubicConvolution( distance, f0, f1, f2, f3 ) { return( ( -f0 + f1 - f2 + f3) * distance**3 + (2.0*f0 - 2.0*f1 + f2 - f3) * distance**2 + ( -f0 + f2 ) * distance**1 + f1 ); }NOTE: A distance of 0.0 would zero the distance**3, distance**2 and distance**1 terms, in which case f1 would be returned as is.