IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ticket #311: stacTransform.c

File stacTransform.c, 8.1 KB (added by Paul Price, 21 years ago)

Demonstration of PS_INTERPOLATE_BILINEAR_VARIANCE

Line 
1#include <stdio.h>
2#include "pslib.h"
3#include "stac.h"
4
5#define SQUARE(x) ((x)*(x))
6#define MIN(x,y) (((x) > (y)) ? (y) : (x))
7#define MAX(x,y) (((x) > (y)) ? (x) : (y))
8
9#define MAXCHAR 80
10
11static int numTransforms = 0; // Number of transformations performed
12
13
14// Hacked the original ps_ImagePixelInterpolateBILINEAR_F32 to add variances
15// i.e., to square the fractions when combining.
16inline psF64 p_psImageErrorInterpolateBILINEAR_F32(const psImage* input,
17 float x,
18 float y,
19 const psImage* mask,
20 unsigned int maskVal,
21 psF64 unexposedValue)
22{
23 double floorX = floor((psF64)(x) - 0.5);
24 double floorY = floor((psF64)(y) - 0.5);
25 psF64 fracX = x - 0.5 - floorX;
26 psF64 fracY = y - 0.5 - floorY;
27 int intFloorX = (int) floorX;
28 int intFloorY = (int) floorY;
29 int lastX = input->numCols - 1;
30 int lastY = input->numRows - 1;
31 psF32 V00;
32 psF32 V01;
33 psF32 V10;
34 psF32 V11;
35 bool valid00 = false;
36 bool valid01 = false;
37 bool valid10 = false;
38 bool valid11 = false;
39
40 if (intFloorY >= 0 && intFloorY <= lastY) {
41 if (intFloorX >= 0 && intFloorX <= lastX) {
42 V00 = input->data.F32[intFloorY][intFloorX];
43 valid00 = true;
44 }
45 if (intFloorX >= -1 && intFloorX < lastX) {
46 V10 = input->data.F32[intFloorY][intFloorX+1];
47 valid10 = true;
48 }
49 }
50 if (intFloorY >= -1 && intFloorY < lastY) {
51 if (intFloorX >= 0 && intFloorX <= lastX) {
52 V01 = input->data.F32[intFloorY+1][intFloorX];
53 valid01 = true;
54 }
55 if (intFloorX >= -1 && intFloorX < lastX) {
56 V11 = input->data.F32[intFloorY+1][intFloorX+1];
57 valid11 = true;
58 }
59 }
60
61 /* cover likely case of all pixels being valid more efficiently */
62 if (valid00 && valid10 && valid01 && valid11) {
63 /* formula from the ADD */
64 return V00*SQUARE((1.0-fracX)*(1.0-fracY)) + V10*SQUARE(fracX*(1.0-fracY)) +
65 V01*SQUARE(fracY*(1.0-fracX)) + V11*SQUARE(fracX*fracY);
66 }
67
68 /* OK, at least one pixel is not valid - need to do it piecemeal */
69
70 psF64 V0;
71 bool valid0 = true;
72 if (valid00 && valid10) {
73 V0 = V00*SQUARE(1-fracX)+V10*SQUARE(fracX);
74 } else if (valid00) {
75 V0 = V00;
76 } else if (valid10) {
77 V0 = V10;
78 } else {
79 valid0 = false;
80 }
81
82 psF64 V1;
83 bool valid1 = true;
84 if (valid01 && valid11) {
85 V1 = V01*SQUARE(1-fracX)+V11*SQUARE(fracX);
86 } else if (valid01) {
87 V1 = V01;
88 } else if (valid11) {
89 V1 = V11;
90 } else {
91 valid1 = false;
92 }
93
94 if (valid0 && valid1) {
95 return ( V0*SQUARE(1-fracY) + V1*SQUARE(fracY) );
96 } else if (valid0) {
97 return V0;
98 } else if (valid1) {
99 return V1;
100 }
101
102 return unexposedValue;
103}
104
105
106
107bool stacTransform(psArray **outputs, // Transformed images for output
108 psArray **outErrors, // Transformed error images for output
109 const psArray *images, // Array of images to be transformed
110 const psArray *maps, // Array of polynomials that do the transformation
111 const psArray *errors, // Array of error images to be transformed
112 const psArray *masks, // Masks of input images
113 const psImage *region, // Region of interest for transformation
114 const stacConfig *config // Configuration
115 )
116{
117 int nImages = images->n; // Number of images
118 int nx = config->outnx, ny = config->outny; // Size of output images
119 numTransforms++;
120
121 // Check input sizes
122 if (images->n != maps->n) {
123 psError("stac.transform", "Number of maps (%d) does not match number of images (%d).\n",
124 maps->n, images->n);
125 return false;
126 }
127 if (errors && (images->n != errors->n)) {
128 psError("stac.transform", "Number of error images (%d) does not match number of images (%d).\n",
129 errors->n, images->n);
130 return false;
131 }
132
133 // Allocate the output images if required, otherwise check the number
134 if (*outputs == NULL) {
135 *outputs = psArrayAlloc(nImages);
136 psTrace("stac.transform", 5, "Allocating space for transformed images, %dx%d\n", nx, ny);
137 for (int i = 0; i < nImages; i++) {
138 (*outputs)->data[i] = psImageAlloc(nx, ny, PS_TYPE_F32);
139 }
140 } else if ((*outputs)->n != nImages) {
141 psError("stac.transform", "Number of output images (%d) does not match number of input images "
142 "(%d).\n", (*outputs)->n, nImages);
143 return false;
144 }
145
146 // Allocate the output error images, if required, otherwise check the number
147 if (errors && (*outErrors == NULL)) {
148 *outErrors = psArrayAlloc(errors->n);
149 psTrace("stac.transform", 5, "Allocating space for transformed error images, %dx%d\n", nx, ny);
150 for (int i = 0; i < nImages; i++) {
151 (*outErrors)->data[i] = psImageAlloc(nx, ny, PS_TYPE_F32);
152 }
153 } else if (errors->n != (*outErrors)->n) {
154 psError("stac.transform", "Number of error output images (%d) does not match number of input"
155 "images (%d).\n", (*outErrors)->n, errors->n);
156 return false;
157 }
158
159 // Check the masks, if specified
160 if (masks != NULL) {
161 if (masks->n != nImages) {
162 psError("stac.transform", "Number of masks (%d) does not match number of input images (%d).\n",
163 masks->n, nImages);
164 return false;
165 }
166 for (int i = 0; i < nImages; i++) {
167 psImage *image = images->data[i];
168 psImage *mask = masks->data[i];
169 if ((mask->numRows != image->numRows) || (mask->numCols != image->numCols)) {
170 psError ("stac.transform",
171 "Size of input mask (%dx%d) does not match that of input image (%dx%d).\n",
172 mask->numCols, mask->numRows, image->numCols, image->numRows);
173 return false;
174 }
175 }
176 }
177
178
179 // Stuff for the transformations
180 psPlane *detector = psAlloc(sizeof(psPlane)); // Coordinates on the detector
181 psPlane *sky = psAlloc(sizeof(psPlane)); // Coordinates on the sky
182
183
184 // Iterate over the images
185 for (int n = 0; n < nImages; n++) {
186 psTrace("stac.transform", 1, "Transforming image %d....\n",n);
187
188 // Pull out the various stuff we're working on
189 psImage *image = images->data[n]; // The input image
190 psPlaneTransform *map = maps->data[n]; // The map
191 psImage *error = errors->data[n]; // The error image
192 psImage *outImage = (*outputs)->data[n]; // The output image
193 psImage *outError = (*outErrors)->data[n]; // The output error image
194
195#if 0
196 // No need for initialisation, since we iterate over the entire output image.
197 for (int y = 0; y < ny; y++) {
198 for (int x = 0; x < nx; x++) {
199 outImage->data.F32[y][x] = 0.0;
200 outError->data.F32[y][x] = 0.0;
201 }
202 }
203#endif
204
205 // Mask
206 psImage *mask = NULL;
207 if (masks != NULL) {
208 mask = masks->data[n];
209 }
210
211 // Iterate over the output image pixels
212 for (int y = 0; y < ny; y++) {
213 for (int x = 0; x < nx; x++) {
214
215 // Only transform those pixels requested
216 if (!region || (region && region->data.U8[y][x])) {
217 // Transform!
218 sky->x = (double)x + 0.5;
219 sky->y = (double)y + 0.5;
220 (void)psPlaneTransformApply(detector, map, sky);
221
222 // Change PS_INTERPOLATE_BILINEAR to best available technique.
223 outImage->data.F32[y][x] = (psF32)psImagePixelInterpolate(image, detector->x + 0.5,
224 detector->y + 0.5, mask, 1, 0.0,
225 PS_INTERPOLATE_BILINEAR);
226 // Error is actually the variance
227 outError->data.F32[y][x] = (psF32)p_psImageErrorInterpolateBILINEAR_F32(error,
228 detector->x + 0.5,
229 detector->y + 0.5,
230 mask, 1, 0.0);
231 } // Pixels of interest
232
233 }
234 } // Iterating over output pixels
235
236#ifdef TESTING
237 // Write error image out to check
238 char shiftfile[MAXCHAR]; // Filename of shift image
239 char errfile[MAXCHAR]; // Filename of error image
240 sprintf(shiftfile,"%s.shift.%d",config->inputs->data[n],numTransforms);
241 sprintf(errfile,"%s.shifterr.%d",config->inputs->data[n],numTransforms);
242 psTrace("stac.transform.test", 6,
243 "Output files have size: %dx%d\n",outImage->numCols,outImage->numRows);
244 psImageWriteSection(outImage,0,0,0,NULL,0,shiftfile);
245 psImageWriteSection(outError,0,0,0,NULL,0,errfile);
246#endif
247
248 } // Iterating over images
249
250 // Done with transformations
251 psFree(detector);
252 psFree(sky);
253
254 return true;
255}
256